Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

本地搭建react源码调试环境 #13

Open
minhuaF opened this issue Mar 13, 2021 · 0 comments
Open

本地搭建react源码调试环境 #13

minhuaF opened this issue Mar 13, 2021 · 0 comments

Comments

@minhuaF
Copy link
Owner

minhuaF commented Mar 13, 2021

此文档可用于调试和学习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;
}

参考资料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant