本地调试React源码

2023-05-25 0 323

[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 git@github.com: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

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务