Angular构建开启优化后Chevrotain模块抛出Token不存在错误如何解决?
问题根因
Angular开启optimization配置后,构建工具会通过terser对JS代码执行名称混淆(mangle),将类名、变量名缩短为单个字母,而chevrotain的语法解析逻辑依赖Token类的name属性做规则匹配,混淆后Token的名称被改写,导致解析规则无法找到对应的token,才会抛出你遇到的错误。将optimization设为false实际上是关闭了混淆,所以问题消失,但会导致包体积变大,不符合构建要求。
可落地的解决思路
方案1:细粒度配置Angular构建优化项,避免全量关闭优化
Angular的optimization配置支持传入对象而非布尔值,你可以仅关闭脚本的名称混淆,保留其他优化能力,把你原来的"optimization": true替换为:"optimization": { "styles": true, "fonts": true, "scripts": { "mangle": false } }该方案调整成本最低,对构建产物体积的影响远小于全量关闭optimization。
方案2:扩展构建配置,针对性保留chevrotain相关名称
如果需要保留其他业务代码的混淆能力,只排除chevrotain相关逻辑,可以通过@angular-builders/custom-webpack替换Angular默认的构建器,新增自定义webpack配置,为terser插件添加保留规则:- 安装依赖:
npm i @angular-builders/custom-webpack -D - 修改angular.json中dev配置的builder为
@angular-builders/custom-webpack:browser,新增customWebpackConfig字段指定配置文件路径 - 自定义webpack配置内容参考:
const TerserPlugin = require('terser-webpack-plugin'); module.exports = { optimization: { minimizer: [ new TerserPlugin({ terserOptions: { mangle: { // 保留chevrotain相关Token的类名和属性名 reserved: ['n', 'version'], keep_classnames: /.*Token.*/, keep_fnames: /.*Rule.*/ } } }) ] } }- 安装依赖:
方案3:排查依赖版本冲突
部分版本的Three.js内置的VRMLLoader本身绑定了低版本的chevrotain,和你项目中单独安装的^9.0.2版本存在冲突,你可以尝试:- 移除项目中单独安装的chevrotain依赖,直接使用VRMLLoader内置的版本
- 或直接拷贝Three.js官方仓库中最新的VRMLLoader源码到你的项目本地引用,避免打包时的依赖冲突
方案4:轻量适配方案
如果上面的方案调整成本较高,可以临时将buildOptimizer设为false,保留其他optimization配置开启,大部分情况下也能规避该问题,同时对构建产物的体积影响很小。
内容的提问来源于stack exchange,提问作者Julien Rouzot

