tsParticles 仓库中使用 Nx Generator 高效生成代码的完整指南
【免费下载链接】tsparticlestsParticles - Easily create highly customizable JavaScript particles effects, confetti explosions and fireworks animations and use them as animated backgrounds for your website. Ready to use components available for React.js, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Inferno, Solid, Riot and Web Components.项目地址: https://gitcode.com/GitHub_Trending/ts/tsparticles
导读
本指南面向 tsParticles 这个以 Nx + pnpm workspace 管理的大型 monorepo(仓库根目录nx.json同时声明了@tsparticles/cli-nx-plugin这一本地插件)。你将学会一套"先发现、再匹配、后验证"的生成器使用流程:从nx list发现可用生成器、用--help读取选项、通过--dry-run验证文件落点、阅读生成器源码规避陷阱,最终用 lint / test / build 等目标验证产物。读完本文,你可以安全地在 tsParticles monorepo 中新增一个库或应用,而不会踩中--directory语义、"空测试套件导致nx test失败"等常见坑。
说明:
.cursor/skills/nx-generate/SKILL.md是仓库中为 AI 编码助手准备的 Nx 生成器使用规范,本文以其为骨架,结合nx.json、pnpm-workspace.yaml、@tsparticles/cli-nx-plugin源码与测试、以及cli/commands/*的真实 package 脚本进行扩充,全部结论均可在仓库对应文件验证。
为什么需要一套"生成器使用规范"
Nx Generator(生成器)是 Nx 生态中用于脚手架(scaffold)的自动化工具,除了最常被提及的"创建新项目"之外,它还承担着自动化代码迁移、批量执行重复性任务的角色。在 tsParticles 这类动辄几十个包的 monorepo 中,生成器带来的核心价值是一致性与减少样板代码:每次用同一个生成器产出,文件结构、命名、配置风格都会保持一致。
SKILL.md 将其适用场景归纳为四类:
- 创建新的库(library)或应用(application);
- 脚手架特性代码或样板代码;
- 运行 workspace 专属或自定义生成器;
- 任何其他可以由 Nx 生成器完成的工作。
该规范同时强调四条关键原则,它们贯穿整个使用流程:
- 始终使用
--no-interactive——防止交互式提示导致命令挂起; - 阅读生成器源码——仅看 schema 不够,必须理解生成器实际做了什么;
- 匹配仓库既有模式——研究仓库中相似的产物,遵循它们的约定;
- 用 lint / test / build / typecheck 验证——生成的代码必须通过验证,具体目标以该 workspace 实际可用者为准。
在 tsParticles 仓库中,Nx 的实际接入方式是"npm preset + 本地插件"。仓库根目录 nx.json 中extends: "nx/presets/npm.json",这意味着当前 workspace 不是 nx.json 手动声明每个项目的传统模式,而是通过插件(plugins)自动推导项目;plugins数组里注册了nx/plugins/package-json与@tsparticles/cli-nx-plugin两个插件,其中后者正是 tsParticles 自己的本地 Nx 插件,后文会剖析它的实现。
第一步:发现可用的生成器
规范要求先摸清"有哪些生成器可用",使用 Nx CLI 即可:
# 查看某个插件的全部生成器 npx nx list @nx/react # 查看当前 workspace 可用的全部插件 npx nx listnx list输出的既包括插件自带生成器(如@nx/react:library),也包括本地 workspace 生成器。在 tsParticles 仓库中,本地生成器的形态需要留意:nx.json的plugins字段加载了@tsparticles/cli-nx-plugin,同时cli/packages/nx-plugin/目录下提供了该插件的实现(见 project.json),而仓库内目前没有tools/generators/目录与generators.json文件——也就是说,当前仓库的"本地生成能力"主要来自@tsparticles/cli-nx-plugin这类本地插件,而非传统tools/generators/目录(从源码结构看,若未来新增传统本地生成器,会遵循 Nx 惯例放在tools/generators/下)。
第二步:把生成器与用户诉求匹配
规范给出的匹配逻辑是:先判断用户想要哪种产物类型、涉及哪个框架、有没有点名具体生成器,再从候选里挑出最合适的一个。
其中有一条重要取舍规则值得强调:
当本地 workspace 生成器与外部插件生成器都能满足诉求时,永远优先本地生成器。本地生成器针对当前仓库的模式做了定制。
判定的"举证责任"在于确实没有合适生成器的一方——在断言"没有生成器可用"之前,必须先仔细遍历所有候选。只有确认无一适用,才可以退出本流程。
第三步:用 --help 读取生成器选项
确定生成器后,用--help查看它的选项与默认值:
npx nx g @nx/react:library --help需要重点关注的字段:必填选项、可能需要覆盖的默认值、以及与用户诉求直接相关的选项。
库是否可构建(buildable)的决策
规范特别给出了"库可构建性"的决策表,默认倾向不可构建:
| 类型 | 适用场景 | 生成器标志 |
|---|---|---|
| 不可构建(默认) | 仅被 app 消费的 monorepo 内部库 | 不加--bundler标志 |
| 可构建 | 需要发布到 npm、跨仓库共享、追求缓存命中的稳定库 | --bundler=vite或--bundler=swc |
- 不可构建库:直接导出
.ts/.tsx源码,由消费方的打包器编译,开发体验更快、配置更少; - 可构建库:拥有自己的 build target,适合很少变动、需要缓存命中的稳定库,也是 npm 发布的前提。
如果不确定,直接问用户:"这个库需要是可构建的(自带构建步骤、缓存更好)还是不可构建的(源码直接消费、配置更简单)?"
这一原则在 tsParticles 仓库中有非常直观的印证。每个包(如 cli/commands/create/package.json)都把自己的脚本拆得很细(build:ts、prettify:src、lint:ci、circular-deps等),而构建产物统一输出到dist——根 nx.json 的targetDefaults.build.outputs正是{projectRoot}/dist。这说明"构建"在 tsParticles 里是有独立产物目录的可构建行为;而像各命令包之间的共享类型与工具则倾向于源码级消费。决策时把仓库的这种组织方式当作默认约定即可。
第四步:阅读生成器源码——schema 之外的真实行为
这是规范中最强调的步骤:schema 并不能告诉你全部信息。读源码才能搞清楚:
- 生成器会创建/修改哪些文件、落在哪个位置;
- 有哪些副作用(更新配置、安装依赖等);
- 有哪些 schema 里看不出来的行为与选项;
- 各选项之间如何相互作用。
查找生成器源码的路径有三种:
# 1. 插件生成器:用 node 解析 generators.json 的真实位置 node -e "console.log(require.resolve('@nx/<plugin>/generators.json'));" # 2. 上述方式失败时,直接读 node_modules 里的 generators.json # node_modules/<plugin>/generators.json # 3. 本地生成器:通常在 tools/generators/ 或本地插件目录中,按生成器名在仓库内搜索读完之后要重新评估:这个生成器真的是对的吗?如果不是,回到第二步重选。
在 tsParticles 仓库中,这条"读源码"原则可以直接落在@tsparticles/cli-nx-plugin上。该插件由两个文件构成:
- create-nodes.ts:声明
createNodesV2,匹配所有**/package.json,为符合条件的包自动生成 Nx 项目与 target; - canonical-targets.ts:定义 tsParticles 的"规范别名 target"表。
create-nodes.ts的工作方式值得细读(L53-L90):它对每个命中的package.json做"项目增强"——先由createCanonicalAliasTargets从脚本里推导别名 target,再由createFallbackScriptTargets把build/build:ci脚本映射为回退 target,最终以{projectRoot}为键注入projects,并附带metadata.targetGroups(区分 "tsParticles Nx fallback" 与 "tsParticles Nx aliases" 两组)。
而 canonical-targets.ts 给出了完整的别名映射表:
| 规范别名 target | 候选脚本(candidates) | 说明 |
|---|---|---|
clean | clear:dist | 清理 dist 产物 |
prettify | prettify:src、format | 源码格式化 |
prettify:ci | prettify:ci:src | CI 环境下的格式化检查 |
tsc | compile、build:ts、typecheck | TypeScript 构建 |
bundle:webpack | build:bundle:webpack | Webpack 打包 |
bundle:rollup | build:bundle:rollup | Rollup 打包 |
distfiles | build:distfiles | 生成 dist 相关文件 |
结合cli/commands/create/package.json的真实脚本可以看到,build是一个串联了clear:dist、prettify:src、lint、compile、circular-deps、prettify:readme的复合命令——这正是"别名化"要解决的问题:不同包可能用compile、build:ts或typecheck表达同一个"跑 TypeScript 编译",别名tsc把这些差异统一起来,让 Nx 目标调用口径一致。规范中"读源码以理解 side effects"的意义在此体现得淋漓尽致:不读canonical-targets.ts,你根本不会知道nx run-many -t tsc在这些包里分别映射到了什么脚本。
插件的行为还受到isTsParticlesWorkspacePackage的过滤(L102-L115):只有路径以commands/、packages/、utils/开头(含cli/前缀归一化后的情况)的 package 才被认为是 tsParticles 工作区包,且凡是路径中包含/files/(模板文件目录)的 package.json 一律跳过——因为那些只是脚手架模板,不应注册为 Nx 项目。这一逻辑在 create-nodes.test.ts 中有直接的单测佐证。
⚠️--directory标志的语义陷阱
规范特别用一段警告框强调--directory的行为容易误导:
--directory应该指定生成的库或组件的完整路径,而不是"它将要被生成到其下的父目录"。
# ✅ 正确——directory 是库的完整路径 nx g @nx/react:library --directory=libs/my-lib # 会生成 libs/my-lib/package.json 等文件 # ❌ 错误——这会在 libs 与 libs/src/... 下创建文件 nx g @nx/react:library --name=my-lib --directory=libs # 会生成 libs/package.json 等在 tsParticles 中,包的物理布局本身就是"目录即包":pnpm-workspace.yaml声明的 glob(如cli/commands/*、cli/packages/*、bundles/*、plugins/*、shapes/*)决定了每个包目录就是一个独立 npm 包,且多数包名与目录名一一对应(如@tsparticles/cli-nx-plugin位于cli/packages/nx-plugin)。因此这里--directory的正确用法与仓库的既有组织方式天然吻合:直接给出包的完整目录路径,而不是父目录。
第五步:研究仓库既有模式
生成之前,先考察目标区域:
- 查看相似的既有产物(其他库、应用等);
- 确认命名约定、文件结构与配置模式;
- 记录它们使用的测试运行器、构建工具与 linter;
- 据此配置生成器,让产物与既有模式对齐。
以 tsParticles 为例,如果要在cli/commands/下新增一个命令包,可以从 cli/commands/create/package.json 观察到标准模式:type: module、prettier统一指向@tsparticles/prettier-config、脚本族包含prettify:*、lint(:ci)、compile(:ci)、build:ts、test(vitest run)、build/build:ci串联全流程;目录里固定配套eslint.config.js、tsconfig.json、vitest.config.ts、renovate.json、project.json。新增包时,让生成器产出对齐这套约定即可。根 package.json 还说明测试跑在 vitest、格式化用 prettier(含prettier-plugin-multiline-arrays)、ESLint 采用typescript-eslint与eslint-plugin-tsdoc,这些都是"目标"层面要考虑的既有模式。
第六步:先用 --dry-run 验证文件落点
永远先跑一次--dry-run,确认文件会落在正确位置:
npx nx g @nx/react:library --name=my-lib --dry-run --no-interactive仔细审查输出。如果文件会落在错误位置,就根据第四步读源码得到的认知调整选项。
需要说明的限制:某些生成器不支持 dry-run(例如它会安装 npm 包的情况)。如果 dry-run 因此失败,可以直接真实运行生成器。
第七步:正式运行生成器
验证通过后执行生成:
nx generate <generator-name> <options> --no-interactive规范还附带一条实用提示:新包往往需要接线 workspace 依赖(例如导入共享类型、被 app 消费),此时可以借助link-workspace-packages技能正确添加。在 tsParticles 中这一点同样成立——pnpm-workspace.yaml设置了linkWorkspacePackages: deep,包间依赖以workspace:*协议互联(如根package.json中的"@tsparticles/cli-nx-plugin": "workspace:*"),新包若依赖@tsparticles/engine或共享工具包,应沿用该协议并注意包目录间的相对关系。
第八步:按需修改生成产物
生成器只提供起点。按需调整产物:
- 按请求新增或修改功能;
- 调整导入、导出或配置;
- 与既有代码模式集成。
关键警告:如果替换或删除了生成的测试文件(如*.spec.ts),要么写出有意义的替代测试,要么从项目配置中移除testtarget——空的测试套件会让nx test失败。
这一点在 tsParticles 有直接的正面与反面证据:@tsparticles/cli-nx-plugin自己就带了一份有意义的测试 create-nodes.test.ts,用两个describe分别覆盖createCanonicalAliasTargets(别名生成、不覆盖已有脚本)与isTsParticlesWorkspacePackage(路径匹配判定)——这正是"删除测试就要补上有意义的测试"的仓库内范例。
第九步:格式化并验证
格式化所有生成/修改的文件:
nx format --fix(这是 Nx 内置 prettier 格式化的示例;如果 workspace 使用其他格式化工具,应优先用它们。)
随后验证生成代码可用。要注意:生成器带来的改动可能影响多个项目,通常只跑新建产物的 target 是不够的:
# 这些 target 只是示例! nx run-many -t build,lint,test,typecheck这些是许多 workspace 的常见目标;你应当调研当前 workspace 及其项目实际可用的其他 target。CI 配置通常是判断"必须通过的关键目标"的可靠指南。
对 tsParticles 而言,"调研 workspace 实际目标"完全可以落到两处:
- CI 工作流:仓库
.github/workflows/下的nodejs.yml、npm-publish.yml等定义了发布与验证流水线,是判断关键目标的第一手材料; - 根 package.json 脚本:
build(nx run-many -t build --parallel=50%)、build:ci、build:affected等展示了批量目标的标准写法;nx.json的targetDefaults则为build/build:ci声明了dependsOn: ["^build"](先构建依赖)与缓存输出目录。
另外,得益于@tsparticles/cli-nx-plugin的别名机制(见第四步),验证时除了脚本原名,还可以直接使用规范化的别名目标:nx run-many -t clean,prettify,prettify:ci,tsc,bundle:webpack,bundle:rollup,distfiles——别名对已有同名脚本的包不会重复生成(有测试覆盖 create-nodes.test.ts),所以可以安全地在整个仓库范围内统一调用。
附:本仓库配套的 CLI 生成器工具链
虽然 SKILL.md 的核心是"使用 Nx 生成器",但在 tsParticles 中,"生成新包"还有一个仓库自带的 CLI 工具链与之互补:cli/commands/下的create-*系列命令(create-app、create-bundle、create-effect、create-interaction、create-palette、create-path、create-plugin、create-preset、create-shape、create-updater、create-utils),它们以模板方式在cli/commands/create-*各自的files/目录中预置了不同场景的脚手架内容,并以独立包(如cli/packages/create-confetti、cli/packages/create-particles)发布为create-*可执行命令。当诉求是"新增一种效果/形状/预设"时,这些 CLI 脚手架与 Nx 生成器互为补充;而本指南聚焦的 Nx 生成器流程,负责的是 monorepo 内库与应用的规范化创建。
结语
把 SKILL.md 的九步流程放到 tsParticles monorepo 中实践,本质上是三件事:先发现与匹配(nx list→ 选生成器 →--help读选项)、先理解再执行(读生成器源码 → 研究既有包模式 →--dry-run→ 正式生成)、改完必验证(nx format --fix→ 以 CI 与根脚本为准跑run-many验证)。而@tsparticles/cli-nx-plugin的别名 target 机制(clean/prettify/tsc/bundle:rollup等)则为全仓库统一验证提供了便利。遵循这套规范,你可以在保持 tsParticles 既有包结构一致性的前提下,低风险地扩展这个庞大的粒子效果 monorepo。
【免费下载链接】tsparticlestsParticles - Easily create highly customizable JavaScript particles effects, confetti explosions and fireworks animations and use them as animated backgrounds for your website. Ready to use components available for React.js, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Inferno, Solid, Riot and Web Components.项目地址: https://gitcode.com/GitHub_Trending/ts/tsparticles
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考