Terser 混淆后为什么我的 HTML 内联脚本失效了?

Tr° 绍桐 阅读 37

我用 Terser 打包压缩 JS 时,发现页面里一段内联脚本不执行了,但外链 JS 没问题。是不是混淆把某些变量名改掉了?

这段内联脚本是用来初始化全局配置的,结构大概像这样:

<script>
  window.__INITIAL_CONFIG__ = {
    apiUrl: '/api',
    debug: false
  };
</script>

我试过在 Terser 配置里加 keep_fnames 和 reserved,但还是不行,控制台报 __INITIAL_CONFIG__ is undefined。这到底该怎么处理?

我来解答 赞 9 收藏
二维码
手机扫码查看
2 条解答
慕容倩利
兄弟,这问题我踩过,真的坑。

根本原因不是变量名被改那么简单的。Terser 压缩的时候,它分析你的内联脚本,发现 window.__INITIAL_CONFIG__ 这个属性赋值之后根本没人用(它看不到 HTML 里其他外链 JS 会读这个变量),直接给你整个优化掉了。所以后面代码读 window.__INITIAL_CONFIG__ 当然是 undefined。

你试的 keep_fnamesreserved 完全是方向错了:
- keep_fnames 是保留函数名的
- reserved 是防止某些名称被用作变量名的

这俩跟对象属性一点关系没有。

正确做法是用 mangle.properties 配置来保留这个属性:

// terser.config.js
module.exports = {
mangle: {
properties: {
reserved: ['__INITIAL_CONFIG__'],
regex: /^__/
}
}
};
如果你用的是 webpack 或者 vite,直接在构建配置里加上这个:

<pre class="pure-highlightjs line-numbers"><code class="language-javascript">// vite.config.js
export default defineConfig({
build: {
terserOptions: {
mangle: {
properties: {
reserved: ['__INITIAL_CONFIG__']
}
}
}
}
});


还有个小技巧,如果你这段内联脚本不想被压缩,可以在 script 标签上加个 data-terser-ignore 属性(取决于你用的构建工具支不支持),或者干脆把这部分配置放到单独的 JS 文件里靠后加载。

总之核心就是让 Terser 知道这个属性不能动,你得显式告诉它。
点赞
2026-03-19 10:15
Zz金静
Zz金静 Lv1
这个问题其实不是 Terser 直接把你的内联脚本混淆了,而是你很可能用了 webpack 或者类似的打包工具,在处理 HTML 时把内联 script 里的内容也当 JS 给处理了。

常见的解决方案有两个:

第一种,在内联脚本里加注释,告诉 terser 跳过这段代码:

<script>
/* @__NO_TERSER__ */
window.__INITIAL_CONFIG__ = {
apiUrl: '/api',
debug: false
};
</script>


第二种,如果你用的是 webpack + terser-webpack-plugin,检查一下配置,确保 HTML 里的内联脚本不会被二次处理。很多情况下是 html-webpack-plugin 或者其他插件在注入代码时触发了 terser。

另外提醒一下,reserved 选项是用来保留函数名的,不是变量名。你需要的是 keep_fnames: true 或者在 mangle.properties 里配置。最直接的办法还是用第一种注释法,基本上一用一个准。

如果你是用其他打包工具(比如 Vite、Rollup 之类的),原理也差不多——都是要在打包流程里把这部分代码“保护”起来。
点赞
2026-03-17 09:08