搭建React源码调试环境
写在前面
- React源码版本:V17.0.2
- 日期:2021-3-16 17:17:17
- create-react-app 搭建
参考:
https://github.com/nannongrousong/blog/issues/1
https://github.com/bubucuo/DebugReact
1. 搭建项目
npx create-react-app debug-react cd debug-react npm run eject
2. 克隆源码 v17.0.2
git clone https://github.com/facebook/react.git
3. 将源码放在 src 目录下 debug-react/src
4. 修改 webpack alias 配置文件 debug-react/config/webpack.config.js
resolve: { alias: { 'react-native': 'react-native-web', 'react': path.resolve(__dirname, '../src/react/packages/react'), 'react-dom': path.resolve(__dirname, '../src/react/packages/react-dom'), 'shared': path.resolve(__dirname, '../src/react/packages/shared'), 'react-reconciler': path.resolve(__dirname, '../src/react/packages/react-reconciler'), } }
启动项目,根据提示修改以下配置
5. 配置webpack和eslint中的全局变量
修改/config/env.js:
const stringified = { // 保留原有配置..., "__DEV__": true, "__PROFILE__": true, "__UMD__": true };
根目录下新建.eslintrc.json文件:
{ "extends": "react-app", "globals": { "__DEV__": true, "__PROFILE__": true, "__UMD__": true } }
6. 修改源码内文件:
/src/react/.eslintrc.js
将 `extends: []` 数组置空 删掉 `/src/react/.eslintrc.js` 文件中所有 `no-for-of-loops`, `no-function-declare-after-return`。 在 `/src/react/` 下搜索 `react-internal`,把包含 `react-internal` 的`注释行`和`代码行`全部删掉。
/src/react/packages/react-reconciler/src/ReactFiberHostConfig.js
// 注释掉 // import invariant from 'shared/invariant'; // invariant(false, 'This module must be shimmed by a specific renderer.'); // 添加此行 export * from "./forks/ReactFiberHostConfig.dom";
/src/react/packages/shared/ReactSharedInternals.js
// 注释掉 /* import * as React from 'react'; const ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; */ // 添加此行 import ReactSharedInternals from '../react/src/ReactSharedInternals'; export default ReactSharedInternals;
/src/react/packages/shared/invariant.js
export default function invariant(condition, format, a, b, c, d, e, f) { // 添加此行 if (condition) return; throw new Error( "Internal React error: invariant() is meant to be replaced at compile " + "time. There is no runtime version." ); }
在 /src/react/packages/react-dom/src/client
下新建 util.js
文件
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ export const isPrimaryRenderer = true; export const warnsIfNotActing = true; // This initialization code may run even on server environments // if a component just imports ReactDOM (e.g. for findDOMNode). // Some environments might not have setTimeout or clearTimeout. export const scheduleTimeout: any = typeof setTimeout === 'function' ? setTimeout : (undefined: any); export const cancelTimeout: any = typeof clearTimeout === 'function' ? clearTimeout : (undefined: any); export const noTimeout = -1; // ------------------- // Microtasks // ------------------- export const supportsMicrotasks = true; export const scheduleMicrotask: any = typeof queueMicrotask === 'function' ? queueMicrotask : typeof Promise !== 'undefined' ? callback => Promise.resolve(null) .then(callback) .catch(handleErrorInNextTick) : scheduleTimeout; // TODO: Determine the best fallback here. function handleErrorInNextTick(error) { setTimeout(() => { throw error; }); } export const supportsMutation = true; export const supportsHydration = true; export const supportsTestSelectors = true;
然后在 /src/react/packages/react-dom/src/client/ReactDOMHostConfig.js
中找到 所有在 util.js
中定义的常量 并删除掉, 最后在末尾导出 util.js
。
export * from './util';