zx@lite:zx 脚本工具的极简核心版本、功能矩阵与分发实现原理
本文围绕 zx 官方文档中的 zx@lite 主题展开:先讲清这个精简发行渠道的定位、安装方式与全量版的完整功能差异矩阵,再结合仓库源码剖析 zx@lite 包是如何由构建脚本自动裁剪、打包与发布的,帮助你在为自有工具链选型 zx 依赖时做出准确判断,并能读懂其底层分发机制。
zx@lite 是什么
zx@lite 是 zx 的“仅核心功能”版本。它剥离了全部扩展能力,只保留最底层的核心函数,官方文档(docs/lite.md)给出的要点是:
- 体积约为全量版的 1/7(~7x smaller than the full version);
- 不内嵌 CLI、文档与 manpage 等资产;
- 包名与全量版完全相同(都是
zx),只是通过不同的 npm publish channel 区分——即@lite; - 代码更少,意味着更快的加载与更可靠的 ISEC(供应链安全)审计面;
- 官方推荐基于 zx 构建自有工具包(custom toolkits)的项目使用它。
安装命令在 docs/lite.md 中明确给出两种写法:
npm i zx@lite
npm i zx@8.5.5-lite
第一种跟随 lite channel 拉取最新的精简版;第二种锁定到具体版本的精简发行(版本号后带 -lite 后缀)。安装后核心 API 的用法与全量版一致:
import { $ } from 'zx'
await $`echo foo`
注意这里导入名仍然是 'zx',而不是 'zx/lite'——因为精简版发布时保留了原包名,只是 package.json 的 exports 与 files 被重写为只指向核心入口。
功能矩阵:latest 与 lite 的完整差异
docs/lite.md 指向详细对比文档 versions,该页面说明 zx 以三个 channel 分发:@latest(功能完整的稳定版)、@lite(核心与扩展分离后的精简版)、@dev(实验性快照与 RC)。两者逐 API 的差异如下(完整版为 ✔,lite 版缺失的条目即被裁剪的扩展):
| Feature | latest | lite |
|---|---|---|
| zx/globals | ✔ | |
| zx/cli | ✔ | |
$ |
✔ | ✔ |
ProcessPromise |
✔ | ✔ |
ProcessOutput |
✔ | ✔ |
argv |
✔ | |
cd |
✔ | ✔ |
chalk |
✔ | ✔ |
defaults |
✔ | ✔ |
dotenv |
✔ | |
echo |
✔ | |
expBackoff |
✔ | |
fetch |
✔ | |
fs |
✔ | |
glob |
✔ | |
kill |
✔ | ✔ |
log |
✔ | ✔ |
minimist |
✔ | |
nothrow |
✔ | |
os |
✔ | ✔ |
parseArgv |
✔ | |
path |
✔ | ✔ |
ps |
✔ | ✔ |
question |
✔ | |
quiet |
✔ | |
quote |
✔ | ✔ |
quotePowerShell |
✔ | ✔ |
resolveDefaults |
✔ | ✔ |
retry |
✔ | |
sleep |
✔ | |
spinner |
✔ | |
syncProcessCwd |
✔ | ✔ |
tempdir |
✔ | |
tempfile |
✔ | |
updateArgv |
✔ | |
useBash |
✔ | ✔ |
usePowerShell |
✔ | ✔ |
usePwsh |
✔ | ✔ |
version |
✔ | |
which |
✔ | ✔ |
within |
✔ | ✔ |
YAML |
✔ | |
MAML |
✔ |
从矩阵可以清楚看到边界:lite 保留的是“进程执行 + 环境操作”这条主链路——$ 模板命令、ProcessPromise/ProcessOutput 两大核心类、cd/kill/within/defaults/resolveDefaults 等配置与目录函数、useBash/usePwsh/usePowerShell 等 shell 切换、log/chalk/which/ps/quote 等基础工具;而 glob、fs、dotenv、fetch、retry、spinner、tempdir 等便利扩展以及 zx/cli、zx/globals 子入口则只存在于全量版。
定位图谱:在工具尺寸谱系中的位置
docs/lite.md 用一条轴来描述选型空间,工具尺寸从左到右递增,内置功能也依次增多:
tool size ← child_process zurk zx@lite zx → built-in functionality
也就是说:如果你只需要裸的进程控制,用 Node 内置 child_process 即可;需要更优雅的进程管理可以看 zurk(zx 上游的进程库,见 package.json 的 devDependencies 中的 zurk);需要“核心 zx 能力 + 更小的安装体积”就是 zx@lite;需要 glob、fs、fetch、retry 等全家桶则是完整 zx。
源码剖析:lite 包是如何生成的
lite 版并不是手写的一份独立代码,而是由构建脚本在全量构建完成后自动裁剪出来的。触发链路在 package.json 的 scripts 中:
"build:lite": "node scripts/build-pkgjson-lite.mjs",
"build:manifest": "npm run build:pkgjson && npm run build:lite && npm run build:jsr",
"postbuild": "node scripts/build-clean.mjs && npm run build:manifest"
即每次 npm run build(产物输出到 build/ 目录)结束后,postbuild 会执行 build:lite 生成 package-lite.json。核心逻辑见 scripts/build-pkgjson-lite.mjs,分四步:
1. 以 core.js 为入口做依赖闭包分析。 脚本先假定 lite 包只需包含 ./core.js 与 ./3rd-party-licenses 两个入口文件,然后用 depseekSync 解析 build/core.js 源码中引用的模块,凡是本地相对引用(./xxx)就追加进依赖集合,并同步加入对应类型声明文件:
const entries = new Set(['./core.js', './3rd-party-licenses'])
// ...
const deps = depseekSync(contents)
for (const { value: file } of deps) {
if (file.startsWith('.')) {
entries.add(file)
entries.add(file.replace(/\.c?js$/, '.d.ts'))
}
}
这就是“~7x 更小”的来源:files 字段最终只列出 core.js 依赖闭包内的文件,而全量版 package.json 的 files 还包含 cli.js、globals.js、deno.js、index.js 等所有入口及更庞大的 vendor 捆绑包(如 vendor-extra.cjs,包含 YAML、glob、MAML 等第三方库的打包产物)。
2. 白名单过滤 package.json 字段。 只保留 name、version、description、type、main、types、typesVersions、exports、files、engines、optionalDependencies、publishConfig、keywords、repository、homepage、author、license 等字段,devDependencies、scripts、bin、overrides 等一律剔除:
const whitelist = new Set([
'name', 'version', 'description', 'type', 'main', 'types',
'typesVersions', 'exports', 'files', 'engines', 'optionalDependencies',
'publishConfig', 'keywords', 'repository', 'homepage', 'author', 'license',
])
3. 重写入口为 core。 生成的 package-lite.json 中:
version追加-lite后缀(version: _pkgJson.version + '-lite');main指向./build/core.cjs,types指向./build/core.d.ts;exports只保留.与./package.json两个子路径,import/require均指向build/core.js/build/core.cjs;files由上一步的依赖闭包映射为build/xxx并排序。
4. 集成测试验证产物。 集成测试 test/it/build-npm.test.js 中有专门的 zx@lite 用例:将 package-lite.json 临时替换为 package.json 后执行 npm pack 解包,断言产物中 devDependencies 与 bin 均为 undefined,文件清单与预期一致,最后实际运行
node -e 'import {$} from "./package/build/core.js"; $.verbose = true; await $`echo hello`'
并匹配 stderr 中出现 hello,证明 lite 包脱离全量版环境后核心命令仍可独立运行。
lite 版到底导出了什么:core 模块边界
lite 包的入口 build/core.js 由 src/core.ts 编译而来。从该文件的导出声明(src/core.ts#L61-L67)可以看出 lite 的完整 API 表面:
export { bus } from './internals.ts'
export { default as path } from 'node:path'
export * as os from 'node:os'
export { Fail } from './error.ts'
export { log, type LogEntry } from './log.ts'
export { chalk, which, ps } from './vendor-core.ts'
export { type Duration, quote, quotePowerShell } from './util.ts'
再叠加文件主体中定义的 defaults/resolveDefaults(src/core.ts#L135-L153、src/core.ts#L1090-L1104)、$ 与 sync$、ProcessPromise、ProcessOutput、within(基于 AsyncLocalStorage 的选项作用域,src/core.ts#L155-L176)、cd、kill、useBash/usePwsh/usePowerShell(src/core.ts#L1009-L1017)以及 syncProcessCwd。
对比之下,全量版的入口 src/index.ts 在 export * from './core.ts' 的基础上,追加了两层:
export * from './goods.ts':即 src/goods.ts 中的tempdir/tempfile、argv/parseArgv/updateArgv、sleep、fetch(带pipe能力)、echo、question、stdin、retry、expBackoff、spinner、versions等便利函数;export { minimist, dotenv, fs, YAML, MAML, glob } from './vendor.ts':从 vendored 的第三方库再导出的工具集。
这正是功能矩阵中 lite 缺失条目的代码级解释:这些函数与 zx/globals、zx/cli 入口都不在 core.js 的依赖闭包内,因此不会进入 lite 包的 files 清单。
值得说明的是,lite 版仍保留了完整的 Options 配置体系(cwd、timeout、stdio、verbose、nothrow、preferLocal 等,见 src/core.ts#L93-L122)与 ZX_ 环境变量前缀的默认值解析(src/core.ts#L77-L90),resolveDefaults 支持 ZX_cwd、ZX_timeout、ZX_shell 等环境选项注入。也就是说裁剪的是“附加功能”,而不是 $ 模板引擎的执行、管道(pipe)、超时、信号处理等核心机制。
适用场景与选型建议
- 自有工具链/内部 CLI 框架:如果你的脚本库只是需要
$、ProcessPromise/ProcessOutput、cd/kill/within这类核心能力,npm i zx@lite可以显著缩小 node_modules 体积并缩短冷启动时间,这也是文档明确给出的推荐场景; - 供应链审计考量:lite 版
files清单由依赖闭包静态推导生成,包含的第三方代码更少(不捆绑 YAML、glob、MAML 等),审计范围更可控; - 普通脚本/CI 脚本:若用到了
glob、fs、fetch、retry、spinner或需要zx命令行入口(zx script.mjs)与--quiet/--verbose等 CLI 参数(见 man/zx.1),应安装完整版zx; - 环境要求:与全量版一致,
engines声明为node >= 12.17.0(见 package.json),构建与测试基于 Node 24(volta配置);锁定版本时建议使用文档示例中的zx@x.y.z-lite精确写法。
小结
zx@lite 通过“同名包 + 独立 channel + 构建期依赖闭包裁剪”的方式,把 zx 的核心进程执行引擎($、ProcessPromise、ProcessOutput 及 shell 切换、目录/进程控制等基础能力)从完整工具集中分离出来,体积约为全量版的 1/7,且不包含 CLI、文档与 manpage 资产。其分发产物由 scripts/build-pkgjson-lite.mjs 自动生成、由 test/it/build-npm.test.js 的集成测试持续验证,功能边界则完整记录在 docs/versions.md 的矩阵中。对于基于 zx 构建自有工具包的项目,它是官方推荐的更轻、更易审计的依赖形态。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00