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里了
相关推荐
豆约翰几秒前
css自制图书封面效果
前端·css
积硅步致千里6 分钟前
Fyne 兼容性:报错还能救,透明窗才要命
前端·后端
可乐鸡翅yeah_40 分钟前
hls.js 播放质量埋点实战,采集卡顿、起播、错误指标定位线上用户问题
开发语言·前端·javascript·ecmascript·音视频·m3u8·音视频在线播放
tedcloud1231 小时前
Wand-Enhancer:如何搭建一套远程开发与测试环境
前端·人工智能·macos·开源·流程图
掘金挖土1 小时前
前端手摸手跑路之 AI 应用开发(三)
前端·后端
计算机魔术师2 小时前
OpenAI 宣称破解千禧年难题,数学家却说是「反例搜索」?
前端
志尊宝2 小时前
Vue3 零基础每日笔记(015):条件渲染 v-if 与 v-show——控制 DOM 生死还是控制显隐
前端·vue.js·笔记
掘金者阿豪2 小时前
OceanBase 和金仓怎么选?别只看分布式,复杂查询更考验架构取舍
前端·后端·架构
Bug修理工Bubble2 小时前
Swift ARC:一个对象到底什么时候才会被释放?
前端
ClouGence2 小时前
GPT-6 做 UI 自动化测试:Demo 惊艳,但真的适合长期回归吗?
前端·chatgpt·测试