minhuaF / blog

I will write my front-end story.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

本地搭建react源码调试环境

minhuaF opened this issue · comments

commented

此文档可用于调试和学习react源码,适用于当前最新版本(17.0.2)

本地调试react源码的步骤

对本地项目的修改

  1. debug-react 包括了步骤1、2、3,可以直接下载使用;

  2. 生成react项目

npx create-react-app debug-react
  1. 暴露 webpack 配置
npm run eject

3.在src目录下下载react(此文章编写时react版本是17.0.2)

git submodule add https://github.com/facebook/react

4.在 config/webpack.config.js 中修改 react 的引用

resolve: {
    alias: {
        'react-native': 'react-native-web',
        '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. 修改react的引用
// import React from 'react';
// import ReactDOM from 'react-dom';

import * as React from "react";
import * as ReactDOM from "react-dom";
  1. 修改config/env.js
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__: true,
};

修改 react

  1. /src/react/packages/react-reconciler/src/ReactFiberHostConfig.js
// import invariant from 'shared/invariant';
//invariant(false, 'This module must be shimmed by a specific renderer.'); //sy
export * from './forks/ReactFiberHostConfig.dom';
  1. /src/react/packages/shared/invariant.js
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."
  );
}
  1. /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';
  1. /src/react/packages/scheduler/index.js
"use strict";

export * from "./src/Scheduler";
// 添加以下内容
export {
  unstable_flushAllWithoutAsserting,
  unstable_flushNumberOfYields,
  unstable_flushExpired,
  unstable_clearYields,
  unstable_flushUntilNextPaint,
  unstable_flushAll,
  unstable_yieldValue,
  unstable_advanceTime,
} from "./src/SchedulerHostConfig.js";
  1. react/.eslintrc.js
  • extends: []
  • no-function-declare-after-returnreact-internal 相关配置屏蔽,并搜索 /src/react/packages/,把相关的注释都删除。
  1. react/packages/react-dom/src/client下创建CONST.js文件,内容如下(主要解决循环引用问题)
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

export const isPrimaryRenderer = true;
export const warnsIfNotActing = true;
// This initialization code may run even on server environments
// if a component just imports ReactDOM (e.g. for findDOMNode).
// Some environments might not have setTimeout or clearTimeout.
export const scheduleTimeout: any =
  typeof setTimeout === 'function' ? setTimeout : (undefined: any);
export const cancelTimeout: any =
  typeof clearTimeout === 'function' ? clearTimeout : (undefined: any);
export const noTimeout = -1;

// -------------------
//     Microtasks
// -------------------
export const supportsMicrotasks = true;
export const scheduleMicrotask: any =
  typeof queueMicrotask === 'function'
    ? queueMicrotask
    : typeof Promise !== 'undefined'
    ? callback =>
        Promise.resolve(null)
          .then(callback)
          .catch(handleErrorInNextTick)
    : scheduleTimeout; // TODO: Determine the best fallback here.

function handleErrorInNextTick(error) {
  setTimeout(() => {
    throw error;
  });
}

export const supportsMutation = true;
export const supportsHydration = true;
export const supportsTestSelectors = true;
  1. react/packages/react-dom/src/client/ReactDOMHostConfig.js 中找到CONST.js文件中定义的变量并注释,在ReactDOMHostConfig.js文件最后添加export * from './CONST.js'

  2. 启动项目npm start, 控制台显示success,但是打开页面会有error,直接在/src/react项目下搜索并删除即可,有点多,建议批量操作

src/react/packages/react-dom/src/client/ReactDOM.js
  Line 238:9:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging

src/react/packages/react-reconciler/src/ReactFiberHooks.new.js
  Line 1014:7:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging

src/react/packages/react-reconciler/src/ReactFiberHooks.old.js
  Line 1014:7:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging

src/react/packages/react-reconciler/src/ReactFiberHostConfig.js
  Line 10:1:   Definition for rule 'react-internal/invariant-args' was not found  react-internal/invariant-args
  Line 23:15:  Strings must use singlequote                                       quotes

src/react/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
  Line 3201:7:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging

src/react/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
  Line 3201:7:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging

src/react/packages/shared/ConsolePatchingDev.js
  Line 30:7:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging
  Line 55:7:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging
  Line 65:7:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging
  Line 81:7:  Definition for rule 'react-internal/no-production-logging' was not found  react-internal/no-production-logging

src/react/packages/shared/ReactSharedInternals.js
  Line 14:36:  Strings must use singlequote  quotes

Search for the keywords to learn more about each error.

在react源码中添加第一个debugger

在 src\react\packages\react\src\ReactBaseClasses.js 的Component中打个debugger,刷新页面即可看到断点进去了。

/**
 * Base class helpers for the updating state of a component.
 */
function Component(props, context, updater) {
  debugger
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue;
}

参考资料