zoukankan      html  css  js  c++  java
  • Javascript压缩原理及压缩工具收集

    一、为什么要进行Javascript压缩?

    1、减少JS代码容量,增加下载速度和执行速度;

    2、压缩后的JS代码不具备可识性,在一定程度上达到加密效果,防止被人轻易使用。

    二、常规Javascript压缩的原理:

    1、压缩多余的空格和换行符;

    2、删除注释,因为注释对浏览用户是无用的,删除了可以缩小文件体积;

    3、把较长的变量名称和过程名称统一替换为很短的名称。

    三、其他Javascript压缩(加密)原理
    http://www.cnblogs.com/heimirror/archive/2010/06/04/1751304.html 

    1、加密:微软有一个控件,可以将javascript加密,加密后真的是一点都无法阅读,在运行的时候需要再用这个控件解密。加解密的过程是可逆的,所以有些基础的人还是可以破解的。此外,这个控件在浏览器里运行时会报安全警告,而且只适用于IE,所以用处不大。

    2、加壳:有些工具可以将js文件打包成exe,在运行时类似于以cscript/wscript运行,这样的方法是在网页里行不通的。

    3、去冗:将javascript中的注释、换行、没用的空字符都去掉,这样的做法没什么技术含量,如果没注释,用编辑器就可以做。

    4、重整:利用javascript的eval函数以及正则表达式将源文件重整,这个过程也是可逆的,重整后的文件只能对付菜鸟,而且会影响加载效率。

    5、压缩:这个是重点了,大家看一下jQuery的min包,主体部分除了经过去冗处理,函数内部的变量也被替换了,这样可以在不考虑阅读的情况下,最大程度减少文件长度。这个过程也是很有技术含量的,因为不能修改全局变量,否则压缩后的文件可能无法使用。具体实现方法在网上似乎传了很多,其实目前只有一个,就是yuicompressor,我特意在jQuery的SVN上看了一下,在build目录里可以找到这个包,目前的版本是2.4.2。

    四、特别介绍YUI Compressor压缩JavaScript原理 
    http://www.planabc.net/2009/08/02/javascript-compression_with_yui_compressor/ 

    YUI Compressor 压缩 JavaScript 的内容包括:
    1、移除注释 

    2、移除额外的空格 

    3、细微优化 

    4、标识符替换(Identifier Replacement) 

    YUI Compressor 包括哪些细微优化呢?

    object["property"] ,如果属性名是合法的 JavaScript 标识符(注:合法的 JavaScript 标识符——由一个字母开头,其后选择性地加上一个或者多个字母、数字或下划线)且不是保留字,将优化为: object.property 

    {"property":123} ,如果属性名是合法的 JavaScript 标识符且不是保留字,将优化为 {property:123} (注:在对象字面量中,如果属性名是一个合法的 JavaScript 标识符且不是保留字,并不强制要求用引号引住属性名)。 

    'abcd\'efgh',将优化为 "abcd'efgh"。 

    "abcd" + "efgh",如果是字符串相连接,将优化成 "abcdefgh"(注:所有在使用 YUI Compressor 的前提下,对于脚本中的字符串连接,使用连接符 “+” 的效率和可维护性最高)。 
    对于 JavaScript 最有效的压缩优化,当属标识符替换。

    比如:


    (function(){
    function add(num1, num2) {
    return num1 + num2;
    }
    })();


    进行属标识符替换后:


    (function(){
    function A(C, B) {
    return C+ B; 
    }
    })();


    再移除额外的空格,最终成了:


    (function(){function A(C,B){return C+B;}})();



    YUI Compressor 标识符替换仅替换函数名和变量名,那哪些不能被替代呢?

    1、原始值:字符串、布尔值、数字、null 和 undefined。一般来说字符串占的空间最多,而非数字字面量其次(true、false,null,underfinded)。 

    2、全局变量:window、document、XMLHttpRequest等等。使用最多的就是 document、window。 

    3、属性名,比如:foo.bar。占据的空间仅次于字符串,”.” 操作符无法被代替,且 a.b.c 更加费空间。 

    4、关键字。经常被过度使用的关键字有:var、return。最好的优化方法:一个函数仅出现一次 var 和 return 关键字。 

    对于原始值、全局变量、属性名的优化处理方式大致相同:任何字面量值、全局变量或者属性名被使用超过 2 次(包括2次),都应该用局部变量存储代替。

    但有部分情况下是禁止使用标识符替换的:

    1、使用 eval() 函数。解决方法:不使用或者创建一个全局函数封装 eval()。 

    2、使用 with 语句。解决方法:方法同上。 

    3、JScript 的条件注释。唯一解决的方法:不使用。 

    由于 YUI Compressor 是建立在 rhino interpreter 基础上的,所以上述所有的优化都是安全的。


    ++++++++++++++++++++++++++++++++++

    扩展阅读:避免两种比较邪恶的写法:
    http://younglab.blog.51cto.com/416652/302712 

    1.eval()
    eval的作用是把字符串当成JavaScript语句来执行,我们经常用它来处理ajax请求后返回的值。

    但是eval有很多副作用,比如能访问全局变量:


    var message = "Hello world!";

    function doSomething() {
    eval("alert(message)");//Hello world!
    }


    上面的代码,如果使用YUI Compressor的变量替换原则来压缩的话就是:


    var A = "Hello world!";

    function doSomething() {
    eval("alert(message)"); 
    }


    因为eval()中的是字符串,所以YUI Compressor不会对其进行变量替换,这样一来压缩后的JavaScript就会出现错误。

    而YUI Compressor为了保证JavaScript的正确性,在遇到eval的时候,就不会压缩eval相关的变量。

    eval用得比较多的地方就是处理Ajax回调后的数据,例如:


    function handleJSONP(object) {
    return object;
    }

    function interpretJSONP(code) {
    var data = eval(code);

    //process data
    }


    使用eval来转换回调后得到的字符串。但是使用eval带来了全局变量被覆盖的危险,所以最好的方法是减少使用全局变量。

    有时候,你可能会把一些函数放在一个自动执行的匿名函数内,例如:


    (function() {
    function handleJSONP(object) {
    return object;
    }

    function interpretJSONP(code) {
    var data = eval(code);

    //process data
    }
    })();


    而由于其中出现了eval,所以整个匿名函数都不会进行变量替换,
    它会被压缩成:


    (function(){function handleJSONP(object){return object}function »
    interpretJSONP(code){var data=eval(code)}})();


    可以看到,代码段中的变量没有进行任何的压缩替换。
    更好的写法是:


    function myEval(code) {
    return eval(code);
    }

    function handleJSONP(object) {
    return object;
    }

    (function() {
    function interpretJSONP(code) {
    var data = myEval(code);

    //process data
    }
    })();


    压缩后变成了:


    function myEval(code){return eval(code)}function handleJSONP »
    (a){return a}(function(){function a(b){var c=myEval(b)}})();



    2.with
    使用with,可以避免重复地写同一个变量名。例如:


    var object = {
    message: "Hello, ",
    messageSuffix: ", and welcome."
    };
    object.message += "world" + object.messageSuffix;
    alert(object.message);


    可以写成:


    var object = {
    message: "Hello, ",
    messageSuffix: ", and welcome."
    };
    with (object) {
    message += "world" + messageSuffix;
    alert(message);
    }


    另外,如果object中没有某个属性是,with中使用到的变量会沿着作用域链去寻找它的定义,例如:


    function displayMessage(object) {
    var message = "Yo, ";

    with (object){
    message += "world" + messageSuffix;
    alert(message);
    }
    }

    displayMessage({ message: "Hello, ", messageSuffix: ", and welcome." });
    displayMessage({ messageSuffix: ", and welcome." });



    第二次调用时,输出的会是“Yo, world, and welcome.”

    不像eval,with没有什么更好的写法,而YUI Compressor也不会对with所在的函数进行变量替换,上面的函数压缩后是:


    function displayMessage(object){var message="Yo, ";with(object) »
    {message+="world"+messageSuffix;alert(message)}};


    大小是112 bytes。
    如果不使用with,


    function displayMessage(object) {
    var message = "Yo, ";

    object.message += "world" + object.messageSuffix;
    alert(object.message);
    }


    压缩后是:


    function displayMessage(a){var b="Yo, ";a.message+="world"+ »
    a.messageSuffix;alert(a.message)};


    大小是93 bytes,可以看到比使用with减少了不少。


    在百度搜索完整的Javascript压缩原理及压缩工具收集内容,或者用Google搜索相关的更多内容

    原文:http://www.cnbruce.com/blog/showlog.asp?log_id=1389

    如果感觉不错,请 一个!
    by simpman
  • 相关阅读:
    QT设置窗口屏幕居中
    屏蔽ubuntu桌面鼠标右键以及Ctrl Alt F*
    ubuntu12.04 U盘自动挂载配置
    最受欢迎的15个Python开源框架
    异步非阻塞IO的Python Web框架--Tornado
    RabbitMQ RPC问题
    petapoco模板修改
    事件&表达式
    .net core2 单元测试
    检查邮箱IP是否在国际反垃圾邮件组织的黑名单中
  • 原文地址:https://www.cnblogs.com/simpman/p/2961919.html
Copyright © 2011-2022 走看看