React Scan 集成 Vite 项目完整指南:从 script 注入、模块导入到官方插件
2026/9/13 3:24:02 网站建设 项目流程

React Scan 集成 Vite 项目完整指南:从 script 注入、模块导入到官方插件

【免费下载链接】react-scanScan and fix React performance issues项目地址: https://gitcode.com/GitHub_Trending/re/react-scan

React Scan 是一个用于扫描并定位 React 应用性能问题的开源工具,它能够在组件重渲染时自动高亮出问题组件。本文以 docs/installation/vite.md 为核心骨架,系统讲解在 Vite 构建的 React 项目中接入 React Scan 的三种主流方式(script 标签、模块导入、官方 Vite 插件),并深入源码揭示每种方式的底层原理与注意事项。读完本文,你将能根据开发/生产环境需求,选择最合适的接入方案并正确配置。

为什么需要关心接入方式

React Scan 的核心机制是"劫持" React DevTools 的 hook(见 packages/scan/src/index.ts,其中通过import 'bippy'的副作用安装 hook),在渲染发生时注入探针。这意味着接入时机直接决定扫描是否生效:所有初始化代码必须在 React(及 React DOM)之前执行。不同的 Vite 接入方式,本质上是解决"如何在 React 加载前注入扫描器"这一问题。

方式一:Script 标签方式(最简单,适合快速试用)

在 Vite 项目中,index.html位于项目根目录。把以下 script 标签加入<head>,并确保它位于其他脚本之前:

<!doctype html> <html lang="en"> <head> <script src="https://unpkg.com/react-scan/dist/auto.global.js"></script> <!-- rest of your scripts go under --> </head> <body> <!-- ... --> </body> </html>
  • auto.global.js是 React Scan 打包出的 IIFE 全局脚本,它在加载后自动执行scan()并暴露window.reactScan(见 auto.ts),因此无需任何额外 JS 代码。

  • 可用的 CDN 地址以 docs/installation/cdn.md 为准,目前提供两个:

    https://cdn.jsdelivr.net/npm/react-scan/dist/auto.global.js https://unpkg.com/react-scan/dist/auto.global.js

从源码看,tsup.config.ts 将auto.ts构建为iife格式(dist/auto.global.js),并以 ES2019 为目标,以兼容未配置@babel/preset-env的旧版 babel-loader。Script 方式的典型场景是:在浏览器里快速验证、临时排查问题,或接入非模块化构建的页面。要注意,生产构建时该脚本依然会执行,若不想在生产暴露,应在部署前去除此标签。

方式二:模块导入方式(推荐,可控性更强)

在项目入口文件(如src/indexsrc/main)中显式导入并调用scan()

// src/index import { scan } from "react-scan"; // must be imported before React and React DOM import React from "react"; scan({ enabled: true, });

这里有两个关键细节:

  1. 导入顺序react-scan的 import 语句必须位于 React / React DOM 之前(见代码注释)。原因正如文档中的警告——React Scan 需要在 React 访问 DevTools hook 之前完成劫持(见 docs/installation/vite.md)。
  2. enabled选项scan()接受Options对象,其中enabled默认值为true,官方推荐在生产环境通过enabled: process.env.NODE_ENV === 'development'关闭扫描(见 packages/scan/src/core/index.ts 的 Options 类型定义)。注意不要与dangerouslyForceRunInProduction混淆,后者用于强制在生产运行,官方明确标注"不推荐"(not recommended)。

由于模块导入发生在 Vite 的模块图解析阶段,react-scan的 ESM 入口dist/index.mjs会先于业务代码执行,从而保证 hook 注入时机正确。

让扫描器在生产环境也运行

默认情况下 React Scan 遵循开发环境优先的设计。如果你确实需要在生产环境也启用(例如线上性能巡检),可以把导入路径从react-scan换成react-scan/all-environments

- import { scan } from "react-scan"; + import { scan } from "react-scan/all-environments";

从源码看,all-environments.ts 的实现非常直白:调用内部scan()前会设置ReactScanInternals.runInAllEnvironments = true,从而绕过环境限制。该导出路径在 package.json 的exports字段中声明。需要强调的是:这是有意为之的"逃生舱",应仅在确实需要时使用。

方式三:官方 Vite 插件(零手写代码,自动注入)

原文档中"Vite plugin"与"Preserving component names"两节标注为 TODO,但仓库中已有完整实现:@react-scan/vite-plugin-react-scan(源码见 packages/vite-plugin-react-scan/src/index.ts,完整文档见 packages/vite-plugin-react-scan/README.md)。该插件负责在构建时自动注入扫描脚本,开发者无需手动修改index.html或入口文件。

安装

# npm npm install -D @react-scan/vite-plugin-react-scan react-scan # pnpm pnpm add -D @react-scan/vite-plugin-react-scan react-scan # yarn yarn add -D @react-scan/vite-plugin-react-scan react-scan

注意:react-scan是必需的 peer 依赖,插件会自动在项目依赖树中向上查找node_modules/react-scan/dist/auto.global.js(见 resolveModuleFileContent 的逐级向上解析逻辑);若找不到,构建会直接失败并提示安装。

基础用法

vite.config.ts中注册插件:

import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import reactScan from '@react-scan/vite-plugin-react-scan'; export default defineConfig({ plugins: [ react(), reactScan({ // options (optional) }), ], });

插件选项

OptionTypeDefaultDescription
enablebooleanprocess.env.NODE_ENV === 'development'Enable/disable scanning
scanOptionsobject{ ... }Custom React Scan options
autoDisplayNamesbooleanfalseAutomatically add display names to React components
debugbooleanfalseEnable debug logging

参数说明(对应源码 ReactScanPluginOptions):

  • enable:总开关。默认仅在开发模式启用;设为true会强制在构建产物中注入扫描脚本。
  • scanOptions:透传给scan()的选项对象(即上文Options类型,如enabledlog等)。
  • autoDisplayNames:自动为组件补充displayName,解决压缩/混淆后组件名不可读的问题(详见下文"组件名保留"小节)。
  • debug:开启插件自身的调试日志,方便排查注入失败等异常。

插件会在初始化时对上述选项做类型校验,非法类型(如enable传了字符串)会抛出明确错误(见 validateOptions)。

完整示例配置

import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import reactScan from '@vite-scan/vite-plugin-react-scan'; export default defineConfig({ plugins: [ react(), reactScan({ enable: true, autoDisplayNames: true, scanOptions: {} // React Scan specific options }), ], });

插件工作原理(源码级解析)

理解插件行为有助于你排查问题。核心逻辑分布在四个钩子中(均见 packages/vite-plugin-react-scan/src/index.ts):

  1. config(L154-L160):自动将react-scan加入optimizeDeps.exclude,避免 Vite 预构建时缓存扫描器导致 hook 注入失效。
  2. configResolved(L205-L223):读取最终配置,区分serve(开发)与build模式,并计算扫描脚本在产物中的路径scanFilePath
  3. transformIndexHtml(L225-L272):通过 cheerio 操作 HTML:
    • 先移除页面中已有的重复扫描脚本(去重,removedCount > 0时打 debug 日志);
    • 开发模式下,把注入脚本插到@vite/client之后(确保 Vite HMR 客户端先就绪);
    • 构建模式下,把脚本插到<head>最前面,确保优先于业务代码执行。
  4. generateBundle(L282-L311):构建时读取node_modules/react-scan/dist/auto.global.js内容,作为静态资源 emit 到assets目录(默认assets/auto.global.js),再由注入的<script src>引用。

开发模式注入的是模块式脚本(import { scan } from '${base}@id/react-scan',配合resolveId钩子 L274-L280 解析),构建模式注入的是auto.global.js+ 一段reactScan(options)的调用包装。因此:

  • 开发环境:插件把 React Scan 直接注入应用,实现实时分析;
  • 生产环境:默认不注入;仅当enable显式设为true时才会随产物输出(此时插件会自动把扫描脚本复制进构建资源,无需手动处理 CDN)。

组件名保留(Preserving component names)

生产构建中组件名常被压缩为单字母,导致性能面板里看不到有意义的名称。插件提供两条路径:

  • 开启autoDisplayNames: true:插件会在transform钩子(L162-L203)中对每个.jsx/.tsx文件运行 Babel 转换,利用babel-plugin-add-react-displayname自动为组件注入displayName。转换失败时插件会记录错误并返回原始代码,不会阻断构建。
  • 使用react-scan/react-component-name/vite子路径:仓库还提供了独立的组件名保留插件实现(见 packages/scan/src/react-component-name/vite.ts 的构建产物声明于 package.json 的typesVersions/exports),可按需单独集成。

注意:源码中ReactScanPluginOptions.autoDisplayNames的 JSDoc 标注默认值为true,而插件运行时默认值为false(index.ts),README 表格同样标注false。以实际运行行为为准:不传该选项时默认关闭,如需启用请显式设置autoDisplayNames: true

三种方式对比与选择建议

接入方式侵入性适用场景生产环境控制
Script 标签最低(改index.html快速试用、临时排查、非模块化页面需手动移除标签
模块导入低(改入口文件)追求显式可控、希望按环境开关通过enabledall-environments控制
Vite 插件无(改vite.config.ts长期集成、需要组件名保留、团队协作默认仅开发注入,可enable: true强制

常见踩坑点

  1. 导入顺序:无论用哪种模块方式,react-scan的 import 必须早于 React/React DOM,否则 DevTools hook 劫持失败,扫描不生效(这是官方文档明确标注的 CAUTION)。
  2. 重复注入:如果同时用了 script 标签和插件,插件会在transformIndexHtml中自动移除旧脚本(L235-L243);反之,手动接入了 script 标签的页面又加载插件,会出现重复扫描。建议只保留一种接入方式。
  3. enablescanOptions.enabled的区别enable是插件是否注入脚本的总开关;scanOptions.enabled是运行时scan()的开关。两者都配置时以注入后实际调用结果为准。
  4. 生产环境默认不扫描:这是设计使然。需要线上巡检时,请显式配置(模块方式用react-scan/all-environments,插件方式设enable: true),并自行评估对线上性能的影响。

延伸阅读

仓库内其他框架的安装指南与本文方式一、方式二通用:Next.js(App Router / Page Router)、Remix、Astro、React Router、TanStack Start、Parcel、Rsbuild 等见 docs/installation/。Vite 插件的中文用户可结合 packages/vite-plugin-react-scan/README.md 与源码 packages/vite-plugin-react-scan/src/index.ts 深入理解;React Scan 运行时选项的完整定义见 packages/scan/src/core/index.ts。

【免费下载链接】react-scanScan and fix React performance issues项目地址: https://gitcode.com/GitHub_Trending/re/react-scan

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询