首先关闭:我知道this SO question以及externs extractor here。
我正在使用ThreeJS处理我的第一个游戏项目。由于我是以模块化方式构建的,因此我打算使用Google's Closure Compiler将结果打包到最后。一个小小的测试表明,编译(使用高级优化)也会缩小构造对象的方法和属性,例如THREE.Geometry
或THREE.Color
。
检查生成的外部文件,这是我在THREE.Color
第78行(ThreeJS r60)上找到的内容:
"Color": function () {},
显然它缺少方法和属性,所以Closure Compiler不知道它不应该重命名这些。
我有另一个解决方案,它将在单独的文件中定义曝光并将其与源一起编译。它工作正常,但是通过这种方式定义每个使用的方法和属性是很多手工工作。这也只是一个hackish解决方法。 Closure Compiler简单地决定不在对象上重命名任何这些名称。
例如,所有这些都具有相同的效果:
/** @expose */
THREE.Geometry.vertices;
/** @expose */
THREE.vertices;
/** @expose */
Object.vertices;
window.vertices = function() {
console.log("foo");
};
window.vertices
将不会重命名。因此,这不是一个理想的解决方案。
实际问题是: Closure编译器是否能胜任此问题?或者我是否应该将这些依赖项烘焙到我的编译中并重命名我使用的所有方法和属性?
答案 0 :(得分:2)
如果我正确地理解了你的问题,那么你正在尝试编译你的awesomeGame.js - 这取决于threejs.js - 但你对threejs.js的引用正被关闭的重命名过程打破。
我同意自动extern脚本可能在它们之前有很多开发,并且可能不是一个强大的解决方案。
我的项目有一个非常类似的问题。我可以提供两种可能的解决方案每个都有权衡。我个人不是三个用户,我只会在这里说明一般惯例。
Per this discussion,在库执行并将其根对象放在全局上下文中后,您可以从window
开始找到它 - 并且永远不会重命名窗口对象。此外,括号语法永远不会重命名。因此,您编译的代码可以在THREE
找到window['THREE']
,在THREE.Geometry
找到window['THREE']['Geometry']
等等。此外,jQuery可以在窗口找到[' jQuery' ],并在窗口[' _']下划线。
我建议你每次需要从编译代码中访问一个外部对象或函数时,比如说三个js.js,在文件的顶部陈述一些全局定义,如下所示:
// awesomeGame.js:
// global defines:
var three_vertex = window['THREE']['Geometry']['vertex'],
three_rectangle = window['THREE']['Geometry']['rectangle'],
three_crossproduct = window['THREE']['Math']['crossproduct'],
jquery_ajax = window['jQuery']['ajax'];
// game assets:
var myVertex = new three_vertex(10,10),
myRectangle = new three_rectangle(10,10,10,10);
// do stuff:
console.log(myVertex['x'] + ' ' + myVertex['y']);
console.log(three_crossproduct(myVertex, myVertex));
myRectangle['paint']('black');
如果您在Pretty / advanced模式下将上述内容粘贴到Compiler Service,则会产生以下结果。
var a = window.THREE.Geometry.rectangle,
b = window.THREE.Math.crossproduct,
c = new window.THREE.Geometry.vertex(10, 10),
d = new a(10, 10, 10, 10);
console.log(c.x + " " + c.y);
console.log(b(c, c));
d.paint("black");
<强>肯定:强> 完整的threejs.js引用仅在全局定义中打印一次。从那时起,封闭打印一个容器&#39; a&#39;或者&#39; b&#39;代替。因此,与您讨论的外部方法不同,您获得了大部分压缩效益。
<强>否定:强>
来自threejs.js对象的方法和属性 - 必须在括号语法中一致地命名。请注意,[&#39; x&#39;]和[&#39; y&#39;]属性以及[&#39; paint&#39;]方法如果没有,则会重命名被括起来的。将关闭设置为--warning_level=VERBOSE
,注意JSC_INEXISTENT_PROPERTY
错误,并将其括起来。如果你忘了什么,编译器会提醒你。 Error Reference
如果您的linter对所有括号感到不安,请使用--sub
说服,如&#34;容忍下标&#34;。 All jsLint errors/options
另一种方法:为自己设置一个构建脚本,按顺序将所有源文件连接到一个临时文件中。如果你是unix-y,你的脚本可能如下所示:
#!/bin/bash
# build_and_run.sh
# get updates to google closure: http://code.google.com/p/closure-compiler/downloads/list
#
# local jslint:
# sudo apt-get install nodejs npm
# sudo npm jslint -g
rm temp.js
rm final.js
cat threejs.js \
awesomeGame_moduleOne.js \
awesomeGame_moduleTwo.js \
> temp.js
# docs: http://www.jslint.com/lint.html
jslint temp.js \
--maxerr=50 --sloppy --white --sub --plusplus \
--nomen --bitwise --browser \
--predef unescape \
--predef Uint8Array \
--predef Blob
java -jar compiler-20130823.jar \
--compilation_level ADVANCED_OPTIMIZATIONS \
--formatting pretty_print \
--language_in=ECMASCRIPT5 \
--js temp.js \
--js_output_file final.js
#maybe
nodejs final.js
# or
# https://developers.google.com/chrome/web-store/docs/get_started_simple
chromium --load-and-launch-app=./
# rinse, repeat
<强>肯定:强> 没有括号,没有定义,没有extrens,没有中间件。谷歌关闭所有。最终产品的最大压缩。完整的装运项目(扫描原始的,分开的源文件可能会使linter混淆)。发送一个集成的文件。
<强>否定:强> 沉浸在上游源代码中。这可能是也可能不适合您。 Linting上游源代码将特别诱使您将代码风格强加于上游。抵制,抗拒。另一方面,了解您所依赖的中间件具有优势。
还涉及调试master.js文件,因为将为final.js报告行号,您需要在阅读时识别源文件。使用漂亮模式,更温和的编译设置,@preserve
评论以及大量console.log
,您将获得它的处理。
最后,根据threejs的优先级和代码约定,可能不支持Closure中的编译,或者可能会在行为中引入细微的更改。如果是这种情况,请将此选项排除在外。例如,jQuery与闭包的兼容性为actively being discussed。
无论如何,我希望这能回答你的问题。如果我不在标记,请回复。有很多&包括/模块化&#39;框架也在那里。也许有人可以填写这个主题。