配置 React 源码的本地调试环境

  1. creat-react-app <项目名称>
  2. yarn run eject
  3. clone 官方源码(目前是 master latest)小版本可能会有些许异同,可以根据命令行的报错信息再去搜索(镜像 react 仓库,clone 慢的可以使用这个)
根目录中执行
git clone --depth=1 https://github.com.cnpmjs.org/facebook/react.git src/react

修改相关配置

  1. 链接本地源码
    react/config/webpack.config.js
resolve: {
    alias: {
        'react-native': 'react-native-web',
-       ...(isEnvProductionProfile && {
-         'react-dom$': 'react-dom/profiling',
-         'scheduler/tracing': 'scheduler/tracing-profiling',
-       }),
-       ...(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'),
         'react-events': path.resolve(__dirname, '../src/react/packages/events')
    }
}
  1. 修改环境变量

这一步不同版本中可能会出现变量不对等的情况
如有报错可以看下源码中的 .eslintrc.js 里面的 globals 属性

react/config/env.js

  const stringified = {
    ....,
    
+    __DEV__: true,
+    SharedArrayBuffer: true,
+    spyOnDev: true,
+    spyOnDevAndProd: true,
+    spyOnProd: true,
+    __PROFILE__: true,
+    __UMD__: true,
+    __EXPERIMENTAL__: true,
+    __VARIANT__: true,
+    gate: true,
+    trustedTypes: true,
  };

2.1 项目根目录中创建 .eslintrc.json 文件

{
  "extends": "react-app",
  "globals": {
    "SharedArrayBuffer": true,

    "spyOnDev": true,
    "spyOnDevAndProd": true,
    "spyOnProd": true,
    "__PROFILE__": true,
    "__UMD__": true,
    "__EXPERIMENTAL__": true,
    "__VARIANT__": true,
    "gate": true,
    "trustedTypes": true
  }
}
  1. 忽略 flow

    webstrom 中可自动识别 flow,其他编辑器可能需要下载插件

yarn add @babel/plugin-transform-flow-strip-types -D

3.1 添加配置

react/config/webpack.config.js[babel-loader]

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]',
        },
      },
    },
  ],
],
  1. 导出 HostConfig

修改文件/react/packages/react-reconciler/src/ReactFiberHostConfig.js

- invariant(false, 'This module must be shimmed by a specific renderer.');
+ export * from './forks/ReactFiberHostConfig.dom'

4.1 修改文件/react/packages/shared/ReactSharedInternals.jsreact此时未export内容,直接从ReactSharedInternals拿值

- import * as React from 'react';

- const ReactSharedInternals =
-   React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;

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

export default ReactSharedInternals;

4.2 关闭 eslint 扩展

/react/.eslingrc.js[module.exports]

  extends: [
-   'fbjs',
    'prettier'
  ],

相关报错

invariant

Error: Internal React error: invariant() is meant to be replaced at compile time. There is no runtime version.

解决


export default function invariant(condition, format, a, b, c, d, e, f) {
+  return;

  throw new Error(
    'Internal React error: invariant() is meant to be replaced at compile ' +
      'time. There is no runtime version.',
  );
}

完结撒花

  • github 源码地址
  • 版本更新复制 clone 代码即可,建议 pull,避免代码覆盖问题

运行结果