### 前言 如果不想麻烦,可以直接在[我的git地址][1]中克隆项目至本地,使用`npm i`安装依赖包,然后`npm run start`启动即可。大 TODO:大白话讲React原理目录: ### 创建 React17 项目 #### 先使用官方脚手架`create-react-app`创建项目 ``` npx create-react-app learn-react-source-code ``` #### 降级 React 版本 我们需要把 React 版本从 18 降到 17 。 ``` "@testing-library/react": "^12.1.5", "react": "^17.0.2", "react-dom": "^17.0.2", ``` ![构建2.jpg][2] #### 修改src/index.js ``` import React from "react"; import ReactDOM from "react-dom"; import "./index.css"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; const root = document.getElementById("root"); ReactDOM.render( , root ); ``` ![构建3.jpg][3] #### 尝试运行项目 **删除**根目录下`package-lock.json`,重新安装依赖 `npm i` ,最后 `npm run start`。 此时应该能成功运行项目了,但是目前开发者工具`sources`面板里文件还是打包后的react代码。 为了调试源码,我们还需要做以下步骤 ### 创建带源码的项目 #### 在 src 目录下,克隆 React17 源码 ``` cd src git clone https://github.com/facebook/react.git -b 17.0.2 ``` #### 根目录下,释放 webpack 配置 ``` npm run eject or yarn eject ``` 因为此时 `webpack` 配置全部集成在`react-script`中,我们需要将他释放开来,让我们自己配置 `webpack` 。 命令执行完毕后在新增的 `config` 文件夹下可以看到 `webpack` 的配置文件: ![构建8.jpg][4] #### 根目录下,配置 webpack 使其引用源码 往`config/webpack.config.js` 添加 `alias` ``` // ./config/webpack.config.js ... alias: { ... ...(modules.webpackAliases || {}), + 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" ), + scheduler: path.resolve(__dirname, "../src/react/packages/scheduler"), }, ``` ![构建5.jpg][5] #### 关闭 EsLint ``` // ./config/webpack.config.js ... const disableESLintPlugin = true; ``` ![构建4.jpg][6] #### `config/env.js`添加环境变量 ``` // ./config/env.js ... // Stringify all values so we can feed into webpack DefinePlugin const stringified = { + __DEV__: true, + __PROFILE__: true, + __UMD__: true, + __EXPERIMENTAL__: true, "process.env": Object.keys(raw).reduce((env, key) => { env[key] = JSON.stringify(raw[key]); return env; }, {}), }; ``` ![构建6.jpg][7] #### 修改index.js中 react 和 react-dom 的引入 ``` import * as React from "react"; import * as ReactDOM from "react-dom"; ``` ![构建7.jpg][8] #### 修改报错文件 可以直接[参考此次Commit][9] 如果此时尝试运行项目,webpack会告诉你有 300 多个错误,不要怕,我们马上解决。 `webpack compiled with 336 errors` ##### 1. ./src/react/packages/scheduler/index.js ``` // 添加 export { unstable_flushAllWithoutAsserting, unstable_flushNumberOfYields, unstable_flushExpired, unstable_clearYields, unstable_flushUntilNextPaint, unstable_flushAll, unstable_yieldValue, unstable_advanceTime } from './src/SchedulerHostConfig.js'; ``` ![构建9.jpg][10] ##### 2. ./src/react/packages/shared/invariant.js ``` // 添加 if (condition) { return; } ``` ![构建10.jpg][11] ##### 3. ./src/react/packages/react-reconciler/src/RectFiberHostConfig.js ``` // 注释文件并在最后导出 export * from './forks/ReactFiberHostConfig.dom'; ``` ![构建11.jpg][12] ##### 4. ./src/react/packages/shared/RectSharedInternals.js ``` // 注释文件并添加导入 import ReactSharedInternals from '../react/src/ReactSharedInternals' ``` ![构建12.jpg][13] ##### 5. ./src/react/packages/scheduler/src/SchedulerFeatureFlags.js ``` // 修改 export const enableProfiling = true; ``` ![构建13.jpg][14] ##### 6. ./src/react/packages/scheduler/src/SchedulerHostConfig.js ``` // 注释文件并添加 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'; ``` ![构建14.jpg][15] ### 运行项目 此时使用`npm run start`就可以正常运行项目了,通过`debugger`或者`console.log`我们就可以开始调试源码啦。 比如 ![构建1.jpg][16] [1]: https://github.com/232295311/learn-react-source-code [2]: http://120.25.166.245/usr/uploads/2024/03/3108046133.jpg [3]: http://120.25.166.245/usr/uploads/2024/03/2342834140.jpg [4]: http://120.25.166.245/usr/uploads/2024/03/1752848700.jpg [5]: http://120.25.166.245/usr/uploads/2024/03/2043372383.jpg [6]: http://120.25.166.245/usr/uploads/2024/03/3085103012.jpg [7]: http://120.25.166.245/usr/uploads/2024/03/631557534.jpg [8]: http://120.25.166.245/usr/uploads/2024/03/1656241588.jpg [9]: https://github.com/232295311/learn-react-source-code/commit/c968ffd285bd02e45bbfc708ba85279c1590c581 [10]: http://120.25.166.245/usr/uploads/2024/03/387793252.jpg [11]: http://120.25.166.245/usr/uploads/2024/03/3662571732.jpg [12]: http://120.25.166.245/usr/uploads/2024/03/1142517594.jpg [13]: http://120.25.166.245/usr/uploads/2024/03/2628396643.jpg [14]: http://120.25.166.245/usr/uploads/2024/03/2433840008.jpg [15]: http://120.25.166.245/usr/uploads/2024/03/2242156174.jpg [16]: http://120.25.166.245/usr/uploads/2024/03/2318368381.jpg 最后修改:2024 年 03 月 14 日 01 : 17 PM © 著作权归作者所有 赞赏 如果觉得我的文章对你有用,请随意赞赏 ×Close 赞赏作者 扫一扫支付 支付宝支付 微信支付
作者以非凡的视角解读平凡,让文字焕发出别样的光彩。
独特的构思和新颖的观点,让这篇文章在众多作品中脱颖而出。
?总结与建议类?
你的文章让我心情愉悦,真是太棒了! http://www.55baobei.com/Xf4xeGaDfS.html
你的文章让我心情愉悦,真是太棒了! http://www.55baobei.com/a1SUly80Eb.html
你的文章让我感受到了生活的美好,谢谢! https://www.yonboz.com/video/40709.html