代码混淆后动态生成的HTML元素报错找不到,该怎么保证代码完整性?
我在给Vue项目混淆代码时用了Terser,结果发现原本能正常工作的动态DOM操作突然报错”Cannot read property ‘addEventListener’ of null”。比如这个按钮点击后动态创建的div:
<button @click="createElement">生成元素</button>
<div id="dynamic-container"></div>
混淆前正常,混淆后getElementById找不到节点,难道是变量名被压缩导致id冲突了?试过在terser选项里加keep_fnames也不行,求解具体该怎么配置才能保留关键DOM引用?
Terser默认会压缩变量名,但getElementById里的字符串参数按理说不应该被处理。问题更可能是你的代码写法有问题——如果你是在JS里动态给元素设置ID然后立刻查询,像这样:
那问题在于你用的ID选择器本身是动态拼接的,混淆编译器可能把你的变量引用搞乱了。
解决方案很简单:别用getElementById,用Vue的方式。在Vue里操作动态元素,直接上ref:
如果你非要保留getElementById,那在Terser配置里这样写:
或者更直接的办法,把你要用的ID放到白名单里:
说真的,Vue项目里能用ref就用ref,别跟原生DOM操作较劲,压缩后出问题的概率能少一半。
一个靠谱的解决方案是,在 Terser 的配置里明确保留那些和 DOM 相关的关键标识符。比如你可以通过
mangle.properties来避免压缩特定的属性名。具体配置可以这样写:另外,建议你在代码里尽量避免直接依赖 HTML 的 ID 或者 class 名来做动态操作,改成用 Vue 的 ref 更加稳妥。比如你的例子可以改成这样:
用 ref 的好处是它不会受到混淆的影响,而且更符合 Vue 的设计理念。如果你非得用原生 DOM 操作,记得在 Terser 配置里加上类似
reserved的选项来保护这些关键的 DOM 标识符。比如:总结一下,推荐优先用 Vue 的 ref 来替代原生 DOM 操作,如果一定要用原生方式,记得在 Terser 配置里保护好相关的标识符。这样基本就能解决混淆后找不到节点的问题了。