最新版React源码阅读环境搭建

2,039 阅读1分钟

环境准备

npx create-react-app xxx
cd xxx
npm/yarn run eject
cd src
// 你也可以fork 这样你可以注释源码解释并提交远程仓库
git clone react GitHub地址

webpack部分修改

  • 如果你不想第一次失败的话 请关闭eslint
// 删除eslint配置项 ***** 旧版本 *******
位置在 -----> module.rules[1]
****** 新版本 react 17.0.2*************
const disableESLintPlugin = true;
const hasJsxRuntime = false
// 至于怎么用这个 后续更新
  • babel-loader部分修改
// react的源码中采用了flow类型检查 
// 安装对应的babel插件忽略flow的类型检查,并且在webpack的babel-loader中增加该插件
npm/yarn install/add @babel/plugin-transform-flow-strip-types -D

{
    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-named-asset-import'),
            {
                loaderMap: {
                svg: {
                    ReactComponent:
                    '@svgr/webpack?-svgo,+titleProp,+ref![path]',
                },
                },
            },
            ],
            // --------- 新增 ---------
            [require.resolve('@babel/plugin-transform-flow-strip-types')]
            // --------- 结束 ---------
        ],
        // 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,
        cacheCompression: isEnvProduction,
        compact: isEnvProduction,
    },
}
  • 修改resolve下的alias
alias: {
        "react-native": "react-native-web",
        // --------- 新增 ---------
        react: path.resolve(__dirname, "../src/react/packages/react"),
        "react-dom": path.resolve(__dirname, "../src/react/packages/react-dom"),
        "legacy-events": path.resolve(
          __dirname,
          "../src/react/packages/legacy-events"
        ),
        shared: path.resolve(__dirname, "../src/react/packages/shared"),
        "react-reconciler": path.resolve(
          __dirname,
          "../src/react/packages/react-reconciler"
        ),
        // --------- 结束 ---------
        // Allows for better profiling with ReactDevTools
        ...(isEnvProductionProfile && {
          "react-dom$": "react-dom/profiling",
          "scheduler/tracing": "scheduler/tracing-profiling"
        }),
        ...(modules.webpackAliases || {})
      },
  • devtool的值改为source-map ----> 为了让打出的包有sourcemap

config/env.js中的stringifed对象增加属性

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__: false
    // --------- 结束 ---------
  };

修改src文件下react文件

// src/react/packages/react-reconciler/src/ReactFiberHostConfig.js文件添加
export * from './forks/ReactFiberHostConfig.dom'


// src/react/packages/shared/ReactSharedInternals.js文件添加
//  import React from 'react';
//  const ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
import ReactSharedInternals from '../react/src/ReactSharedInternals';


// src/react/packages/shared/invariant.js文件修改
export default function invariant(condition, format, a, b, c, d, e, f) {
    return condition;
    throw new Error(
        'Internal React error: invariant() is meant to be replaced at compile ' +
        'time. There is no runtime version.',
    );
}

导入react``react-dom需要修改

import React from 'react' ----> import * as React from 'react'
import ReactDOM from 'react-dom' ----> import * as ReactDOM from 'react-dom'

8月25日更新

如果出现ReferenceError: React is not defined

检查组件的文件是否引入了import * as React from 'react'