React源码调试

最近看了很多react源码的讲解视频、文章,不过纸上得来终觉浅,看一百次不如自己调试一次印象来得深。

拉取react源码安装依赖

js 复制代码
git clone https://github.com/facebook/react.git
yarn

拉取源码后可以看到react的模块都放在packages目录下,因为react的类型检查用的是flow,肯定是不能直接运行在浏览器里的所以我们需要使用babel转换成普通的js。packages下有许多模块有的模块涉及到服务端渲染、开发工具、跨平台,这里我们只需要浏览器相关的模块 react react-client react-dom react-dom-bindings react-reconciler scheduler shared 接下来就可以使用babel转换这些模块,转换的时候会遇到报错有些报错文件并不会转换成功,先不用管,后面启动项目时遇到缺少的文件或目录再一一单独转换就行

js 复制代码
// 这里只举例了react, 上述其他模块也是如此
./node_modules/.bin/babel ./packages/react --out-dir ./build/react

启动项目

  1. 先创建一个react项目,然后把react源码build目录拷到react-debug下改名为react-source。
js 复制代码
pnpm create vite react-debug --template react
  1. 修改vite.config.js
js 复制代码
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "path";

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    // 修改 jsx 方法的引用路径,会指向到react-source/react/jsx-dev-runtime.js
    react({
      jsxRuntime: "automatic",
      jsxImportSource: path.resolve(import.meta.dirname, "react-source/react/"),
    }),
  ],
  // 定义react中的变量
  define: {
    __EXPERIMENTAL__: false,
    __PROFILE__: false,
    __DEV__: false,
  },
  resolve: {
  // 设置文件系统别名
    alias: [
      {
        find: "react",
        replacement: path.resolve(import.meta.dirname, "react-source/react/"),
      },
      {
        find: /^react-dom\/(.*)?/,
        replacement: path.resolve(
          import.meta.dirname,
          "react-source/react-dom/$1"
        ),
      },
      {
        find: /^react-source\/(.*)?/,
        replacement: path.resolve(import.meta.dirname, "react-source/$1"),
      },
      {
        find: /^react-dom-bindings\/(.*)?/,
        replacement: path.resolve(
          import.meta.dirname,
          "react-source/react-dom-bindings/$1"
        ),
      },
      {
        find: /^shared\/(.*)?/,
        replacement: path.resolve(
          import.meta.dirname,
          "react-source/shared/$1"
        ),
      },
      {
        find: /^react-reconciler\/(.*)?/,
        replacement: path.resolve(
          import.meta.dirname,
          "react-source/react-reconciler/$1"
        ),
      },
      {
        find: "scheduler",
        replacement: path.resolve(
          import.meta.dirname,
          "react-source/scheduler/"
        ),
      },
      {
        find: /^react-client\/(.*)?/,
        replacement: path.resolve(
          import.meta.dirname,
          "react-source/react-client/$1"
        ),
      },
    ],
  },
});
  1. 修改 react/src/jsx/ReactJSX.js。(PS: 可能会因为在第一步执行babel失败在react-source中并没有jsx目录,再到react源码中执行 ./node_modules/.bin/babel ./packages/react/src/jsx --out-dir ./build/react/src/jsx然后再把jsx目录复制到react-source就行了,其他babel执行失败的文件也是一样 )
js 复制代码
// react-source/react/src/jsx/ReactJSX.js 
var jsxDEV = __DEV__ ? _jsxDEV : jsxProd
  1. 把引入路径都成从 react-source 中引入
js 复制代码
// App.jsx
import { useState } from "react-source/react"

function App() {
  const [count, setCount] = useState(0)
  return (
    <div>
      I am React
      <button onClick={() => {
        setCount(count + 1)
      }}>{count}</button>
    </div>
  )
}

export default App
  1. 最后就可以开始"愉快"得调试源码啦,现在在createRoot的地方打断点就会进到react-source里了
相关推荐
3GPP仿真实验室7 分钟前
【MATLAB源码】OTFS-SCMA:链路仿真平台
前端
JarvanMo13 分钟前
NativePHP 移动版现已免费:用 Laravel 打造原生 iOS 和 Android 应用
前端
答案answer23 分钟前
一个非常实用的Three.js3D模型爆破💥和切割开源插件
前端·github·three.js
掘金安东尼37 分钟前
Fun with TypeScript Generics:玩转 TS 泛型
前端·javascript·面试
掘金安东尼38 分钟前
Next.js 企业级落地
前端·javascript·面试
掘金安东尼42 分钟前
React 性能优化完全指南 2026
前端·javascript·面试
Moment1 小时前
OpenClaw 从能聊到能干差的是这 50 个 Skills 😍😍😍
前端·后端·开源
小霖家的混江龙1 小时前
从 0 到 1 实现一个 useState
前端·javascript·react.js
晓得迷路了1 小时前
栗子前端技术周刊第 118 期 - Oxfmt Beta、Angular GitHub stars、React 基金会...
前端·javascript·react.js
亿元程序员1 小时前
小伙伴说我的拼图游戏用Mask不能合批...
前端