如何运行react源码用于源码分析
说到使用react那很简单 react 和reactdom 两个文件引入一下就ok,但是这两个文件是经过编译打包,我们无法在里面进行断点调试或者console调试,
所以想学习框架源码,第一步就要在本地运行源码这样才能在内部进行各种输出调试。
好了闲话不说,直接开始正题:
React源码获取
在这里我选择用的的版本是16.10.0 ,
获取方式当然是react的git仓库
创建测试项目
在本地通过create-react-app创建测试项目
创建完项目之后要修改源码以及webopack配置,需要 将‘旺旺大礼包’给解出来
npm run eject
项目目录下会多出一个config文件
reject目录
将创建的项目替换为下载的源码文件
将下载16.10.0的项目源码丢到src目录下
源码目录
更改配置文件 /config/webpack.config.js在运行项目的时候编译我们导入的源码为
    resolve:{
        ...,
        alias: {
        // Support React Native Web
        // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
        // 'react-native': 'react-native-web',
        // Allows for better profiling with ReactDevTools
        // ...(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'),
        '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'),
      },
    }
错误处理
替换完成后,因为版本和编译的原因会遇到各种错误,
具体的错误类型与解决方式,在这里做一个简单的介绍
flow 检测报错
flow检测错误
由于react的源码中采用了flow这个东东做类型检查,
所以我们需要安装 @babel/plugin-transform-flow-strip-types这个插件忽略类型检测
插件安装
npm install @babel/plugin-transform-flow-strip-types -D
插件配置
  //在webpack.config.js的babel-loader中添加配置
    {
        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')]
          // 配置忽略flow类型检测
        ],
        ...
    }
HostConfig配置错误
修改文件 src/react/packages/react-reconciler/src/ReactFiberHostConfig.js==, 根据环境去导出HostConfig。
//添加以下代码
export * from './forks/ReactFiberHostConfig.dom';
部分全局变量报错
修改 /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
  };
hasOwnProperty ReactSharedInternals.js错误
修改文件 src/react/packages/shared/ReactSharedInternals.js
// react此时未export内容,直接从ReactSharedInternals拿值
// import React from 'react';
// 此时React为undefined
// const ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
import ReactSharedInternals from '../react/src/ReactSharedInternals';
invariant() 函数报错
inval函数报错
src/react/packages/shared/invariant.js文件下 invariant 函数的错误处理
修改如下:
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.',
  );
}
到此为止现在运行的react项目采用的使我们下载导入的react16.10.0的源码,我们就可以在源码里进行输出的错误调试
比如我在react/index.js源码 进行输出测试
'use strict';
const React = require('./src/React');
console.log('源码测试',React)
// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
module.exports = React.default || React;
运行测试:
npm run install
npm run start
下载地址:
链接:https://pan.baidu.com/s/1yC6MMLAEpDJZaeJcXP7Zwg 密码:vvz8

