Skip to content

如何正确debug 源码react #1

@dravenww

Description

@dravenww

网上找了好多debug react的文章,在17上都不好使;在其他前辈们的基础上,进行了自己的尝试,记录下来,算是个开头,使用的是yarn不是npm哈。

  • 安装create-react-app
  • 创建react项目:create-react-app study-react
  • 进入到项目目录,并暴露webpack等配置文件:cd study-react && yarn eject
  • 执行yarn start,确保现在的项目是可以run起来的,结果TMD报错:
     Cannot find module '@babel/plugin-syntax-jsx'
    
  • 没关系,我们安装依赖:yarn add -D @babel/plugin-syntax-jsx
  • 重新执行yarn start,这次跑起来了,打开浏览器输入:http://localhost:3000/,可以看到如下界面:
  • 接下来我们需要把对应的react等依赖,指向源码了,没有源码,我们clone源码,
  • 进入到src目录,执行:git submodule add [email protected]:facebook/react.git,然后切换分支:cd react && git checkout tags/v17.0.0 -b v17.0.0
  • 接下来,我们就得改引用了,也就是webpack的alias配置,进入到项目目录,直接把原先的alias配置全部替换成下面的:
    // @file study-react/config/webpack.config.js
    alias: {
      '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'),
      'scheduler': path.resolve(__dirname, "../src/react/packages/scheduler"),
    },
    
  • 重新执行yarn start,编译报错:
    ./src/react/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
    Attempted import error: 'afterActiveInstanceBlur' is not exported from './ReactFiberHostConfig'.
    
  • 我们进入到ReactFiberHostConfig文件,修改下导出:
    // @file src/react/packages/react-reconciler/src/ReactFiberHostConfig.js
    // 当前文件下其他内容全部注释掉即可,没用
    export * from './forks/ReactFiberHostConfig.dom'
    
  • 此时编译会继续报错:
    ./src/index.js
    Attempted import error: 'react' does not contain a default export (imported as 'React').
    
  • 是react引用的问题,我们进到/src/index文件,把对react和react-dom的引用改成下面样子:
    import * as React from 'react';
    import * as ReactDOM from 'react-dom';
    
  • 接下来会继续报编译的错:
    ./src/react/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
    Attempted import error: 'unstable_flushAllWithoutAsserting' is not exported from 'scheduler' (imported as 'Scheduler').
    
  • 我们找到unstable_flushAllWithoutAsserting的声明是在SchedulerHostConfig.mock.js里面,所以我们在scheduler增加以下导出,挺多的,别漏了:
    // @file src/react/packages/scheduler/src/Scheduler.js
    export * from './src/SchedulerHostConfig.js';
    
    // @file src/react/packages/scheduler/src/SchedulerHostConfig.js
    // 添加以下
    export {
        unstable_flushAllWithoutAsserting,
        unstable_flushNumberOfYields,
        unstable_flushExpired,
        unstable_clearYields,
        unstable_flushUntilNextPaint,
        unstable_flushAll,
        unstable_yieldValue,
        unstable_advanceTime
    } from './forks/SchedulerHostConfig.mock.js';
    
    export {
        requestHostCallback,
        requestHostTimeout,
        cancelHostTimeout,
        shouldYieldToHost,
        getCurrentTime,
        forceFrameRate,
        requestPaint
    } from './forks/SchedulerHostConfig.default.js';
    
    
  • 接下来还是会报错如下,可以看到是eslint的问题:
    Failed to load config "fbjs" to extend from.
    Referenced from: /Users/wuhongjie/mywork/study-react/src/react/.eslintrc.js
    
  • 我们接下来把eslint给去掉,在webpack的配置文件里面,把ESLintPlugin从代码里面注释掉。重新执行yarn start;
  • 这时候,编译已经不报错了,打开浏览器可以看到:
  • 从上面可以得知什么呢?PROFILEEXPERIMENTAL 属于变量替换的问题,我们继续改webpack的配置:
    // @file config/env.js
    const stringified = {
      'process.env': Object.keys(raw).reduce((env, key) => {
        return env;
      }, {}),
      "__DEV__": true,
      "__PROFILE__": true,
      "__UMD__": true,
      "__EXPERIMENTAL__": true
    };
    
  • 本以为接下来就ok了,重新执行yarn start后,发现还是报错
    Error: Internal React error: invariant() is meant to be replaced at compile time. There is no runtime version.
    
  • 上面报错函数invariant报错,现在我们去处理invariant函数:
    // @file src/react/packages/shared/invariant.js
    export default function invariant(condition, format, a, b, c, d, e, f) {
      return false; // 加上这个,啥也不管直接返回false
      throw new Error(
        'Internal React error: invariant() is meant to be replaced at compile ' +
          'time. There is no runtime version.',
      );
    }
    
  • 接下来,重新执行yarn start,看浏览器:

    yeah,成功了!!!

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions