我使用uglifyjs来缩小连接的文件集,这种方法很好但不够好。构建的lib使用名称空间,因此类,函数和常量存储在根名称空间变量中:
(function() {
var root = { api:{}, core:{}, names:{} };
/* util.js file */
root.names.SOME_LONG_NAMED_CONST='Angel';
/* Person.js file */
root.core.Person = function(name) { this.name = name };
/* API.js with the functions we want to expose */
root.api.perform = function(param_for_api) { /* do something */ }
window.lib_name.perform = root.api.perform;
})();
缩小为不那么小的版本
(function(){var a={api:{},core:{},names:{}};a.names.SOME_LONG_NAMED_CONST="Angel",a.core.Person=function(a){this.name=a},a.api.perform=function(){},window.lib_name.perform=a.api.perform})();
我理解uglify可能认为root var是一个必须保持原样并且不能更改的数据结构。有没有办法让uglify破坏根命名空间中的嵌套名称?
答案 0 :(得分:8)
当您最小化Javascript时,您只能更改变量的名称,api,核心和名称不是变量,而是对象的属性。如果最小化器改变了这些,您可能会得到意想不到的结果。如果在您的代码中你会打电话
root["api"].perform = function()...
甚至是
之类的东西function doIt(section, method, argument) {
root[section][method](argument);
}
doIt('api','perform', 101);
所有完全合法的JS,但是最小化者永远无法弄清楚发生了什么。
答案 1 :(得分:4)
除了@JanMisker的观点(完全有效)之外,重写属性是不安全的,因为它们可以暴露在缩小范围之外的代码中。
虽然自执行函数有一个范围,如果代码只是
(function() {
var root = { api:{}, core:{}, names:{} };
root.names.SOME_LONG_NAMED_CONST='Angel';
alert(root.names.SOME_LONG_NAMED_CONST); // some code that does something
})();
确实,在函数外部,无法访问根对象,因此重写属性名称是安全的,以下代码会产生相同的结果:
(function() {
var a = { b:{}, c:{}, d:{} };
a.d.e='Angel';
alert(a.d.e);
})();
但即使您在私有范围内,您也可以访问,更重要的是从外部范围分配变量!想象一下:
(function() {
var root = { api:{}, core:{}, names:{} };
root.api.perform = function(param_for_api) { /* do something */ }
window.lib_name = root.api;
})();
您不仅要展示一个函数,还要展示一个具有函数的对象。从窗口可见的任何地方都可以看到该功能。
因此,例如,在javascript控制台中编写以下内容会产生不同的结果:
window.lib_name.perform(asdf);
通过缩小,你必须写:
window.lib_name.f(asdf);
或类似的东西。
请记住,在缩小范围之外总会有代码。
拥有绝对最小的JS并不是至关重要的,但如果IT因某种原因而至关重要(例如:外星人绑架了你的继女,让她回来的唯一方法是将这个缩小到100个左右以下),您可以手动将不需要的长属性名称替换为较短的属性名称,只要确保它不会暴露在任何地方,并且不能通过关联数组表示法(root['api']
)进行访问。
答案 2 :(得分:1)
但是,您可以通过将属性名称定义为局部变量来解决此问题,并将所有.properties修改为[keys],以缩小文件大小:
(function() {
var API = 'api';
var CORE = 'core';
var NAMES = 'names';
var SLNC = 'SOME_LONG_NAMED_CONST';
var root = {};
root[API]={};
root[CORE]={};
root[NAMES]={};
/* util.js file */
root[NAMES][SLNC] ='Angel';
/* Person.js file */
root[CORE].Person = function(name) { this.name = name };
/* API.js with the functions we want to expose */
root[API].perform = function(param_for_api) { /* do something */ }
window.lib_name.perform = root[API].perform;
})();
因为现在所有的属性都变成了一个局部变量,所以uglify js会破坏/缩短变量名,因此整体文件大小减少了:
!function(){var a="api",b="core",c="names",d="SOME_LONG_NAMED_CONST",e={};e[a]={},e[b]={},e[c]={},e[c][d]="Angel",e[b].Person=function(a){this.name=a},e[a].perform=function(){},window.lib_name.perform=e[a].perform}();
然而,缩小文件大小并不意味着您将在真实服务器上缩短下载时间,因为通常我们的http传输是gzip压缩,大多数重复将由您的http服务器压缩,并且它比人类做得更好。
答案 3 :(得分:1)
最新版本的uglify(今天)有对象属性重整,见v2.4.18。它还支持保留文件,用于排除对象属性和不希望损坏的变量。看看吧。
使用--mangle-props
选项和--reserved-file filename1.json filename2.json
等....