build怎么调试 react_搭建本地React源码调试环境

本文介绍了如何直接使用React源码包进行调试,通过创建一个新项目,eject配置,克隆特定版本的React源码,并修改Webpack配置,环境变量,忽略Flow类型,解决事件冲突,导出HostConfig,关闭ESLint对fbjs的扩展,以及配置VSCode。最后,通过设置断点进行测试,确保源码调试环境搭建成功。
摘要由CSDN通过智能技术生成

一般来说,我们想要去学习 React 的源码的时候,可能会先Build一下,然后使用源码包下的fixtures内的测试样例进行调试,但是,不管是production的build还是Development的build,源码都是被打包在一个文件中的,结构混乱,即使代码没有被压缩,也很难看得懂具体那一个方法是属于哪一个模块的。所以,为何不使用源码包直接来调试源代码呢?

本文将会介绍如何直接使用React源码包来调试源码。

创建一个项目1create-react-app reading_source

其中,reading_source是自己起的名字,你也可以使用自己的名字。1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22Creating a new React app in ./reading_source.

Installing packages. This might take a couple of minutes.

Installing react, react-dom, and react-scripts with cra-template...

yarn add v1.19.2

[1/4] 🔍 Resolving packages...

[2/4] 🚚 Fetching packages...

[3/4] 🔗 Linking dependencies...

[4/4] 🔨 Building fresh packages...

[1/4] ⡀ fsevents

...(省略)

...(省略)

...(省略)

We suggest that you begin by typing:

cd reading_source

yarn start

Happy hacking!

这个时候,我们就创建好了一个空白的项目,最好之前可以启动一下:1

2cd reading_source

yarn start

此时会自动打开一个页面,显示下面的样子,说明,我们的项目创建成功了。

Eject 配置

因为我们需要对项目中的依赖进行自定义配置,所以,我们需要暴露出 React 项目的配置文件,执行:1$ yarn eject

我们就会得到 React 项目的配置文件以及一些构建脚本:

克隆 React 源码

克隆一个指定版本的 React 源码,到src/react目录下,当然这里也可以使用master分支,但是不建议。如果你需要将你自己对代码的修改保存到版本控制中,你最好自己fork一份React官方的repo,到自己的账号。话说 github 是在是太慢了,所以,我fork了一份,到我的github仓库,然后,强制同步到了gitee仓库了。

我选择的分支是16.8.6,截止发稿日期的最新版本。1git clone git@gitee.com:cyrusky/react.git -b 16.8.6 src/react

开始修改配置

webpack 中将包链接到源代码

修改/config/webpack.config.js1

2

3

4

5

6

7

8

9

10resolve: {

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'),

'react-events': path.resolve(__dirname, '../src/react/packages/events')

}

}需要注意的一点是:react-events在master分支中已经变更为legacy-events了,不需要在此处添加了。

修改环境变量

修改/config/env.js1

2

3

4

5

6

7

8

9const stringified = {

__DEV__: true,

__PROFILE__: true,

__UMD__: true,

'process.env': Object.keys(raw).reduce((env, key) => {

env[key] = JSON.stringify(raw[key])

return env

}, {})

}

根目录创建.eslintrc.json文件1

2

3

4

5

6

7

8{

"extends": "react-app",

"globals": {

"__DEV__": true,

"__PROFILE__": true,

"__UMD__": true

}

}

忽略 flow 下 type1$ yarn add @babel/plugin-transform-flow-strip-types -D

同时在/config/webpack.config.js中babel-loader的plugins中添加该插件1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32{

test: /\.(js|mjs|jsx|ts|tsx)$/,

include: paths.appSrc,

loader: require.resolve('babel-loader'),

options: {

customize: require.resolve(

'babel-preset-react-app/webpack-overrides'

),

plugins: [

+ require.resolve('@babel/plugin-transform-flow-strip-types'),

[

require.resolve('babel-plugin-named-asset-import'),

{

loaderMap: {

svg: {

ReactComponent:

'@svgr/webpack?-svgo,+titleProp,+ref![path]'

}

}

}

]

],

// This is a feature of `babel-loader` for webpack (not Babel itself).

// It enables caching results in ./node_modules/.cache/babel-loader/

// directory for faster rebuilds.

cacheDirectory: true,

// See #6846 for context on why cacheCompression is disabled

cacheCompression: false,

compact: isEnvProduction

}

},就是避免这个错误:1

2

3

4

5

6

7

8

9

10

11

12Failed to compile.

./src/react/packages/react-dom/src/client/ReactDOM.js

SyntaxError: ./reading_source/src/react/packages/react-dom/src/client/ReactDOM.js: Unexpected token (10:12)

8 | */

9 |

> 10 | import type {ReactNodeList} from 'shared/ReactTypes';

| ^

11 | // TODO: This type is shared between the reconciler and ReactDOM, but will

12 | // eventually be lifted out to the renderer.

13 | import type {

解决 event 冲突(master 分支请忽略)

在webpack.config.js中的alias中添加react-events后,需要修改react源码包中相应引用event的部分,具体如下:替换源码中所有的import XXX from 'events/...'为import XXX from 'react-events/...',其中react-events就是alias中的命名。

导出 HostConfig

修改文件/src/react/packages/react-reconciler/src/ReactFiberHostConfig.js。注释中说明,这块还需要根据环境去导出HostConfig。1

2// invariant(false, 'This module must be shimmed by a specific renderer.');

export * from './forks/ReactFiberHostConfig.dom'

保持 import first,根据编译信息修改

修改文件/src/react/packages/shared/ReactSharedInternals.js。react此时未export内容,直接从ReactSharedInternals拿值1

2

3

4// import React from 'react';

import ReactSharedInternals from '../react/src/ReactSharedInternals'

// const ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;

关闭 ESlint 对 fbjs 插件的扩展

修改src/react/.eslingrc.js,在module.exports中删去extends: 'fbjs':1

2

3module.exports = {

// extends: 'fbjs',

......

vscode 配置

安装flowtype.flow-for-vscode插件:

进行配置,一般来说,我们只会在看源码的时候用到flow,所以我们将配置写在workspace的配置文件下:

测试

至此,我们的源码调试环境就搭建完毕了。我们可以测试一下:

我们修改一下src/react/packages/react-dom/src/client/ReactDOMComponents.js中的createElement,添加一个断点:1

2

3

4

5

6

7

8

9export function createElement(

type: string,

props: Object,

rootContainerElement: Element | Document,

parentNamespace: string,

): Element{

debugger

let isCustomComponentTag;

......

一般来说,如果你操作了yarn start,在修改代码后,会热加载。所以,如果你的development tools是打开的,这个时候,应该就可以停在断点处了,具体如下:

来愉快的进行调试把!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值