YAOHAIXIAO.COM

HTML(5),CSS(3),JavaScript,DOM,Ajax,JSON,Front-end technologies & Yaohaixiao

热门标签:JavaScript Performance 前端开发 前端性能优化 原创

Rss

Home » Tools » 隐藏 JavaScript 源代码?不,你只能混淆和压缩JavaScript源代码

隐藏 JavaScript 源代码?不,你只能混淆和压缩JavaScript源代码

隐藏、加密 JavaScript 源代码

自己写了很酷的代码,希望防止别人剽窃你的JavaScript代码。怎么才可以隐藏或者说是加密我的JavaScript代码啊?说实话,我以前也这么想过,不过很遗憾。JavaScript代码是一种天然的开放源代码的语言。除非你的JavaScript代码在你的本机里保存着,一旦作为在线的程序发布出去,只要浏览器可以运行访问它,任何人也就可以阅读到它。

你可能在网上看过有人说可以加密JavaScript源代码,但就像其他所有的加密方法一样,都是无法保证别人解密不了的。而实际上,从实际的前端性能来说,这些经过加密的代码反而会造成不必要的性能损失,甚至可能会让JavaScript代码无法正常运行。所以我的建议,不要花时间想着加密你的JavaScript代码,这完全是在瞎折腾自己,浪费时间。

当然,我说的是没有必要加密你的JavaScript代码,但不是说没有必要保护你的劳动成果。其实,实际的开发中,我们常常做的一个简单的保护措施就是混淆你的JavaScript代码。混淆后的代码会变得非常的不宜阅读,可以起到一些保护的作用。下面我就跟大家谈谈如何混淆JavaScript代码。

混淆和压缩JavaScript源代码

实际的开发中,我们常常会混淆并压缩代码。前面我提到过,采取混淆压缩过的代码会变得很难阅读,能够起到一些保护代码的作用。这里我给个实际的例子,看看混淆压缩前后的代码有什么不同:

// 混淆压缩前
var SetAnimateDefaultTopLeft = function(){
    // 遍历 $('.animate')这个nodeList集合
    $('.animate').each(function(i, animateElement){
	    // 获得当前的动画DOM元素
        var animateImg = $(animateElement);
		var imgAlt = '动画图片';
		// 给当前元素添加'data-defaulttop'属性和'data-defaultleft'属性和各自的属性值
        animateImg.attr('data-defaulttop', animateImg.position().top);
        animateImg.attr('data-defaultleft', animateImg.position().left);
    });
};

// 混淆压缩后
var SetAnimateDefaultTopLeft=function(){$(".animate").each(function(c,a){var d=$(a);var b="\u9354\u3127\u657e\u9365\u5267\u5896";d.attr("data-defaulttop",d.position().top);d.attr("data-defaultleft",d.position().left)})};

同样的代码,现在就不是那么容易阅读了吧?我这里就直接说出两段代码的不同吧:

  • 移除了所有不必要的空格和换行,起到压缩代码体积的作用。
  • 移除所有代码注释,起到压缩代码体积的作用。
  • 使用单个字母取代有意义的变量名称,起到混淆代码的作用,并且也压缩了代码体积。
  • 将中文字符转义为unicode字符,起到混淆代码作用。

其实上面的不同也直接指出了为什么要做混淆压缩代码的处理,也是这么处理的好处。主要的目的不是在于为了混淆代码,而是要压缩代码体积,从而能够加快页面加载JavaScript脚本文件的速度。加载快了, 当然也会让页面执行脚本的速度更快。所以,再重复一次:混淆和压缩JavaScript源代码的目的主要是为了优化前端性能。

混淆和压缩JavaScript源代码的工具

知道为什么要混淆和压缩JavaScript源代码后,接下来我就要介绍如何来压缩,有哪些工具来帮助我们高效的完成这项工作。

TBCompressor

当然,压缩的工具有很多,这里我不一一介绍,我要隆重介绍的是:TBCompressor

TBCompressor 是由淘宝网的前端工程师们在YUI Compressor的基础上修改而来的。TBCompressor 不仅可以压缩 JavaScript代码,也可以压缩CSS代码。而TBCompressor使用起来相对YUI Compressor来说也更加方便。这里要顺便要说一下的是 YUI Compressor和TBCompressor 都是针对 Windows 平台开发的。下面我就介绍一下如果使用TBCompressor来压缩JavaScript代码。

TBCompressor 的配置

不要看到需要配置就吓到了,配置TBCompressor的步骤其实很简单的。前面也介绍了,TBCompressor 是在 YUI Compressor 的基础上开发出来的。而 YUI Compressor 是一款 Java 开发的程序(requires Java >= 1.4),所以如果要使用TBCompressor,你要做的第一件事情是在你的电脑环境中配置Java环境。

安装,配置 Java 环境变量

首先,到Oracle下载最新的JDK。然后选择将Java安装到 C:/Java目录。那么你的JDK的目录就是 C:/Java/jdk(我一般都去掉版本号,更新的时候直接覆盖安装)。

其次,配置Java的Path和ClassPath环境变量。到桌面,右键点击“我的电脑”,选择“属性”菜单,Windows XP 系统会直接弹出“系统属性”窗口,Windows 7 系统则需要点击“高级系统设置”,才会出现“系统属性”窗口,如下图:

“系统属性”窗口

“系统属性”窗口

点击“环境变量按钮”,弹出“环境变量”窗口,如下图

Java-Config-2

“环境变量”窗口

我们需要新建一个叫“JAVA_HOME”(习惯都是大写字符)的系统环境变量,点击窗口的“系统变量”下的“新建…”按钮,弹出“新建系统变量”窗口,分别在“变量名”和“变量值”,输入JAVA_HOME和C:/Java/jdk(根据你安装JDK的路径自行调整),如下图:

Java-Config-3

“新建系统变量”窗口

一般新用户是没有“ClassPath”环境变量的,所以你还要在此重复上面的方法,创建一个“ClassPath”的环境变量,只是“变量名”和“变量值”现在分别是“ClassPath”和“.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;”。

系统默认都是有“Path”这个变量的,所以你这是要选中“Path”,点击“编辑”按钮,在“变量值”中添加上Java的“Path”变量值:“JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;”,如下图:

Java-Config-4

添加“Path”系统变量

我是将值加到了原来值的最前面,你也可以加到原来值的最后面,只是要记得,注意最后的值之后有没有“;”分号。有的话,就可以直接把值添加进去,没有则需要在值的最后添加“;”,然后在将值添加进去。到此Java环境变量配置完毕。

最后,验证Java环境变量是否配置成功。在“开始”菜单的运行框中输入”cmd”,敲击“Enter”按钮,弹出命令行程序窗口,输入:“java -version”命令。配置成功就会显示当前Java程序的版本信息,如下图:

验证Java环境变量是否配置成功,查看Java程序版本信息

验证Java环境变量是否配置成功,查看Java程序版本信息

配置 TBCompressor 的compressor.cmd文件

这个很简单,我就把代码贴出来:

@echo off
color 03
REM =====================================
REM    Taobao Compressor CMD Script
REM
REM     - by yubo@taobao.com
REM     - 2009-02-12
REM =====================================
SETLOCAL ENABLEEXTENSIONS

echo.
echo Taobao Compressor v2.4.2

REM 过滤文件后缀,只压缩js和css
if "%~x1" NEQ ".js" (
    if "%~x1" NEQ ".css" (
        echo.
        echo **** 请选择CSS或JS文件
        echo.
        goto End
    )
)

REM 检查Java环境
if "%JAVA_HOME%" == "" goto NoJavaHome
if not exist "%JAVA_HOME%\bin\java.exe" goto NoJavaHome
if not exist "%JAVA_HOME%\bin\native2ascii.exe" goto NoJavaHome

REM 获取压缩后的文件名,规则为:
REM 1. 文件名有.source时: filename.source.js -> filename.js
REM 2. 其它情况:filename.js -> filename-min.js
set RESULT_FILE=%~n1-min%~x1
dir /b "%~f1" | find ".source." > nul
if %ERRORLEVEL% == 0 (
    for %%a in ("%~n1") do (
        set RESULT_FILE=%%~na%~x1
    )
)

REM 调用yuicompressor压缩文件
"%JAVA_HOME%\bin\java.exe" -jar "%~dp0yuicompressor.jar" --charset GB18030 "%~nx1" -o "%RESULT_FILE%"

REM 下面解决编码问题:当js文件的编码与页面编码不一致时,非ascii字符会导致乱码,处理办法是:
REM 1. 对于js文件,还需要调用native2ascii.exe将非ascii字符用\uxxxx表示
REM 2. 对于css文件,需要将非ascii字符转换为\uxxxx, 同时将u去掉(css只认识\xxxx)
REM 3. 目前只处理了js文件
REM 4. 对于css文件,只有font-family和:after等中可能有非ascii字符,情况很少,手工处理
if "%~x1" == ".js" (
    copy /y "%RESULT_FILE%" "%RESULT_FILE%.swp" > nul
    "%JAVA_HOME%\bin\native2ascii.exe" -encoding GB18030 "%RESULT_FILE%.swp" "%RESULT_FILE%"
    del /q "%RESULT_FILE%.swp"
)

REM 显示压缩结果
if %ERRORLEVEL% == 0 (
    echo.
    echo 压缩文件 %~nx1 到 %RESULT_FILE%
    for %%a in ("%RESULT_FILE%") do (
        echo 文件大小从 %~z1 bytes 压缩到 %%~za bytes
    )
    echo.
) else (
    echo.
    echo **** 文件 %~nx1 中有写法错误,请仔细检查
    echo.
	goto End
)

REM 检查是否含有内网地址(taobao.net)
find /i "taobao.net" "%RESULT_FILE%" > nul
if %ERRORLEVEL% == 0 (
	echo.
	echo **** 注意:%~nx1 中含有 taobao.net, 建议修改为线上地址
	echo.
)
goto End


:NoJavaHome
echo.
echo **** 请先安装JDK并设置JAVA_HOME环境变量
echo.

:End
ENDLOCAL
pause

配置文件中所有的“%JAVA_HOME%”值的地方是大家要更具自己的JAVA_HOME环境变量自行调整的,如果你是按我前面教的步骤处理的,就没有任何问题了。

使用 TBCompressor 压缩文件

配置好了后,大家要先运行“install.cmd”程序,将TBCompressor安装到系统中,这样我们就可以通过直接选中JavaScript文件,点击右键,在菜单中选择“Compressor CSS or JS”选项来方便的压缩JavaScript代码了。压缩时会弹出这样的一个窗口:

TBCompressor

TBCompressor 压缩JavaScript代码

压缩结束后,按任意键就关闭这个窗口。我们就会看到在你选择的JS文件目录下,多了一个“-min.js”的文件,例如我压缩的是test.js文件,压缩完成后,在同目录下生成了test-min.js文件。

压缩生成-min.js代码

压缩生成-min.js代码

Packer 混淆算法

其实,仔细看看TBCompressor压缩的后的结果,并不是真正的混淆代码,只是简化了变量的名称,主要的目的是压缩代码体积。而 Dean Edwards编写的Packer算法,才是真正的混淆算法。还是来看看Packer算法混淆前后的代码吧:

// 混淆前的代码
(function($){
    var images = ['images/arrow-up.png', 'images/arrow-down.png', 'images/bg.png', 'images/what-is-product.png', 'images/what-is-intro-bg.png', 'images/nutrition-product.png', 'images/nutrition-intro-bg.png', 'images/compare-product.png', 'images/compare-intro-bg.png', 'images/suitable-product.png', 'images/suitable-intro-bg.png', 'images/efficacy-product.png', 'images/efficacy-intro-bg.png', 'images/buy-product.png', 'images/buy-intro-bg.png'], completedCount = 0, totalCount = images.length;
    $(images).imgpreload({
        each: function(){
            completedCount += 1;
            $('#preloader .preload-status .progress').height(Math.round(260 * (completedCount / totalCount)));
            if (completedCount >= totalCount) {
                $('#preloader').hide();
            }
        },
        all: function(){
            $('#preloader').hide();
        }
    });
})(jQuery);

// 混淆后的代码
eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(8($){l a=[\'2/c-m.3\',\'2/c-n.3\',\'2/4.3\',\'2/d-e-5.3\',\'2/d-e-6-4.3\',\'2/f-5.3\',\'2/f-6-4.3\',\'2/g-5.3\',\'2/g-6-4.3\',\'2/h-5.3\',\'2/h-6-4.3\',\'2/i-5.3\',\'2/i-6-4.3\',\'2/j-5.3\',\'2/j-6-4.3\'],7=0,9=a.o;$(a).p({q:8(){7+=1;$(\'#b .r-s .t\').u(v.w(x*(7/9)));y(7>=9){$(\'#b\').k()}},z:8(){$(\'#b\').k()}})})(A);',37,37,'||images|png|bg|product|intro|completedCount|function|totalCount||preloader|arrow|what|is|nutrition|compare|suitable|efficacy|buy|hide|var|up|down|length|imgpreload|each|preload|status|progress|height|Math|round|260|if|all|jQuery'.split('|'),0,{}))

看看混淆后的代码是不是真的看得一头雾水了?!Packer 混淆算法不光混淆了JavaScript代码,同时也压缩了代码。而且明显可以看出,Packer 算法的混淆效果更好。不过就像之前说的,这个算法是可以反编码的,所以实际的“加密”效果并不好。

TBCompressor vs Packer

TBCompressor 还是 Packer 的效果好呢?个人更喜欢TBCompressor。因为之前说过,TBCompressor只是压缩代码,并没有其他的处理,所以加载的代码直接运行即可。而Packer算法则需要运行eval()处理压缩混淆的代码。而eval()的处理效率可不高,即使现在的浏览器性能提高了很多,但毕竟Packer算法需要多处理一步,自然会花费更多的时间来执行代码。事实也证明了这一点,现在所有的JavaScript框架提供的压缩版本的都只是采取的跟TBCompressor一样的处理方式。

其它的JavaScript压缩工具

JSMIN就是非常注明的一个算法,Crockford 大牛在2003年就提出了这个算法,有兴趣的朋友大家可以了解一下,这里是JavaScript利用这个算法实现的在线工具:JavaScript Minifier

JSBuilder2是配合Ext 3新发布的Ajax打包工具。JSBuilder也是到阿里巴巴工具站工作时用的第一个压缩工具。它可以很方便的把同个文件打包压缩到同一个.js文件中。感兴趣的朋友可以看看这篇文章:《用 JSBuilder 压缩你的 JavaScript / CSS 源代码 》。

YSlow是一个Firefox插件,最为一个前端性能的分析工具大家应该都知道。不过不直到大家使用过tools工具没有?YSlow Tools提供了压缩JavaScript代码和CSS代码的功能,大家可以去试试。

YSlow Tools

YSlow Tools

Google Closure Compiler提供三种压缩方法,分别是空格移除、简单压缩及进阶压缩。简单压缩基本上只是把comments 和空格拿走(跟YUI Compressor 基本一样);进阶压缩除以上功能外,还能够rename variable name、甚至重写某些statement!很好很强大!

当然JavaScript的压缩工具不光只上面介绍的几款工具,例如YAHOO开发的PHP Minify(感兴趣的朋友可以看看《使用PHP Minify来做前端性能优化》这篇文章)。另外,像Aptana这样的编辑器也提供Minify压缩JavaScript代码。

压缩JavaScript代码要注意的问题

压缩JavaScript代码时要注意两点:

第一:备份你原始的JavaScript代码,也就是我们通常说的debug版本。可以想象以后修改代码时,面对压缩后代码一头雾水的痛苦。

第二:编写代码时要准确而严格的使用“;”分号结束。否则,压缩移除换行和空格时就会出现问题,让代码无法运行。而代码被压缩到一行后,要调试定位错误也是件非常痛苦的事情。所以,有一个良好的编码风格也是非常重要的。

好了,到这里关于压缩JavaScript代码相关的内容介绍得差不多了,我们要清楚一点,压缩JavaScript代码的目的是为了优化前端性能,而并非为了所谓的“加密”程序。由于篇幅和能力有限,我也不可能把相关的问题介绍的面面俱到,如果你想知道这些压缩工具性能比较,大家可以看看《Yahoo YUI Compressor vs. Microsoft AJAX Minifier vs. Google Closure Compiler》。

声明:本文采用BY-NC-SA协议进行授权。转载请注明转自:隐藏 JavaScript 源代码?不,你只能混淆和压缩JavaScript源代码

« »

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(Spamcheck Enabled)