@afterpack/parcel-optimizer 是一个 Parcel 2 Optimizer,注册在 .parcelrc 中。它在 Parcel 自身的优化阶段在内存中混淆每个打包产物,因此该产物不会以明文形式落盘。
该软件包是 @afterpack/parcel-optimizer。
安装
$ npm install -D @afterpack/parcel-optimizer// .parcelrc
{
"extends": "@parcel/config-default",
"optimizers": {
"*.{js,mjs,cjs}": ["...", "@afterpack/parcel-optimizer"]
}
}"..." 展开很重要:它保留了 Parcel 的默认优化器(@parcel/optimizer-swc),并把 AfterPack 放在最后。AfterPack 在压缩之后运行。对等依赖:Parcel >=2.9.0。
构建
.parcelrc 中的条目是不带内联选项的裸包名,因此选项来自项目根目录下的 afterpack.json,这是每个 AfterPack 集成都会读取的唯一配置文件:
{
"seed": "git",
"preset": "medium"
}只有项目根目录会产生构建产物;不会在你的打包产物旁边生成任何文件:
- 每个打包产物一个
protectionMap.html,位于.afterpack/<bundle>.<id>.protectionMap.html。 - 当 sourceMap 策略 启用时生成一个 source map。它会返回给 Parcel 而不是直接写入磁盘,因此由 Parcel 用自己的内容哈希来命名并输出它。
.afterpack/ 自带一个 .gitignore;该插件从不修改你项目的 .gitignore。
验证
由于没有合并报告,请直接检查你关心的打包产物:对 Parcel 打包的每个入口或延迟加载的代码块,查看 .afterpack/<bundle-name>.<id>.protectionMap.html。生产环境下默认关闭 map;要覆盖此行为,请在 afterpack.json 中设置 "sourceMap": { "enabled": true }。每份报告都包含你的完整源码,切勿提交或对外提供该文件。
选项
每个配置项都可以在这里设置,例如 { "preset": "hard", "complexity": 40 }。protectionMap.enabled 取决于打包产物是否带有 source map,而不是取决于构建模式,并且始终写入已被 gitignore 的 .afterpack/ 中。该插件没有 build.backup 选项,设置它会发出警告。显式选项始终优先于生产环境默认值。
指令
指令由插件从你的源码中读取。如果没有可用的 source map,该处理阶段就无法恢复任何内容,并会明确说明这一点。
入口模块中的指令不会被恢复。 该处理阶段会报告 DIAG_DIRECTIVE_SOURCE_UNRESOLVED 并指出具体模块。一旦启用 source map,其他所有非入口模块中的指令都能正常工作。如果你需要在入口模块中使用指令,请把受保护的代码移到一个被导入的模块中。
边界情况
内容哈希占位符可能导致构建失败
启用内容哈希时(parcel build 的默认行为),如果目标环境不支持原生 ESM,Parcel 的内容哈希占位符会落入被混淆的字符串内部,导致每个代码分割出的分块在生产环境中都返回 404。
该插件会检测这种冲突,并使构建失败,而不是继续发布:
AfterPack obfuscated 1 Parcel content-hash placeholder(s) in app.[hash].js (HASH_REF_...).
hint: Run `parcel build --no-content-hash` (chunk URLs stop being content-addressed).
hint: Or set "complexity": 0 in afterpack.json to ship minify-only.Parcel 的默认 ESM 输出不受影响。
需要了解的情况
- 每个打包产物在工作进程中处理一次。 Parcel 按打包产物运行优化器,不同工作进程中打包的产物无法共享状态。在同一进程中打包的产物共享同一个种子。要在所有工作进程中固定同一个种子,请显式设置
seed或导出AFTERPACK_seed。 - Parcel 会缓存优化器输出。 如果
.parcel-cache是热缓存且输入未变化,重新构建不会重新运行 AfterPack,也不会轮换未固定的种子。要获得全新的处理结果,请清除.parcel-cache;CI 构建反正都是从冷缓存开始的。 - 两条无害的警告。 Parcel 会打印
ES module dependencies are experimental(每个 AfterPack 包都是 ESM),并报告该插件contains non-statically analyzable dependencies(原生引擎的运行时二进制文件解析)。二者都不影响构建。
不使用插件:改用 CLI
照常使用 Parcel 构建,然后让 AfterPack 处理其输出:
$ npx parcel build$ npx afterpack@latest dist/ --preset=medium --seed=git不带路径参数时,CLI 会检测 dist/,即 Parcel 的默认输出目录;如果你的目录不同,请指定它。AfterPack 会遍历该目录,收集所有 .js/.mjs/.cjs 文件并原地混淆它们。CLI 运行没有内容哈希防护,并且会为整个目录生成一份合并的 protectionMap.html,而不是每个打包产物一份。失败即中止依然有效:构建目录缺失、没有 JS 文件、error/critical 诊断信息,或者某个文件引擎无法混淆,都会以 1 退出。