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里了
相关推荐
程序员爱钓鱼2 小时前
Node.js 编程实战:文件读写操作
前端·后端·node.js
PineappleCoder2 小时前
工程化必备!SVG 雪碧图的最佳实践:ID 引用 + 缓存友好,无需手动算坐标
前端·性能优化
JIngJaneIL3 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
敲敲了个代码3 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web
澄江静如练_3 小时前
列表渲染(v-for)
前端·javascript·vue.js
JustHappy3 小时前
「chrome extensions🛠️」我写了一个超级简单的浏览器插件Vue开发模板
前端·javascript·github
Loo国昌3 小时前
Vue 3 前端工程化:架构、核心原理与生产实践
前端·vue.js·架构
sg_knight3 小时前
拥抱未来:ECMAScript Modules (ESM) 深度解析
开发语言·前端·javascript·vue·ecmascript·web·esm
LYFlied3 小时前
【每日算法】LeetCode 17. 电话号码的字母组合
前端·算法·leetcode·面试·职场和发展