npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ng-esbuild-obfuscator

v1.0.0

Published

面向 Angular 18+ esbuild 构建链的代码混淆插件

Readme

ng-esbuild-obfuscator

面向 Angular 18 及以上 esbuild 构建链的业务代码混淆插件。它根据 esbuild metafile 判断每个输出 chunk 是否包含项目业务源码,只处理命中的 JavaScript chunk,并保留静态导入和懒加载 import() 的模块路径。

特性

  • Angular 18+及后续采用 esbuild application builder 的版本可用。
  • 只识别 src 下的业务 TypeScript/JavaScript,默认排除 src/assets
  • 业务代码和第三方依赖被打进同一 chunk 时处理整个 chunk,避免业务代码漏混淆。
  • 使用 JavaScript 语法分析器保护静态导入、再导出和动态导入路径。
  • 默认采用轻量混淆配置,避免控制流平坦化、死代码注入带来的明显体积和性能开销。
  • 提供摘要日志、debug 判定日志、严格失败策略和 source map 防泄漏检查。
  • 同时提供开箱即用的默认插件和可配置工厂函数,包含 TypeScript 类型声明。

环境要求

  • Node.js >= 18.19.0;实际 Node.js 版本还必须满足所用 Angular CLI 的要求。
  • Angular 18 或更高版本。
  • @angular-builders/custom-esbuild 必须与 Angular 主版本一致。

| Angular | 自定义 builder | | --- | --- | | 18 | @angular-builders/custom-esbuild@^18 | | 19 | @angular-builders/custom-esbuild@^19 | | 20 | @angular-builders/custom-esbuild@^20 | | 21 | @angular-builders/custom-esbuild@^21 | | 22 | @angular-builders/custom-esbuild@^22 |

本包不依赖 Angular API,因此不需要跟随 Angular 主版本发布不同构建产物。兼容边界由 esbuild 插件 API 和对应版本的自定义 builder 提供。

esbuild >= 0.21 < 1 是 peer dependency,通常会由 Angular 构建工具链提供或被 npm 自动解析,无需在常规 Angular 项目中单独配置。

安装

以 Angular 18 项目为例:

npm install --save-dev ng-esbuild-obfuscator @angular-builders/custom-esbuild@^18

其他 Angular 版本只需替换自定义 builder 的主版本。

推荐接入方式

在 Angular 项目中新建 tools/esbuild-plugins.mjs

import { createObfuscatorPlugin } from 'ng-esbuild-obfuscator';

export default createObfuscatorPlugin({
  sourceRoots: ['src'],
  excludeRoots: ['src/assets'],
  logLevel: process.env.OBFUSCATOR_LOG_LEVEL ?? 'info',
  obfuscatorOptions: {
    seed: 20260722,
  },
});

修改 angular.json。保留原有 build 配置,只替换 builder,并新增一个独立的 obfuscate configuration:

{
  "projects": {
    "your-app": {
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-esbuild:application",
          "options": {
            "outputPath": "dist/your-app",
            "index": "src/index.html",
            "browser": "src/main.ts",
            "tsConfig": "tsconfig.app.json"
          },
          "configurations": {
            "production": {
              "optimization": true,
              "outputHashing": "all"
            },
            "obfuscate": {
              "optimization": true,
              "sourceMap": false,
              "outputHashing": "all",
              "plugins": ["tools/esbuild-plugins.mjs"]
            }
          }
        }
      }
    }
  }
}

package.json 中增加脚本:

{
  "scripts": {
    "build:obfuscate": "ng build --configuration obfuscate"
  }
}

执行:

npm run build:obfuscate

不要把插件放进常用的开发构建。混淆会增加构建时间,也会降低浏览器调试体验。

零配置接入

默认配置可直接使用包内插件文件:

{
  "plugins": ["node_modules/ng-esbuild-obfuscator/dist/default-plugin.js"]
}

@angular-builders/custom-esbuildplugins 项当作相对工作区的文件路径加载,因此不能直接写成 "ng-esbuild-obfuscator/plugin"。需要自定义选项时,使用前述 tools/esbuild-plugins.mjs 包装文件。

配置项

| 配置 | 默认值 | 说明 | | --- | --- | --- | | enabled | true | 是否注册混淆逻辑。 | | workspaceRoot | absWorkingDir / process.cwd() | 工作区根目录,通常无需手动设置。 | | sourceRoots | ['src'] | 用于识别业务代码的源码目录。 | | excludeRoots | ['src/assets'] | 从业务源码中排除的目录;传 [] 取消默认值。 | | outputExtensions | ['.js', '.mjs', '.cjs'] | 允许处理的输出扩展名。 | | obfuscatorOptions | 见下文 | 传给 javascript-obfuscator 的覆盖配置。 | | logLevel | 'info' | silenterrorwarninfodebug。 | | failOnError | true | 单个 chunk 混淆失败时是否让整个构建失败。 | | sourceMapPolicy | 'error' | 检测到 source map 时采用 errorwarnignore。 | | logger | console | 工厂方式下可注入日志实现。 |

默认混淆参数:

{
  compact: true,
  identifierNamesGenerator: 'hexadecimal',
  renameGlobals: false,
  renameProperties: false,
  controlFlowFlattening: false,
  deadCodeInjection: false,
  stringArray: true,
  stringArrayRotate: true,
  stringArrayThreshold: 1,
  stringArrayEncoding: ['base64']
}

obfuscatorOptions 会覆盖这些默认值。插件会把用户提供的 reservedStrings 与检测到的模块引用合并,防止懒加载 chunk 路径被改写。

不建议轻易开启 renamePropertiesrenameGlobalscontrolFlowFlatteningdeadCodeInjectionselfDefending。Angular、依赖库、接口字段、反射访问和 CSP 环境都可能受到影响;上线前必须做完整业务回归和性能评估。

日志

info 级别每轮构建只输出一行摘要:

[ng-esbuild-obfuscator] 完成:处理 12 个 chunk,跳过 3 个;1.82 MiB -> 2.06 MiB(+245.4 KiB);耗时 1843 ms。

定位“某个 chunk 为什么没有处理”时临时启用 debug:

OBFUSCATOR_LOG_LEVEL=debug npm run build:obfuscate

debug 日志只记录 chunk 路径、业务输入数量和模块引用保护数量,不打印完整源码、环境变量或整份 metafile。

API

import obfuscatorPlugin, {
  createObfuscatorPlugin,
  type ObfuscatorPluginOptions,
} from 'ng-esbuild-obfuscator';
  • 默认导出:使用默认配置的 esbuild Plugin
  • createObfuscatorPlugin(options):创建可配置插件。
  • ObfuscatorPluginOptions:完整 TypeScript 配置类型。

构建行为

  1. esbuild 完成打包并提供内存输出和 metafile
  2. 插件逐个检查 .js.mjs.cjs 输出。
  3. 只要 chunk 的输入列表含有 sourceRoots 下且不在 excludeRoots 下的业务脚本,就处理整个 chunk。
  4. 插件解析 chunk 中的模块引用,并把路径加入 reservedStrings
  5. 混淆结果替换内存中的输出内容,再由 Angular builder 写入 dist

“整个 chunk”是 esbuild 打包后的最小可靠处理单位。一个 chunk 同时包含业务代码和第三方包时,无法在最终 JavaScript 中无损拆开模块,因此第三方代码也会随该 chunk 一起处理。

常见问题

报错无法访问 outputFiles 或 metafile

确认 build builder 是 @angular-builders/custom-esbuild:application,而不是 Angular 原生 @angular-devkit/build-angular:application@angular/build:application;同时确认 plugins 放在该 build target 的 options/configuration 中。

报错检测到 source map

在混淆 configuration 中设置 "sourceMap": false。不建议把 sourceMapPolicy 改成 warnignore,因为 .map 文件可能直接包含原始源码。

懒加载页面无法打开

先用 logLevel: 'debug' 确认相关 chunk 已处理。若应用还在运行时拼接非字面量资源路径,把这些固定路径的完整正则加入 obfuscatorOptions.reservedStrings。ES 模块的静态和字面量动态导入由插件自动保护。

构建明显变慢或产物变大

这是字符串数组混淆的正常代价。优先降低 stringArrayThreshold,不要先开启控制流平坦化或死代码注入。可通过固定 seed 获得可复现产物,方便比较体积。

SSR 项目是否可用

插件会依据每次 esbuild 构建的 metafile 处理命中业务源码的 JavaScript,包括 browser/server 构建。SSR 上线前需要验证 Node.js 启动、路由渲染和动态导入;若只希望处理浏览器产物,应将插件仅配置到单独的浏览器 build target。

本地开发

跨项目联调、打包验证和发布流程见 docs/local-development.md。可配置包装文件见 examples/esbuild-plugins.mjs

许可证

MIT