Ripple CLI 版本演进与脚手架实战:从 @ripple-ts/cli 的 CHANGELOG 看项目创建流程实现
【免费下载链接】ripplethe elegant TypeScript UI framework项目地址: https://gitcode.com/GitHub_Trending/ripple25/ripple
本文以 packages/cli/CHANGELOG.md 为主线,梳理 Ripple 官方 CLI(@ripple-ts/cli)的版本演进脉络与每次关键变更的技术动机,并结合 CLI 源码与basic模板文件,还原npx @ripple-ts/cli create背后的完整脚手架流程:模板下载、package.json 改写、样式框架集成与包管理器版本锁定。读完后你将能够熟练使用该 CLI 创建 Ripple 应用,并理解每条变更记录对应仓库中的哪些代码实现。
一、@ripple-ts/cli 定位与当前版本
@ripple-ts/cli是 Ripple 提供的交互式项目脚手架工具,用于快速创建新的 Ripple 应用。从 packages/cli/package.json 可以看到以下关键事实:
- 包名
@ripple-ts/cli,当前仓库内版本为0.3.127(与 CHANGELOG 顶部版本一致); bin入口指向./dist/index.js,即发布后可执行命令为@ripple-ts/cli;- 运行环境要求
engines.node >= 22.0.0——这一点与 CHANGELOG 中0.3.20的变更("chore: drop Node 20 support")相互印证,当前 CLI 仅支持 Node 22 及以上版本; - 依赖了
commander(命令行解析)、prompts(交互式提问)、degit(模板下载)、ora(加载指示)、kleur(终端着色)等库,从依赖结构看,CLI 的核心职责就是“交互式参数收集 + 模板下载复制 + 工程化改写”。
另外,仓库还提供了语法更简洁的入口 packages/create-ripple/src/index.js,其实现只有一行import '@ripple-ts/cli';,即create-ripple只是对@ripple-ts/cli的二进制转发包装,两个入口能力完全等价。
二、使用方法与命令参数
根据 packages/cli/README.md 与 packages/cli/src/index.js,CLI 支持的使用方式如下:
# 无需预先安装,直接运行 npx @ripple-ts/cli <command> # 交互式创建项目 npx @ripple-ts/cli create # 带参数创建 npx @ripple-ts/cli create my-app --yes --no-git参数说明(以 packages/cli/src/index.js 中的 commander 定义为准):
| 参数 | 说明 | 默认值 |
|---|---|---|
[project-name] | 可选的位置参数,项目名 | 未提供时进入交互式提问 |
-t, --template <template> | 指定模板 | 仅basic一种(见 packages/cli/src/constants.js 中TEMPLATES只定义了basic) |
-p, --package-manager <pm> | 包管理器,支持 npm、yarn、pnpm、bun | 自动检测当前运行 CLI 所用的包管理器 |
--no-git | 跳过 Git 仓库初始化 | 默认询问,--yes模式下默认执行git init |
-y, --yes | 跳过所有提示并采用默认值 | — |
几个源码层面的行为细节值得注意:
- 无子命令即显示帮助:程序通过
program.parse()启动,未提供子命令时由 commander 输出帮助信息; - 包管理器自动检测:packages/cli/src/commands/create.js 中会先调用
getCurrentPackageManager()探测当前实际执行 CLI 的包管理器,作为交互式选择或--yes模式下的默认值; --yes的隐式默认:从源码看,--yes模式下gitInit默认为true(执行git init),样式框架固定为vanilla,即不询问 Tailwind/Bootstrap;- 目录冲突保护:若目标目录已存在且非空(
isFolderEmpty判断),CLI 直接退出; - 创建完成后的 Next steps:CLI 会按所选包管理器打印对应的
install/dev命令,并提示访问http://localhost:3000、在src/目录中修改代码——端口 3000 与模板中 Vite 配置一致(见下文)。
项目名校验规则
在提供project-name位置参数时,CLI 会先走 packages/cli/src/lib/validation.js 的validateProjectName,规则与 npm 包命名约定对齐:
- 长度不超过 214 个字符;
- 仅允许小写字母、数字、连字符、点、下划线(正则
/^[a-z0-9._-]+$/); - 不能以点或下划线开头,不能以点结尾,不能包含连续点;
- 禁止使用
node_modules、favicon.ico、con、prn、com1–com9、lpt1–lpt9等保留名。
交互式提问模式下同样的校验逻辑被注入prompts的validate回调中(见 packages/cli/src/lib/prompts.js)。
三、CHANGELOG 版本脉络
packages/cli/CHANGELOG.md 记录了@ripple-ts/cli从 0.2.210 到 0.3.127 的完整版本线(中间还出现过一次 1.0.x 的版本,下文专门说明)。绝大部分版本是 changesets 流程下随其他包联动产生的空条目,真正影响使用者的变更集中在以下几个节点,按时间从旧到新排列:
| 版本 | 变更内容 | 源码印证 |
|---|---|---|
| 0.3.4 | 升级到 Vite 8 | templates/basic/package.json 中vite: ^8.1.5 |
| 0.3.9 | 将 Tailwind 脚手架更新为 v4 CSS-first 配置 | packages/cli/src/lib/project-creator.js 中configureStyling |
| 0.3.20 | 移除 Node 20 支持 | packages/cli/package.json 中engines.node >= 22.0.0 |
| 0.3.26 | TypeScript 插件包更名为@tsrx/typescript-plugin,同步更新本地消费者、模板与 playground | 模板 devDependencies 与 tsconfigplugins字段 |
| 0.3.34 | 为 typescript-plugin 增加prepare脚本,确保 dist 一定被构建并随包发布 | 发布流程变更,保证main指向 dist 的包可用 |
| 0.3.48 | 新模板启用 strict 检查,使被追踪的值在编辑器悬浮提示中保留 nullable 类型 | templates/basic/tsconfig.json 中"strict": true |
| 0.3.51 | 修复一次误操作:某个 minor changeset 意外触发了 major 1.0.0 发布,0.3.50 及相邻版本被回补修正 | CHANGELOG 中出现的## 1.0.1、## 1.0.0空条目 |
| 0.3.67 | 基础模板添加skipLibCheck | templates/basic/tsconfig.json 中"skipLibCheck": true |
| 0.3.109 | 生成的 pnpm 项目固定(pin)pnpm 11.15.1 | packages/cli/src/lib/project-creator.js 中getPackageManagerVersion的pnpm@11.15.1 |
| 0.3.125 | 目标无关的 TSRX 源码迁往独立的tsrx-org/tsrx后,CLI 改为直接消费其已发布包;新 Ripple 项目使用@tsrx/language-server、TSRX 编辑器身份与已发布的 TSRX 集成 | 模板 devDependencies 中的@tsrx/*包 |
其中 0.3.51 的条目值得多一句解释:CHANGELOG 里## 1.0.1/## 1.0.0两个紧随 0.3.52 的空版本,对应的正是那次 changesets 版本误升——“用 minor changeset 却 bump 出 major 1.0.0”。团队随后发布补丁包修复版本号,1.0.x 因此只留下了两个没有变更说明的空标题。这是一个很典型的 monorepo 发布事故现场,也说明该 CLI 的主版本线实际停留在 0.3.x。
四、关键变更的源码级解析
4.1 TSRX 工具链外置(0.3.125)
0.3.125 的变更是整个版本线中架构影响最大的一条:TSRX(Ripple 所使用的 TS 方言)中与目标平台无关的编译器/工具链源码被迁移到独立的tsrx-org/tsrx仓库并以 npm 包形式发布,Ripple CLI 从“随仓库内置”转为“消费已发布包”。
这一变化直接反映在 CLI 生成新项目的依赖注入逻辑中。packages/cli/src/lib/project-creator.js 的updateDependencyVersions会把模板中出现的以下包统一改写为latest:
ripple、@ripple-ts/vite-plugin、@tsrx/prettier-plugin、 @tsrx/eslint-plugin、@tsrx/eslint-parser、@tsrx/language-server、@tsrx/typescript-plugin对照 templates/basic/package.json,模板本身就声明了@tsrx/language-server、@tsrx/typescript-plugin、@tsrx/eslint-plugin、@tsrx/eslint-parser、@tsrx/prettier-plugin等 devDependencies,配合 templates/basic/tsconfig.json 中的"plugins": [{ "name": "@tsrx/typescript-plugin" }],可以确认:新创建的每个 Ripple 项目的编辑器智能提示(语言服务)与类型检查,都由 TSRX 侧独立发布的包承担,Ripple 仓库只保留运行时框架ripple与 Vite 集成@ripple-ts/vite-plugin。
4.2 包管理器版本锁定(0.3.109)
0.3.109 的变更是“Update generated pnpm projects to pin pnpm 11.15.1”。实现位于 packages/cli/src/lib/project-creator.js 的updatePackageJson:当所选包管理器不是 npm 时,CLI 会向生成项目的package.json写入packageManager字段,取值来自getPackageManagerVersion:
| 包管理器 | 写入的 packageManager 字段 |
|---|---|
| yarn | yarn@4.0.0 |
| pnpm | pnpm@11.15.1 |
| bun | bun@1.3.0 |
这正是 changesets 风格的精确版本钉扎:生成的项目会携带核心包管理器(corepack)可识别的版本声明,保证不同开发者的工具链版本一致。pnpm 的值与 0.3.109 变更记录中的 “pin pnpm 11.15.1” 逐字对应。
4.3 Tailwind v4 CSS-first 脚手架(0.3.9)
0.3.9 将 Tailwind 脚手架更新为 v4 的 CSS-first 配置,源码见configureStyling:选择tailwind时,CLI 会:
- 覆写
src/index.css为@import "tailwindcss";——v4 不再需要tailwind.config.js,内容源自动检测,主题定制用 CSS 中的@theme; - 在
src/index.ts头部注入import './index.css';; - 删除模板原
vite.config.js并重新生成,加入@tailwindcss/vite插件与server.port: 3000; - 生成
.vscode/settings.json,配置 Tailwind IntelliSense 对.tsrx文件的识别(tailwindCSS.includeLanguages将 tsrx 映射为 html、files.associations将*.tsrx关联到 tsrx 语言),保证工具类 class 在 Ripple 组件文件中能被补全。
依赖版本上,Tailwind 写入 devDependencies 的固定版本是tailwindcss: ^4.1.12与@tailwindcss/vite: ^4.1.12;若选择bootstrap,则向 dependencies 注入bootstrap: ^5.3.0并在入口注入其 CSS。这与 CHANGELOG 中 “update Tailwind scaffolding to v4 CSS-first config” 的记录完全对应。
4.4 Node 22 与 Vite 8(0.3.20 / 0.3.4)
0.3.20 移除 Node 20 支持后,packages/cli/package.json 的engines与 templates/basic/package.json 中生成项目的engines均声明node >= 22.0.0,即 CLI 本身与它生成的项目共享同一 Node 基线。0.3.4 升级 Vite 8 后,模板 devDependencies 固定为vite: ^8.1.5,templates/basic/vite.config.js 则以defineConfig形式注册ripple()插件并设置build.target: 'esnext'。
五、create 命令的完整执行流程
结合 packages/cli/src/commands/create.js 与 packages/cli/src/lib/project-creator.js,一次create调用的完整调用链如下:
参数收集阶段(create.js 的createCommand)
- 项目名:未提供则交互式提问(默认值
my-ripple-app),提供则校验合法性; - 目录检查:目标路径已存在且非空则退出;
- 模板:未提供则询问;当前
TEMPLATES列表只有一项basic,packages/cli/src/lib/prompts.js 中promptTemplate会在选项数为 1 时自动跳过提问直接采用basic; - 包管理器:交互式模式下以检测到的包管理器为初始选项,四选一(npm/yarn/pnpm/bun);
--yes模式直接取检测值或--package-manager显式值; - Git 初始化与样式框架(vanilla/bootstrap/tailwind):
--yes时分别取true与vanilla,其余情况逐项询问。
项目落盘阶段(project-creator.js 的createProject)
- 获取模板:
isLocalDevelopment()会向上探测 monorepo 根目录下的templates/目录(相对packages/cli/src/lib/上溯四级,对应仓库根),存在则直接使用本地 templates/basic 目录——这是仓库内开发调试路径;否则调用 packages/cli/src/lib/templates.js 的downloadTemplate,通过degit从Ripple-TS/ripple仓库main分支的templates/<name>子目录下载到系统临时目录(常量定义在 packages/cli/src/constants.js:GITHUB_REPO、GITHUB_BRANCH、GITHUB_TEMPLATES_DIRECTORY),下载失败会抛出带模板名的明确错误; - 创建目录并复制:
mkdirSync递归建目录后cpSync复制,filter回调显式跳过node_modules与各类锁文件(package-lock.json、yarn.lock、pnpm-lock.yaml、bun.lock),保证新项目从干净状态安装依赖; - 改写 package.json:项目名替换为
basename(projectName),模板占位版本0.0.0提升为1.0.0,写入 description,非 npm 场景写入packageManager字段,按选择注入样式依赖,并把 Ripple/TSRX 系依赖统一改写为latest; - 样式配置:即上文 4.3 所述的 Tailwind/Bootstrap 分支;
- Git 初始化:
gitInit为真时执行git init,失败仅告警不阻断(“Git initialization failed (optional)”); - 清理:下载得到的临时模板目录无论成败都会被
rmSync清理。
六、脚手架产物:basic 模板长什么样
综合模板文件与 CLI 的改写逻辑,create完成后你得到的最小 Ripple 应用包含:
templates/basic/package.json 的核心内容(经 CLI 改写后 name/version 变为实际项目信息):
{ "type": "module", "engines": { "node": ">=22.0.0" }, "scripts": { "start": "vite", "dev": "vite", "build": "vite build", "lint": "eslint .", "typecheck": "tsrx-tsc --noEmit", "serve": "vite preview", "format": "prettier --write .", "format:check": "prettier --check ." }, "dependencies": { "ripple": "latest" }, "devDependencies": { "eslint": "^9.0.0", "@tsrx/eslint-plugin": "latest", "@tsrx/eslint-parser": "latest", "@tsrx/prettier-plugin": "latest", "@tsrx/language-server": "latest", "@tsrx/typescript-plugin": "latest", "@ripple-ts/vite-plugin": "latest", "prettier": "^3.6.2", "typescript": "^5.9.3", "vite": "^8.1.5" } }注意typecheck脚本使用tsrx-tsc --noEmit,即类型检查由 TSRX 的工具链完成,而非原生tsc——这与 0.3.125 “消费已发布 TSRX 包”的变更一脉相承。
templates/basic/tsconfig.json体现了 0.3.48 与 0.3.67 两条变更记录的落地:"strict": true让.ripple()追踪值在编辑器悬浮中保留 nullish 类型;"skipLibCheck": true跳过声明文件检查以提升 IDE 性能;"jsx": "preserve"+"jsxImportSource": "ripple"声明 JSX 由 Ripple 编译器接管(noEmit下仅做类型层处理);"plugins": [{ "name": "@tsrx/typescript-plugin" }]挂接 TSRX 语言插件。
templates/basic/vite.config.js只有两个要点:注册ripple()Vite 插件、开发服务器固定在 3000 端口——与 CLI 完成后打印的http://localhost:3000提示保持一致。
七、适用前提与限制小结
- 适用前提:Node.js >= 22(CLI 与生成项目共同基线,来自两处 package.json 的
engines声明); - 当前仅
basic一个模板,--template传入其他值会被validateTemplate拒绝并打印可用列表; - 非 monorepo 场景下模板经
degit从 GitHubmain分支拉取,属于网络依赖步骤; - README 中“Node.js 20.0.0 or higher”的旧表述与
engines及 0.3.20 的变更记录不一致,以engines.node >= 22.0.0与 CHANGELOG 为准; - 生成的项目依赖 Ripple/TSRX 系包被统一钉为
latest,意味着新项目永远跟踪各包最新稳定发布,这是 CHANGELOG 0.3.125 之后“消费已发布包”策略的直接产物。
整体来看,@ripple-ts/cli的 CHANGELOG 虽然条目稀疏,但每一条有说明的 patch 都能在当前仓库的源码与模板中找到对应实现:TSRX 工具链外置、pnpm 版本钉扎、Tailwind v4 CSS-first、strict/skipLibCheck 的模板演进、Node 22 基线与 Vite 8 升级。理解这条版本线,基本也就掌握了 Ripple 项目脚手架的全部工程化细节。
【免费下载链接】ripplethe elegant TypeScript UI framework项目地址: https://gitcode.com/GitHub_Trending/ripple25/ripple
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考