超简单的 React 源码调试方法(v16.8.6)

841 阅读3分钟

一、前言

  你是否有这样的疑惑?明明代码写错了,却能正常的运行;你觉得代码写的是正确的,却报了个 error。你绞尽脑汁,发挥毕生之所学,却始终不得其解。
  来吧!调试源码吧!从源码的执行流程中,找到问题本质。

二、创建测试项目

  为了专注于源码调试,所以我从0到1创建一个webpack-dev项目。

// 开发环境:
os: win11 x64
node: v16.10.0
java: 11.0.18

1、初始化项目

  • npm init -y
  • pnpm add react@16.8.6 react-dom@16.8.6
  • pnpm add -D webpack webpack-cli webpack-dev-server
  • pnpm add -D @babel/core babel-loader html-webpack-plugin
  • pnpm add -D @babel/preset-env @babel/preset-react

然后,在package.json文件中增加一个命令:

"dev": "webpack serve"

2、创建一个src文件夹,下面建立index.js

import React, { useEffect } from 'react'
import ReactDom from 'react-dom'

function App() {
  useEffect(() => {
    console.log('useEffect')
  }, [])
  return <div>111</div>
}

ReactDom.render(<App />, document.getElementById('root'))

3、根目录下新增 webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  devServer: {
    port: 10001
  },
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              '@babel/preset-react'
            ]
          }
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'react',
      template: 'index.html'
    })
  ],
  // 取消入口文件大小限制
  performance: {
    hints: false
  },
}

4、根目录下新建index.html页面

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
</head>
<body>
  <div id="root"></div>
</body>
</html>

5、测试运行

执行:pnpm dev
结果如下:

1.png

三、调试源码

在当前目录下,使用git clone拉下来React的远程仓库代码。代码体积很大,约几百兆,需要稍微等一会儿。

1、切换到16.8.6的源码

cd react 进入源码目录,然后使用 git checkout -b 16.8.6 v16.8.6 命令,基于v16.8.6 这个tag创建自己的测试分支。

2、修改源码打包配置,以生成sourcemap

sourcemap 是用来映射编译后代码在源码中位置的文件。有了它,我们在调试时可以直接查看源代码。

下面,修改/scripts/rollup/build.js中文件:
滑到页面最底部,注释掉除了dev包之外的其他打包配置:

1.png

接下来,我们开启sourcemap:
找到getRollupOutputOptions函数位置,修改sourcemap: true

1.png

下面,我们还需要注释掉格式化代码的一些配置项,不然生成sourcemap过程中会报错。
找到getPlugins这个函数,注释掉下面的内容

1.png

1.png

1.png

好了,接下来,修改package.json文件中的 devEngines

1.png

然后执行:
yarn
yarn build

打包后文件存放在react/build下面。我们将要用到的是react-development.jsreact-dom-development.js这两个文件。

1.png

3、让测试项目引用源码构建的react、react-dom产物

我们回到根目录,修改webpack.config.js文件。

配置externals去避免打包时引入reactreact-dom
配置devServer下的static属性设置静态资源目录,映射到源码打包产物目录。

// webpack.config.js
...
  devServer: {
    port: 10001,
    static: path.join(__dirname, './react/build/node_modules')
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
  }
...

然后,记得修改index.html文件来引入react、react-dom。

  <script src="./react/umd/react.development.js"></script>
  <script src="./react-dom/umd/react-dom.development.js"></script>

运行 pnpm dev

4、调试源码

这里,我们使用VsCode自带的调试程序。按照下图两个流程走下来,会在根目录创建一个.vscode目录,目录中有个launch.json文件就是调试程序的配置项了。

1.png

1.png 我们给src/index.js文件打上一个断点,然后点击调试按钮,就可以开始调试了。

1.png

4、映射到源码文件

经过上面的一些列操作,虽然可以直接查看源码,但是我们不能打开当前调试步骤中源码的位置。只是一个模拟的地址。

1.png 这是因为,sourcemap文件中, 源码地址使用的相对地址../../../../packages。这样去映射到硬盘中,对应的位置文件不存在,就会给个模拟的假地址。

我们需要替换两个sourcemap文件中../../../../packagesC:/.../packages,即绝对地址,就像下面这样:

1.PNG 此时再去点击调试,一步步执行下去,可以成功看到当前步骤在源码目录中的位置了!

1.png