
Next.js App Router TypeScript 插件测试指南typescript-plugin fixture 结构与验证方法【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js本文是一份面向 Next.js 贡献者与高级使用者的技术指南围绕仓库中的 typescript-plugin 测试 fixture 展开讲解如何对 Next.js 内置的 App Router TypeScript 语言服务插件进行手工 IDE 验证与自动化回归测试并深入其插件源码、错误码体系与各类 fixture 场景客户端组件 prop 序列化、Client Boundary、metadata 补全与告警。读完你将掌握该插件的能力边界、触发方式以及如何在仓库内为其新增或维护测试。为什么需要一个独立 fixture 来测 TypeScript 插件Next.js 的 TypeScript 插件源码位于 packages/next/src/server/typescript/index.ts是一个TypeScript 语言服务插件它运行在编辑器进程中通过包装LanguageService对代码提供诊断、补全和 hover 提示。其顶部注释明确列出了四类能力警告服务端组件中不允许使用的 React API对应 rules/server 下的server规则警告 layout/page 不允许的导出entry规则为入口配置如dynamic、runtime、revalidate提供自动补全为入口配置提供 hover 文档。由于这类插件只对编辑器生效命令行tsc不会加载tsconfig.json中声明的plugins行为无法完全靠普通的单测模拟 UI因此仓库在 test/development/typescript-plugin 维护了一整套fixture测试夹具既有供人工在 VSCode 中体验的样例应用也有用 TypeScript 语言服务 API 直接驱动插件跑的自动化用例。Getting started在 VSCode 中手动体验插件fixture 的 README 给出了三步人工验证流程在 monorepo 根目录执行pnpm install安装依赖fixture 通过 workspace 解析到本地next包从而加载到正在开发的插件版本在 VSCode 中打开该 fixture 的任意 TypeScript 文件将 TypeScript 版本切换为Workspace 版本通过命令面板TypeScript: Select TypeScript Version→Use Workspace Version让 VSCode 使用工作区安装的 tsserver 加载插件。插件在tsconfig.json中按标准 TypeScript 插件协议声明。以 fixture 根 tsconfig 为例{ compilerOptions: { target: ES2017, module: esnext, moduleResolution: bundler, jsx: react-jsx, plugins: [ { name: next } ] } }源码 index.ts 中可以看到enabled开关的处理info.config.enabled ?? true即默认启用也可显式写{ name: next, enabled: false }关闭并直接返回原生LanguageService。插件在启动时会打印一条日志[next] Initialized Next.js TypeScript plugin自动化用例正是用该日志断言插件确实被加载。自动化测试基座用 TypeScript LanguageService 直接驱动插件仅靠 VSCode 人工验证无法进入 CI因此 test-utils.ts 在 Node 环境里手工组装了 tsserver 所需的最小环境用ts.sys.readDirectory读取目录内全部文件作为宿主提供的脚本文件列表构造ts.LanguageServiceHost与ts.createLanguageService再按ts.server.PluginCreateInfo的形状注入project、languageService、config用工厂方式调用插件模块(tsNextPluginFactory)({ typescript: ts })随后plugin.create(pluginCreateInfo)得到被包装后的服务额外注入一个捕获 logger 与自定义方法getCapturedLogs()供测试断言插件的初始化日志。基于该基座测试可以像编辑器一样查询语义诊断与quick info悬停信息。其中 index.test.ts 通过getQuickInfoTestAdapter拦截原生getQuickInfoAtPosition制造“原生 TS 文档已存在/不存在”两种前提用来验证插件对 quick info 的合成与合并行为参数转发插件必须原样透传(fileName, position, maximumLength, verbosityLevel)四个参数不能吞掉编辑器传来的额外参数有效配置值如 app/quick-info/page.tsx 中的dynamic force-static悬停时既保留原生文档、又追加 Next.js 的force-static说明断言含forces caching of all fetches与“”指引同时canIncreaseVerbosityLevel保持为trueTS 无原生文档时如dynamicParams true插件需自行合成 quick infokind为enumElement文档含Allow rendering dynamic params非法配置值如runtime invalid-runtime插件会用合成的覆盖信息替换原生文档原生文档不再出现提示用户该值非法函数内部标识符generateMetadata函数体内的普通变量如metadataTitle不得被误合成应保留原生行为配置函数本身对generateMetadata标识符追加Next.js generateMetadata configurations一类的增强文档。这些断言精确刻画了插件的 quick info 策略是防止后续改动破坏 IDE 体验的第一道防线。场景一客户端组件 prop 的可序列化校验插件会校验“use client”入口文件暴露的组件 props 是否可跨网络边界序列化。fixture 用三种文件对照验证规则边界serializable-props.tsx声明string、number、boolean、string[]、{ some: string }、null、undefined七种可序列化类型断言零诊断non-serializable-props.tsx声明函数、箭头函数类型别名、类实例、构造签名等不可序列化类型断言触发错误码71007non-serializable-action-props.tsx把同样形态的 props 命名为_xxxAction/_xxxFunctionAction验证Server Action 的豁免——函数只要名字是action或以Action结尾就被视为可传递的 Server Action 而放行。值得注意的细节是诊断消息的可操作性。以 client-boundary.test.ts 中的 inline snapshot 为例对普通函数 prop插件不只是报“不可序列化”还会给出改名建议Rename _arrowFunction either to action or have its name end with Action。同时类实例_classAction与构造签名_constructorAction即便带上了Action后缀也仍被标记因为类本身永远无法序列化——测试注释将其称为对命名启发式的“漏洞检查”。测试里还保留了一条 TODO(() void) | null这类联合类型期望在 TypeScript 6.x 中进一步覆盖。场景二error 边界中框架注入 props 的豁免error.tsx与global-error.tsx是 App Router 的特殊文件Next.js 会向其中的错误组件注入error、reset等 propsglobal-error.tsx 中还有retry。若插件把它们当作普通函数 prop 报 71007开发者将无法正确编写错误边界。因此 app/error.tsx 与 app/global-error.tsx 的注释与用例专门验证该豁免reset与retry都不应被标记而豁免必须“边界化”——同一文件里新加的普通函数 prop_notExempt仍应被标记相关断言见 client-boundary.test.ts。这防止豁免规则被滥用为“error 文件里随便写函数都行”。场景三metadata 与 generateMetadata 的补全、告警与类型校验metadata 相关能力被拆成两层 fixture。补全与“客户端禁止”场景位于 fixture 顶层app/metadata/completion/page.tsx 是一个空白 page文件尾注释引导手工测试者输入export const即可看到metadata、generateMetadata以及源码常量表中的generateViewport等补全候选app/metadata/client/page.tsx 是带use client的页面却导出了metadata与generateMetadata用于验证“客户端组件中不允许 metadata 导出”的告警路径。类型存在性告警warn-no-type是一个庞大的用例矩阵位于 metadata/app/warn-no-type由 warn-no-type.test.ts 驱动。该矩阵把若干维度做笛卡尔积对象是metadata还是generateMetadata是否显式标注类型has-type期望零诊断no-type期望触发告警类型来源是next导入的还是其他来源导出方式是内联inline还是分离separate声明函数形态是同步/异步 × 普通函数/箭头函数/函数表达式。组合结果形成export-inline-from-next-sync-arrow-function这类高度描述性的目录名每个目录下都是一个最小layout.tsxpage.tsx对。之所以要如此细致地做矩阵是因为插件需要区分“从next正确导入类型却漏标类型”与“随意声明一个无类型的对象”这两种情况并确保对 metadata 的推断不误伤其余导出形态。错误码体系理解断言背后的编号fixture 中的多数断言都指向固定的错误码其定义集中在 packages/next/src/server/typescript/constant.ts错误码常量含义71001INVALID_SERVER_API服务端组件使用了被禁止的 React API71002INVALID_ENTRY_EXPORT入口文件存在非法导出71003INVALID_OPTION_VALUE入口配置选项值非法71004MISPLACED_ENTRY_DIRECTIVE入口指令位置错误71005INVALID_PAGE_PROPpage 组件接收了非法 props71006INVALID_CONFIG_OPTION非法配置选项71007INVALID_CLIENT_ENTRY_PROP客户端入口组件存在不可序列化 props71008INVALID_METADATA_EXPORT非法的 metadata 导出71009INVALID_ERROR_COMPONENT错误组件形态非法71010INVALID_ENTRY_DIRECTIVE非法入口指令71011INVALID_SERVER_ENTRY_RETURN服务端入口返回值非法客户端边界用例中过滤NEXT_TS_ERRORS.INVALID_CLIENT_ENTRY_PROP71007的做法就是通过该常量表按语义精准挑选诊断而不是靠硬编码数字。同一常量文件还记录了其他规则依据合法导出集合ALLOWED_EXPORTS含config、generateStaticParams、metadata、generateMetadata、viewport、generateViewport服务端组件禁用 API 清单DISALLOWED_SERVER_REACT_APIS覆盖useState、useEffect、createContext等以及 page/layout 各自允许的 propsparams、searchParams与params、children。这些清单正是 plugin 各 rules 文件config、server、entry、client-boundary、server-boundary、metadata、error的诊断依据。如何运行与维护这套测试该目录下的*.test.tsindex.test.ts、client-boundary.test.ts、warn-no-type.test.ts属于仓库统一的 Jest 测试体系由根目录的 jest.config.js 等配置收集执行运行前先按 AGENTS.md 了解测试相关的运行脚本约定即可把执行范围限定到该目录。大部分断言使用toMatchInlineSnapshot因此在本地跑测试时若插件行为有变Jest 会提示快照差异便于评审者逐条核对诊断文本、start/length是否仍符合预期。补全completion这类强交互能力目前主要通过 app/metadata/completion/page.tsx 等夹具配合 VSCode 人工走查自动化侧重诊断与 quick info二者互补这也是 README 强调“插件只对 VSCode 生效、需要手工验证”的原因。小结test/development/typescript-plugin不仅是测试代码更是插件行为的“活文档”它通过精心组织的夹具目录把 Client Boundary 序列化规则、error 边界豁免、metadata 补全与类型告警等特性固化成可重复验证的契约。当你为 App Router 新增入口配置、调整错误文案或放宽某条诊断规则时第一件事应当是到这个目录补一个最小 fixture让 IDE 体验的变更始终处于自动化与人工双重检验之下。【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考