2 Commits
Author SHA1 Message Date
what efb3141734 feat(esm): Vendor 把装好的 npm 包连同依赖摊平成单文件
解决的是「脚本要用第三方库,但目标机器上没有 node」。

npm 真正干的活是解析依赖树——读 semver 范围、查注册表定版本、递归、处理冲突。
这步绕不开,得在有 node 的机器上做一次。但做完之后依赖树就是死数据了,用
esbuild 摊平成一个文件,发布物里只带那一个就够:

    qs         v6.16.0   打进  47 个文件 -> 73.6 KB   (原 19 个包 1.7 MB)
    es-toolkit v1.52.0   打进 219 个文件 -> 51.9 KB

产物是最小的 node_modules 布局,脚本照常 import,写法完全不变。

两个实现细节:

  - 入口不能直接写包名,esbuild 的 EntryPoints 是文件路径。所以造一段转发
    源码当 stdin 入口,包名放进 import,才走正常的 node_modules 解析。
  - 转发源码里写 export { default } 时,只有具名导出的包会报错(ESM 原生的
    很多是这样),退回去用只带具名导出的版本重打一次。

打包目标从 Loader 里提成了共用常量:摊平出来的库必须跟脚本同一档,
否则库能打出脚本引擎跑不了的语法。

零依赖的包不用这个——直接下 tarball 解开就行,README 里记了命令。
2026-09-07 09:54:18 +08:00
what 6ce9b483fd feat(esm): 按目录加载脚本、打包与热更新
把一个目录当脚本仓库:按路径寻址、esbuild 打包、内容变了自动重编。

  - Loader    扫目录建索引,Load(name) 给出打好包的源码和版本号
  - bundler   esbuild 的封装。ESM 格式而不是 IIFE——IIFE 会附带一整套
              CommonJS interop helper,每建一个 VM 都要重跑一遍
  - plugin    把扩展的 TS 模块变成可以 import 的虚拟模块,磁盘上没有文件
  - typings   把这些虚拟模块的类型按 node_modules 布局落盘,编辑器才认识

esbuild 原生实现了 Node 的模块解析,所以脚本能直接 import node_modules
里的第三方库。写出来的类型文件是 index.ts 而不是 index.d.ts:扩展给的是
真正的模块源码,里面可能带实现,声明文件里不允许有实现。

node_modules 不参与热更新的版本计算——依赖包是装出来的,改动总伴随显式的
安装动作,而真实的 npm 包动辄上千个文件,每次取脚本 stat 一遍太贵。
2026-09-05 22:13:57 +08:00