[TOC]
工欲善其事,工欲善其事。
在自学raect源代码时,假如能在应用程序中Bareli增容,势必增进认知。只不过能借助于webpack的resolve.alias将react等对准邻近地区的产品目录,这种就不能采用node_modules中的react包。 进而能在邻近地区增容react源代码。
邻近地区增容react源代码关键步骤
1. 聚合react工程项目
能间接如前所述react cra cli聚合工程项目,也能他们如前所述react,webpack构筑自然环境,具体内容能参照https://github.com/bozhouyongqi/react-redux-demo工程项目。前述主要就特别针对采用cra的工程项目。
2. yarn run eject 折射出webpack实用性
这一步棋没无所谓,能看见会聚合config产品目录,里头主要就包括webpack的命令行和许多自然环境表述。但很意外,运转yarn run start会校对失利。再次出现前述严重错误。
Failed to compile.
./src/index.js
Error: [BABEL] /xxx/debug-react-new/src/index.js: Cannot find module @babel/plugin-syntax-jsx (While processing: “xxx/debug-react-new/node_modules/babel-preset-react-app/index.js”)
原意是缺乏@babel/plugin-syntax-jsx那个组件,那间接加装xml。
yarn add @babel/plugin-syntax-jsx -D
后再运转,就能成功开启工程项目了。
Compiled successfully!
You can now view debug-react-new in the browser.
Local: http://localhost:3000
On Your Network: http://192.168.0.103:3000
Note that the development build is not optimized.
To create a production build, use yarn build.
3.清理src产品目录
删除测试以及其他文件,只保留App等业务组件。并去除相关引用。
4.clone react源代码至src产品目录下
这里采用git submodule命令引入react源代码作为子组件,以方便后续代码单独管理。
进入src产品目录,执行 git submodule add [email protected]:facebook/react.git。
克隆后,就能在src/react中正常切换分支,而不影响主工程。我这里采用v16.13.1版本,因此能切换至具体内容的tag.
git checkout tags/v16.13.1 -b v16.13.1
5.修改webpack.config.js添加alias实用性
注释掉原先的alias实用性,添加新的,将react等对准邻近地区
alias: {
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),
“legacy-events”: path.resolve(__dirname, “../src/react/packages/legacy-events”),
// react-events: path.resolve(__dirname, ../src/react/packages/events),
// scheduler: path.resolve(__dirname, “../src/react/packages/scheduler”),
},
然后再运转工程项目,发现会再次出现如下严重错误。
Failed to compile.
./src/packages/react-reconciler/src/ReactFiberDeprecatedEvents.js
Attempted import error: DEPRECATED_mountResponderInstance is not exported from ./ReactFiberHostConfig.
6.修改ReactFiberHostConfig文件
修改成如下
// We expect that our Rollup, Jest, and Flow configurations
// always shim this module with the corresponding host config
// (either provided by a renderer, or a generic shim for npm).
//
// We should never resolve to this file, but it exists to make
// sure that if we *do* accidentally break the configuration,
// the failure isnt silent.
// invariant(false, This module must be shimmed by a specific renderer.);
export * from ./forks/ReactFiberHostConfig.dom;
从注释中能看出,那个文件实际上react并不能间接引入,会被打包工具依赖相应的宿主自然环境替换掉。
后再开启工程项目,发现会报如下严重错误
Failed to compile.
./src/index.js
Attempted import error: react does not contain a default export (imported as React).
7.修改react引用方式
再次出现上述严重错误,到源代码中查看源代码,发现/debug-react-new/src/packages/react/index.js中确实没默认导出。但必须保证业务组件中要引入React,因为组件需要用babel-jsx插件进行转换(即采用React.createElement方法)。因此能添加一个中间组件文件,来适配该问题。
adaptation.js
import * as React from react;
import * as ReactDOM from react-dom;
export {
React,
ReactDOM
};
后在业务组件中从adaptation引入React和ReactDOM。
这一步棋后,还是会再次出现新严重错误。
Failed to compile.
Failed to load config “fbjs” to extend from.
Referenced from: /xxx/learn/debug-react-new/src/react/.eslintrc.js
8.关闭ESlint对fbjs,prettier插件的扩展
清空react源代码工程项目下.eslintrc文件中的extends选项
extends: [
fbjs,
prettier
],
改为extends:[]
依然会继续报错:
Failed to compile.
Failed to load plugin no-for-of-loops declared in src/react/.eslintrc.js: Cannot find module eslint-plugin-no-for-of-loops
Require stack:
– /xxx/learn/debug-react-new/config/__placeholder__.js
9.加装eslint-plugin-no-for-of-loops插件
yarn add eslint-plugin-no-for-of-loops -D
继续报错:
Failed to compile.
./src/react/packages/react-reconciler/src/ReactFiberWorkLoop.js
Attempted import error: unstable_flushAllWithoutAsserting is not exported from scheduler (imported as Scheduler).
10.修改scheduler/index.js文件
/src/react/packages/scheduler/index.js 修改为
use strict;
export * from ./src/Scheduler;
//添加以下
export {
unstable_flushAllWithoutAsserting,
unstable_flushNumberOfYields,
unstable_flushExpired,
unstable_clearYields,
unstable_flushUntilNextPaint,
unstable_flushAll,
unstable_yieldValue,
unstable_advanceTime
} from ./src/SchedulerHostConfig.js;
react/packages/scheduler/src/SchedulerHostConfig.js 修改为
// throw new Error(This module must be shimmed by a specific build.);
// 添加以下
export {
unstable_flushAllWithoutAsserting,
unstable_flushNumberOfYields,
unstable_flushExpired,
unstable_clearYields,
unstable_flushUntilNextPaint,
unstable_flushAll,
unstable_yieldValue,
unstable_advanceTime
} from ./forks/SchedulerHostConfig.mock.js;
export {
requestHostCallback,
requestHostTimeout,
cancelHostTimeout,
shouldYieldToHost,
getCurrentTime,
forceFrameRate,
requestPaint
} from ./forks/SchedulerHostConfig.default.js;
继续再次出现严重错误
Failed to compile.
Failed to load plugin react-internal declared in src/react/.eslintrc.js: Cannot find module eslint-plugin-react-internal
Require stack:
– /xxx/learn/debug-react-new/config/__placeholder__.js
11.解决react-internal严重错误
这是react在邻近地区加装的,在源代码的package中能看见。但加装后依然会报错,这里决定删除那个插件,不进行加装。在debug-react-new/src/react/.eslintrc.js 中的plugins中将其删除。
下面是加装邻近地区react-internals。笔者这里没加装,间接不采用该插件。
yarn add link:./src/react/scripts/eslint-rules -D
删除那个插件后,还是报错:
Failed to compile.
./src/index.js
Module not found: Cant resolve react/jsx-dev-runtime in /xxx/learn/debug-react-new/src
8-11中的严重错误都是react eslint中的严重错误,能试试在webpack.config.js中删除eslint插件。
12.修复react/jsx-dev-runtime报错
在webpack-config.js中能看见hasJsxRuntime变量的取值过程,间接在函数中返回false.
修改完后,会报许多react-internal有关的严重错误。
Line 1:1: Definition for rule react-internal/no-to-warn-dev-within-to-throw was not found react-internal/no-to-warn-dev-within-to-throw
Line 1:1: Definition for rule react-internal/invariant-args was not found react-internal/invariant-args
Line 1:1: Definition for rule react-internal/warning-args was not found react-internal/warning-args
Line 1:1: Definition for rule react-internal/no-production-logging was not found react-internal/no-production-logging
src/react/packages/react-dom/src/shared/validAriaProperties.js
Line 1:1: Definition for rule react-internal/no-primitive-constructors was not found react-internal/no-primitive-constructors
Line 1:1: Definition for rule react-internal/no-to-warn-dev-within-to-throw was not found react-internal/no-to-warn-dev-within-to-throw
Line 1:1:
能到/xxx/learn/debug-react-new/src/react/.eslintrc.js中将react-internal相关的规则都注释掉。
能看见会继续报如下严重错误:
Failed to compile.
src/react/packages/react-dom/src/client/ReactDOM.js
Line 241:9: Definition for rule react-internal/no-production-logging was not found react-internal/no-production-logging
src/react/packages/react-reconciler/src/ReactFiberHostConfig.js
Line 10:1: Definition for rule react-internal/invariant-args was not found react-internal/invariant-args
Line 12:8: invariant is defined but never used no-unused-vars
src/react/packages/react-reconciler/src/ReactFiberReconciler.js
Line 584:7: Definition for rule react-internal/no-production-logging was not found react-internal/no-production-logging
能到对应的文件中将eslint注释删除掉。
至此,命令行中不能报严重错误了。但应用程序中会报严重错误,提示DEV没表述。那个简单了,在DefinePlugin中表述xml。
13.设置DefinePlugin插件
在/xxx/learn/debug-react-new/config/env.js中添加:
const stringified = {
process.env: Object.keys(raw).reduce((env, key) => {
env[key] = JSON.stringify(raw[key]);
return env;
}, {}),
“__DEV__”: true,
“__PROFILE__”: true,
“__UMD__”: true,
“__EXPERIMENTAL__”: true
};
应用程序中还是会报错:
Uncaught Error: Internal React error: invariant() is meant to be replaced at compile time. There is no runtime version.
14.修改invariant.js
/xxx/debug-react-new/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.,
);
}
至此,大功告成,终于没严重错误了。后面就能特别针对源代码进行断点增容或者打日志了。
假如觉得构筑自然环境关键步骤比较麻烦,能在我的github中间接clone该工程项目debug-react。