react源码调试

180 阅读2分钟

前言

最近想看看react的源码,但是怎么去调试react源码一直困扰着我,今天就来解决这个问题

官网推荐方法

官网推荐的方式是将react打包成了js文件,但是我想要在真实源码中操作,查看官网方式

Webpack alias

这个方式是通过alias(别名)的方式,将react,react-dom等库的源码指向指定的库中,但是在实际操作的时候遇到了很多报错,我们一点点的来解决。

  1. 创建react项目
    这里为了方便采用create-react-app,也可以自己进行搭建。
    npx create-react-app react-code
    cd react-code
  1. 下载react源码
// 这次我们将存放目录放在项目文件里的 src 目录下 
cd src 
// 我们下载的是带有 v18.2.0 tag 的版本
git clone --branch v18.2.0 https://github.com/facebook/react.git
  1. 更改webpack的配置
    这里因为是脚手架生成的,所以需要命令把webpack配置暴露出来 npm run eject
  2. 修改alias
//原配置
    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 || {}),
      },
//修改后的配置
    alias:{
        react: path.join(paths.appSrc, 'react/packages/react'),
        'react-dom': path.join(paths.appSrc, 'react/packages/react-dom'),
        shared: path.join(paths.appSrc, 'react/packages/shared'), 
        'react-reconciler': path.join(paths.appSrc, 'react/packages/react-reconciler')
    }

修改后运行项目 npm start
5. 报错 修改React和React-Dom的导入 执行完上面的操作后,控制台还剩下5个错误

image.png

//src/index
//修改前
import React from 'react';
import ReactDOM from 'react-dom/client';
//修改后
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
  1. 报错 修改scheduler

image.png

// react-app/src/react/packages/react-reconciler/src/Scheduler.js 
// 在开头引入 SchedulerMock 
import * as SchedulerMock from 'scheduler/src/forks/SchedulerMock'; 
// 修改前 
export const unstable_yieldValue = Scheduler.unstable_yieldValue;
export const unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue;
// 修改后 
export const unstable_yieldValue = SchedulerMock.unstable_yieldValue;
export const unstable_setDisableYieldValue = SchedulerMock.unstable_setDisableYieldValue;

  1. 报错 关闭eslint

image.png

/webpack.config.js
//修改前
const disableESLintPlugin = process.env.DISABLE_ESLINT_PLUGIN === 'true';
修改后
const disableESLintPlugin = true

8.修改环境变量

image.png React 的源码里有直接使用 __DEV__等环境变量,我们直接替换掉,修改 config/env.js

// react-app/config/env.js 
// 修改前
const stringified = {
    'process.env': Object.keys(raw).reduce((env, key) => {
      env[key] = JSON.stringify(raw[key]);
      return env;
    }, {}),
  };
//修改后
const stringified = {
    'process.env': Object.keys(raw).reduce((env, key) => {
      env[key] = JSON.stringify(raw[key]);
      return env;
    }, {}),
    __DEV__: true,
    __EXPERIMENTAL__: true,
    __PROFILE__: true,
  };


  1. __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED

image.png 首先找到了报错文件 /src/react/packages/shared/ReactSharedInternals.js 更改如下

// 修改前
const ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; 
// 修改后
import ReactSharedInternals from 'react/src/ReactSharedInternals'

  1. This module must be shimmed by a specific renderer

image.png 打开报错的文件 src/react/packages/react-reconciler/src/ReactFiberHostConfig.js, 修改如下

// 修改前 
throw new Error('This module must be shimmed by a specific renderer.');
// 修改后 
export * from "./forks/ReactFiberHostConfig.dom";
  1. 这个时候就可以进行调试了,当修改源码时,页面也会发生相应的变化,vscode调试自行搜索方案吧。