news 2026/8/20 16:38:50

react-scanner 原理揭秘:AST 解析与 JSX 组件扫描是如何工作的

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
react-scanner 原理揭秘:AST 解析与 JSX 组件扫描是如何工作的

react-scanner 原理揭秘:AST 解析与 JSX 组件扫描是如何工作的

【免费下载链接】react-scannerExtract React components and props usage from code.项目地址: https://gitcode.com/gh_mirrors/re/react-scanner

如果你想快速摸清一个 React 项目里组件到底被用了多少次、每个 prop 的使用频率如何,react-scanner 是一个非常趁手的静态分析工具。它并不运行你的代码,而是从源码层面解析出组件与 props 的使用情况,输出一份结构化的 JSON 报告。这篇文章将带你深入它的内部实现,一步步拆解AST 解析JSX 组件扫描的完整工作流程,让即使是新手也能看懂这套"扫描魔法"背后的原理。

先认识 react-scanner:静态分析的思路

react-scanner 的核心能力是Extract React components and props usage from code(从代码中提取 React 组件和 props 的使用情况),它天然支持 TypeScript。整个过程不依赖浏览器、不执行 JSX,而是通过**抽象语法树(AST)**来"读"代码。

它的工作可以概括为三步流水线:

步骤做什么对应源码
① 爬取文件按 glob 规则找出所有待扫描的源文件src/run.js
② 解析扫描把代码解析成 AST,识别组件与 propssrc/scan.js
③ 处理报告用处理器把原始报告加工成统计结果src/processors/

整个入口很简单:无论是命令行还是编程式调用,最终都会走进 src/scanner.js 的run方法,先做配置校验,再触发扫描流程。

第一步:如何精准爬取目标文件

扫描开始前,react-scanner 要先确定"扫哪些文件"。在 src/run.js 中,它借助fdir这个高性能目录爬取库,配合 glob 规则过滤出目标文件:

const files = new fdir() .glob(...globs) .exclude(getExcludeFn(config.exclude)) .withFullPaths() .crawl(crawlFrom) .sync();

默认的 glob 是**/!(*.test|*.spec).@(js|ts)?(x),也就是自动跳过测试文件,只扫描.js.jsx.ts.tsxexclude配置则可以在 src/utils.js 的getExcludeFn中看到:既支持字符串/正则数组,也支持自定义函数,灵活排除node_modules之类的目录。

第二步:AST 解析,让机器"看懂"代码

这是最核心的一环。机器没法直接理解字符串形式的 JSX,所以需要先把它解析成抽象语法树。react-scanner 选择的解析器是@typescript-eslint/typescript-estree——它能把 TypeScript 和 JSX 代码都转换成标准的 ESTree 节点树。

在 src/scan.js 中可以看到解析选项:

const parseOptions = { loc: true, // 记录每个节点的行列位置 jsx: true, // 开启 JSX 语法支持 };

loc: true非常重要,它让报告能够精确到某个组件出现在哪个文件的第几行第几列,这为后续的代码审计提供了精确坐标。

第三步:JSX 组件扫描,遍历 AST 找答案

解析出 AST 之后,react-scanner 使用astray这个轻量遍历库,只对两类节点感兴趣:

  • ImportDeclaration:记录 import 信息(来源模块、本地别名)
  • JSXOpeningElement:发现组件被使用的位置

这部分逻辑在 src/scan.js 中。每当遇到一个 JSX 开始标签,getComponentNameFromAST(src/scan.js)就会解析出它的完整名称:

  • JSXIdentifier:普通名称,如Button
  • JSXMemberExpression:成员表达式,如Footer.Content.Legal,会递归拼接成带点的完整路径

同时,importsMap(src/scan.js)维护着"本地名 → 导入来源"的映射。这样即使你写了import { Link as BasisLink } from "basis",扫描器也能准确还原出它实际指向的组件名,而不是被别名迷惑。

属性提取:JSXAttribute 与展开属性

组件实例上的 props 是怎么被记录的?看 src/scan.js 的getInstanceInfo,它会遍历node.attributes

  • JSXAttribute:普通属性,比如<Text margin="4">,属性名和值都会被提取
  • JSXSpreadAttribute{...props}形式的展开属性,无法静态确定具体键值,所以标记propsSpread: true

每个使用实例最终会记录下:导入信息、props 键值对、是否展开、以及文件位置。

深入 getPropValue:字面量与表达式

一个有趣的细节是 prop 值如何被"翻译"成报告内容,这由getPropValue(src/scan.js)完成:

AST 节点类型报告中的值
Literal(字符串/数字/布尔)字面量本身,如"4"
JSXExpressionContainer内的字面量表达式的实际值
其他表达式(变量、函数等)AST 类型名,如(Identifier)

所以静态分析有其天然边界:传的是变量时,它只能告诉你"这里传了一个 Identifier 类型的表达式"。不过你可以通过配置getPropValue自定义处理,把表达式还原成真实代码,比如在 README.md 中就有用escodegen生成表达式源码的例子。

报告结构:一棵嵌套的组件树

扫描完成后,所有实例会聚合进一个嵌套的 report 对象,数据结构大致如下:

组件名 └── instances[] 每次使用实例 ├── importInfo 导入来源信息 ├── props prop 名 → 值 ├── propsSpread 是否使用了展开 └── location 文件与行列位置

子组件(如Footer.Content)会嵌套在父组件之下,而forEachComponent(src/utils.js)提供了递归遍历这棵树的辅助方法,方便处理器逐层访问。

处理器:把原始报告变成有用统计

原始报告是"过程数据",直接看比较繁琐,所以 react-scanner 内置了三个处理器(src/processors/processors.json):

  • count-components:统计每个组件被使用的次数,输出{ "Text": 17 },见 count-components.js
  • count-components-and-props(默认):统计组件实例数 + 各 prop 的使用频次,见 count-components-and-props.js
  • raw-report:原样输出原始 JSON 报告,见 raw-report.js

处理器还可以自由组合、串联执行(支持异步函数),例如先把统计结果算出来,再通过自定义处理器把数据发给你的监控系统,这正是设计系统团队做组件健康度评估的常用玩法。

写在最后:静态扫描的适用场景

理解了 AST 解析与 JSX 组件扫描的原理,你就能明白 react-scanner 的价值所在:

  • ✅ 统计设计系统组件的使用热度,决定哪些组件值得继续维护
  • ✅ 追踪某个 prop 的取值分布,为废弃旧用法提供数据支撑
  • ✅ 在大型代码库中快速盘点组件引用关系,无需手动搜索

由于是纯静态分析,它不会执行你的业务代码,速度快且无副作用;而 AST 方案又比正则匹配更可靠,能正确处理别名、展开属性、嵌套子组件等复杂情况。如果你正在为组件库的"家底"发愁,不妨 clone 下来动手跑一跑,亲眼看看这份报告是如何一步步生成的。🚀

【免费下载链接】react-scannerExtract React components and props usage from code.项目地址: https://gitcode.com/gh_mirrors/re/react-scanner

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/20 16:37:59

IdaRef源码解析:深入InstructionReference核心类的实现原理

IdaRef源码解析&#xff1a;深入InstructionReference核心类的实现原理 【免费下载链接】idaref IDA Pro Instruction Reference Plugin 项目地址: https://gitcode.com/gh_mirrors/id/idaref IdaRef是一款开源的IDA Pro指令参考插件&#xff0c;它的核心价值在于&#…

作者头像 李华
网站建设 2026/8/20 16:30:06

面向银行业的通行密钥控制平面构建研究

摘要 传统静态密码与手动输入式一次性验证码&#xff08;OTP&#xff09;长期作为银行业身份核验的主要手段&#xff0c;但该类技术无法抵御钓鱼中继攻击&#xff0c;攻击者借助仿冒站点诱导用户提交验证码即可完成账号接管。通行密钥&#xff08;Passkey&#xff09;依托 WebA…

作者头像 李华