如何同时使用goog.provide与@externs?解决代码压缩相关问题
我明白你现在遇到的麻烦——为了适配代码压缩不得不改用oVar["stuff"]["things"]这种方括号属性访问写法,还要折腾@externs和goog.provide的配置,每次都要手动给每个相关文件加--externs或--js参数确实太繁琐了。这里有几个更高效的方案可以帮你摆脱这个困境:
方案1:用通配符批量指定文件
Closure Compiler支持用通配符来批量匹配文件,不用逐个手动列出来。这样你只需要一次参数就能覆盖所有相关的externs或业务文件:
- 匹配某个目录下所有externs文件:
java -jar closure-compiler.jar --externs=path/to/your/externs/*.js --js=src/**/*.js - 递归匹配子目录里的文件(用
**):java -jar closure-compiler.jar --externs=src/**/*-externs.js --js=src/**/*.js
这种方式能大幅减少你要写的命令行参数数量,只要文件命名或路径有规律,就能轻松批量引入。
方案2:将externs集中到单个主文件
如果你的externs是分散在多个文件里的,可以把所有需要的外部变量定义合并到一个主externs文件中,只需要给编译器传入这一个文件即可。比如你可以在主文件里统一定义全局对象结构:
/** @externs */ // 定义你需要保护不被压缩重命名的对象结构 var oVar = {}; oVar.stuff = {}; oVar.stuff.things = {}; // 如果需要引用其他externs文件的内容,可以用goog.require(前提是其他文件用goog.provide声明) goog.require('some.other.externs.module');
这样不管你有多少个分散的externs模块,只要在主文件里用goog.require引入,编译器就能自动识别所有相关的externs定义,不用逐个加--externs参数。
方案3:利用Closure模块系统自动关联
如果你项目里已经在使用Closure Library的模块系统(goog.provide/goog.require),可以通过--js_module_root参数指定模块根目录,让编译器自动处理模块依赖,包括externs文件:
java -jar closure-compiler.jar --js_module_root=src/ --js=src/**/*.js --externs=src/externs/main-externs.js
只要你的externs文件和业务代码一样用goog.provide声明模块,并且业务代码里用goog.require引入了对应的externs模块,编译器就会自动加载这些依赖的externs文件,不用手动逐个指定。
另外补充个小提示:其实只要你在externs里正确定义了对象的属性结构,不管用点语法oVar.stuff.things还是方括号语法oVar["stuff"]["things"],Closure Compiler都不会重命名这些属性。所以如果只是为了压缩安全,你不一定非要全改成方括号写法,externs的正确配置才是关键。
内容的提问来源于stack exchange,提问作者strider820

