1. 程式人生 > 其它 >搭建 React 17 原始碼本地除錯環境

搭建 React 17 原始碼本地除錯環境

同步連結: https://www.shanejix.com/posts/搭建 React 17 原始碼本地除錯環境/

通過這種方式只能除錯編譯之後的程式碼,不能實現原汁原味的原始碼除錯體驗。查閱一些社群的實現,記錄下步驟,方便後續查閱。

也可以直接 clone 配置好的倉庫:https://github.com/shanejix/react-source-code-debug

步驟

  1. 使用 create-react-app 腳手架建立專案
npx create-react-app react-source-code-debug
  1. 彈射 create-react-app 腳手架內部配置
yarn run eject
  1. 克隆 react 官方原始碼 (在專案的根目錄下進行克隆)
git clone --branch v17.0.2 --depth=1 https://github.com/facebook/react.git src/react
  1. 通過 alias ,連結本地原始碼
// 檔案位置: react-source-code-debug/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 || {}),
    + // FIXME: REACT SOURCE CODE DEBUG
    + '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'),
  },
}
  1. 修改環境變數
// 檔案位置: react-source-code-debug/config/env.js

// FIXME: REACT SOURCE CODE DEBUG
const stringified = {
  + __DEV__: true,
  + __PROFILE__: true,
  + __UMD__: true,
  + __EXPERIMENTAL__: true,
  'process.env': Object.keys(raw).reduce((env, key) => {
    env[key] = JSON.stringify(raw[key]);
    return env;
  }, {}),
};
  1. 在根目錄建立 eslintrc.json檔案,內容如下
{
  "extends": "react-app",
  "globals": {
    "__DEV__": true,
    "__PROFILE__": true,
    "__UMD__": true,
    "__EXPERIMENTAL__": true
  }
}
  1. 修改 ReactFiberHostConfig.js 檔案
// 檔案位置: /react/packages/react-reconciler/src/ReactFiberHostConfig.js

- import invariant from 'shared/invariant';
- invariant(false, 'This module must be shimmed by a specific renderer.');

+ // FIXME: REACT SOURCE CODE DEBUG
+ export * from './forks/ReactFiberHostConfig.dom'
  1. 修改 ReactSharedInternals.js 檔案
// 檔案位置: /react/packages/shared/ReactSharedInternals.js

- import * as React from 'react';

- const ReactSharedInternals =
-   React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;

+ // FIXME: REACT SOURCE CODE DEBUG
+ import ReactSharedInternals from '../react/src/ReactSharedInternals';

+ export default ReactSharedInternals;
  1. 修改 invariant.js 檔案
// 檔案位置: /react/packages/shared/invariant.js

export default function invariant(condition, format, a, b, c, d, e, f) {

  + // FIXME: REACT SOURCE CODE DEBUG
  + if (condition) {
  +   return;
  + }

  throw new Error(
    'Internal React error: invariant() is meant to be replaced at compile ' +
    'time. There is no runtime version.',
  );
}
  1. 關閉 eslint 擴充套件
// 檔案位置: react/.eslingrc.js [module.exports]

- extends: [
-  'fbjs',
-  'prettier'
- ]
  1. 解決 eslint 報錯
// 將 webpack 中 eslint 外掛給關掉,修改 src/config/webpack.config.js 檔案

// ...

// FIXME: REACT SOURCE CODE DEBUG

// !disableESLintPlugin &&
// new ESLintPlugin({
//   // Plugin options
//   extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'],
//   formatter: require.resolve('react-dev-utils/eslintFormatter'),
//   eslintPath: require.resolve('eslint'),
//   failOnError: !(isEnvDevelopment && emitErrorsAsWarnings),
//   context: paths.appSrc,
//   cache: true,
//   cacheLocation: path.resolve(
//     paths.appNodeModules,
//     '.cache/.eslintcache'
//   ),
//   // ESLint class options
//   cwd: paths.appPath,
//   resolvePluginsRelativeTo: __dirname,
//   baseConfig: {
//     extends: [require.resolve('eslint-config-react-app/base')],
//     rules: {
//       ...(!hasJsxRuntime && {
//         'react/react-in-jsx-scope': 'error',
//       }),
//     },
//   },
// }),
  1. 告訴 babel 在轉換程式碼時忽略型別檢查
yarn add @babel/plugin-transform-flow-strip-types -D
// 檔案位置: react-source-code-debug/config/webpack.config.js [babel-loader]

plugins: [
  // ...

  // FIXME: REACT SOURCE CODE DEBUG
  [require.resolve("@babel/plugin-transform-flow-strip-types")],
];
  1. 新增 eslint 配置
// 在 react 原始碼資料夾中新建 .eslintrc.json 並新增如下配置

{
  "extends": "react-app",
  "globals": {
    "__DEV__": true,
    "__PROFILE__": true,
    "__UMD__": true,
    "__EXPERIMENTAL__": true
  }
}
  1. 修改 react react-dom 引入方式
- // import React from 'react';
- // import ReactDOM from 'react-dom';

+ // FIXME: REACT SOURCE CODE DEBUG

+ import * as React from 'react';
+ import * as ReactDOM from 'react-dom';
  1. 解決 VSCode 中 flow 報錯
// 新建 .vscode/setting.js

{
  "typescript.validate.enable": false,
  "javascript.validate.enable": false
}
  1. 解決 DEV 報錯
// 刪除 node_modules 資料夾,執行 npm install / yarn

// 根目錄下

rm -fr node_modules && yarn

references

作者:shanejix
出處:https://www.shanejix.com/posts/搭建 React 17 原始碼本地除錯環境/
版權:本作品採用「署名-非商業性使用-相同方式共享 4.0 國際」許可協議進行許可。
宣告:轉載請註明出處!