Google Closure Compiler高级压缩混淆Javascript代码
一、背景
前端开发中,特别是移动端,Javascript代码压缩已经成为上线必备条件。
如今主流的Js代码压缩工具主要有:
1)Uglify http://lisperator.net/uglifyjs/
2)YUI Compressor http://developer.yahoo.com/yui/compressor/
3)Google Closure Compiler https://developers.google.com/closure/compiler/
自从jQuery等流行库使用Uglify作为压缩工具,Uglify慢慢流行起来,如今也是很多开发工具(框架)默认使用的Js压缩工具,比如百度的Fis以及绝大部分的Yeoman脚手架等。YUI Compressor也逐渐被Uglify所替代。
Uglify的压缩策略较为安全,所以不会对源代码进行大幅度的改造,压缩相对较为保守。所以将通过Uglify压缩后的代码格式化之后,还是大致能看明白。
而Google Closure Compiler(以下简称GCC)的高级压缩则是完全重新改造JS代码,去除代码中一些可以直接输出运行结果的逻辑,去除根根本不会执行到的JS代码,从而压缩效率会更高。
二、GCC三种压缩模式
GCC提供三种压缩模式:
1)Whitespace only
2)Simple
3)Advanced
我们以这段简单的代码为例
function sayHello(name) {
alert('Hello, ' + name);
}
sayHello('binnng');
分别使用这三种压缩模式进行压缩:
Whitespace only
function sayHello(name){alert("Hello, "+name)}sayHello("binnng");
发现只是简单的去除空格换行注释。
Simple
function sayHello(a){alert("Hello, "+a)}sayHello("binnng");
比Whitespace only
要高端一点,在其基础上,还对局部变量的变量名进行缩短。这也是其他压缩工具所使用的压缩方式,如Uglify等,也是最为主流的压缩方式。比较安全。
Advanced
alert("Hello, binnng");
会发现,Advanced
级别的压缩改变(破坏)了原有代码结构,直接输出了代码最终运行结果,可见的确是分析
,重写
,破坏
,但是对代码压缩做到了极致,极大的减少了代码量。
注意的地方
正因为GCC是这样的破坏性压缩工具,所以使用起来得异常小心,稍微不规范可能就会引起压缩报错或者压缩成功后却不能正常运行。那么,如果要使用Advanced
级别压缩,要注意哪些呢?
以下所有未指名级别的GCC压缩均为Advanced
级别。
GCC会对变量的属性名也进行压缩
var data = {
user: "binnng",
age: "18"
}; if ("user" in data) {
alert(data.age);
} //经过Uglify压缩:
var data={user:"binnng",age:"18"};"user"in data&&alert(data.age); //经过GCC压缩:
var a={b:"binnng",a:"18"};"user"in a&&alert(a.a);
会发现GCC压缩时,将变量的属性名也缩短,代码量减少了,但是却带来了问题,会发现以上GCC压缩后的代码运行其实是不正确的。因为属性名缩短改变后,data已经不再拥有名为user
的属性了。
那如何解决呢?
var data = {
user: "binnng",
age: "18"
}; if (data.user) {
alert(data.age);
} //GCC压缩:
alert("18");
直接输出了正确的结果。
如果不想让GCC压缩属性名,比如在Ajax请求发送给后端接口的时候,可以将属性名用双引号包裹:
var data = {
"user": "binnng",
"age": "18"
}; var ajax = function(url, data, callback) {
(new window.XMLHttpRequest()).send(data);
// ...
}; ajax("//baidu.com", data, function(res) {console.log(res)}); //GCC压缩后:
(new window.XMLHttpRequest).send({user:"binnng",age:"18"});
原封不动的保留了后端需要的参数名。
全局变量要显式挂载在window下
var foo = "1234";
alert(widnow.foo);
//经过GCC压缩后: alert(window.a);
有点莫名其妙。。因为在GCC中,不再认可隐式全局变量,所以上面的代码中在GCC眼里,foo
是没有挂载到window下的,所以下文的window.foo
其实是未定义的。
要解决这个问题,必须将foo
显式挂载到window下:
window.foo = "1234";
alert(widnow.foo);
//这样经过压缩后: window.a="1234";alert(widnow.a);
这时候可能就会疑问,为何不直接压缩成alert("1234")
呢?这是因为GCC不会去除挂载在window下的变量。
必要时导出变量函数等
window.btnClick = function() {
alert("clicked");
};
//以上的代码经过压缩后成为: window.a=function(){alert("clicked")};
此时,如果HTML中存在如下代码,就会报错。
<a onclick="btnClick()">点我</a>
//这时候就需要导出函数: window["btnClick"] = function() {
alert("clicked");
};
用双引号包裹后,btnClick
就保留了下来。在构造函数中,尤其需要注意导出,例如:
var Animal = function(name) {
this.name = name;
};
Animal.prototype.eat = function() {
alert(this.name + " is eating!");
};
以上的代码经过GCC压缩后,什么都没剩下,因为GCC认为,代码中的代码都没有执行,属于dead code
。既然这么写了,那肯定是需要它,提供给别人外部调用什么的,这时候就需要这么导出:
var Animal = function(name) {
this.name = name;
};
Animal.prototype.eat = function() {
alert(this.name + " is eating!");
}; window["Animal"] = Animal;
Animal.prototype["eat"]= Animal.prototype.eat;
//经过压缩后: function a(b){this.name=b}a.prototype.a=function(){alert(this.name+" is eating!")};window.Animal=a;a.prototype.eat=a.prototype.a;
这时候,Animal
这个方法成功的保留了下来。
还有,在使用JSONP
方式获取服务端数据的时候,也一定要导出callback方法名:
var jsonpCb = function() {
//...
}; getScript("/api/data?callback=jsonpCb"); // 导出,否则jsonpCb会被压缩掉不能被识别
window["jsonpCb"] = jsonpCb;
所有业务代码合并压缩
a.js var getName = function() {return "binnng"};
b.js alert(getName());
如果单独压缩a.js
和b.js
就会出问题,结果会是a.js
中什么都没有,b.js
中getName
方法未定义(undefined
)。正确的做法则是,两者合并再进行压缩。
三、GCC三种运行方式
1)、”Closure Compiler Service UI”:GCC提供的在线压缩方式,只需导入文件路径或是直接复制粘贴文件内容,即可实现压缩。在线压缩网站为:http://closure-compiler.appspot.com/home详细步骤如下:
A.打开页面,在”Add a URL”文本框中输入文件路径,然后点击”add”。或者直接把文件内容复制到下边的文件域中。
B.在”Optimization”中选择压缩模式,默认为”Simple”模式。
C.点击”Compile”按钮,进行压缩。如图,右侧这显示压缩完的文件信息。
D.可以选择复制下面的文本内容粘贴到压缩前原文件,或者右键点击”default.js”-->”链接另存为”,直接将压缩完的文件重命名并保存到本地。
2)、”Closure Compiler Service API”:通过自定义HTML页面发送请求的方式来获取压缩文件。与”Closure Compiler Service UI”相比,它可以建立自己的工具,创建自己的工作流。而”Closure Compiler Service UI”只适合压缩少量的代码和文件。详细步骤如下:
A.创建一个名为”closure_compiler_test.html”的HTML页面,用于发送post请求。代码如下:
<html> <body> <form action="http://closure-compiler.appspot.com/compile" method="POST"> <p>Type JavaScript code to optimize here:</p> <textarea name="js_code" cols="50" rows="5"> function hello(name) { // Greets the user alert('Hello, ' + name); } hello('New user'); </textarea> <input type="hidden" name="compilation_level" value="WHITESPACE_ONLY"> <input type="hidden" name="output_format" value="text"> <input type="hidden" name="output_info" value="compiled_code"> <br><br> <input type="submit" value="Optimize"> </form> </body> </html>
B.用浏览器打开该HTML文件,点击”Optimize”按钮提交,并会返回压缩后文件。然后复制粘贴保存。
注意:每个请求至少必须发送以下参数:
a.”js_code”或”code_url”:这个参数的值指示要编译的JavaScript。必须至少包含其中一个参数,并且可以同时包括。”js_code”必须是包含javascript的字符串。”code_url”必须是包含js文件的url地址。
b.”compilation_level”:这个参数表示文件压缩的模式,有三个值,分别为”whitespace_only”,”simple_optimizations”,”advanced_optimizations”。上文用的是”whitespace_only”,默认为”simple_optimizations”。
c.”output_info”:此参数的值指示要从编译器获取的信息类型。有四个值,分别为”compiled_code”,”warnings”,”errors”,”statistics”。上文用的是”compiled_code”,返回的是压缩好的文件。
d.”output_format”:此参数表示输出的格式。有三个值,分别为”text”,”json”,”xml”,默认为”text”。
更多关于API的使用请参照官网。
3)、”Closure Compiler Application”:用官网提供的客户端进行代码压缩。从官网下载压缩包,地址为:https://dl.google.com/closure-compiler/compiler-latest.zip。本客户端是在Java环境下运行的,所以下载之前应安装JDK。安装JDK步骤参考:http://jingyan.baidu.com/article/2d5afd6993a6db85a2e28e9f.html
详细步骤如下:
A.创建一个名为”closure-compiler”的文件夹。
B.把下载的压缩包解压到”closure-compiler”下。
C.把要压缩的js文件也放到当前目录下。
D.用命令窗口打开文件夹中”README.md”文件。打开如下
系统会自动进入到当前文件位置。如果没有打开,可以尝试如下做法:
a.按”windows+r”键,进入“运行”,输入”cmd”,进入命令窗口。
b.然后输入刚刚创建的”closure-compiler”文件夹的路径。例:”F:\workspace\closure-compiler”,则如下:
E.然后输入”java -jar 目录下.jar文件--js 目录下.js文件--js_output_file 压缩完保存的文件名”,例:”java -jar closure-compiler-v20161201.jar --js setting.js --js_output_file setting.min.js”,生成的文件也会保存在当前的目录下(closure-compiler文件夹)。生成的文件的压缩模式默认为”SIMPLE”,如果要改变其他的压缩模式,在上边的的语句中添加”--compilation_level=ADVANCED”,值可以为”WHITESPACE_ONLY”,”SIMPLE”,”ADVANCED”。
如果想了解更多使用方法,请输入”java -jar closure-compiler-v20161201.jar --help”。
四、结语
GCC的高级压缩(Advanced)非常强大,对代码压缩做到了极致,但是其对代码书写要求也比较严格,并且破坏性压缩也被很多开发者所诟病。
但是稍加注意,严格规范自身代码风格,了解GCC压缩方式原理,利用好GCC高级压缩,一定会大大减少JS的体积,从而大幅度的提升前端代码性能。
另外,GCC像其他压缩工具一样,也有Grunt
、Gulp
构建组件,可以很方便的去使用它。
转载自:
1)https://segmentfault.com/a/1190000002575760
2)https://blog.csdn.net/nh18304030935hn/article/details/54571682
Google Closure Compiler高级压缩混淆Javascript代码的更多相关文章
- 使用Google Closure Compiler高级压缩Javascript代码
背景 前端开发中,特别是移动端,Javascript代码压缩已经成为上线必备条件. 如今主流的Js代码压缩工具主要有: 1)Uglify http://lisperator.net/uglifyjs/ ...
- 使用Google Closure Compiler高级压缩Javascript代码注意的几个地方
介绍 GCC(Google Closure Compiler)是由谷歌发布的Js代码压缩编译工具.它可以做到分析Js的代码,移除不需要的代码(dead code),并且去重写它,最后再进行压缩. 三种 ...
- 使用Google Closure Compiler全力压缩代码(转)
JavaScript压缩代码的重要性不言而喻,如今的压缩工具也有不少,例如YUI Compressor,Google Closure Compiler,以及现在比较红火的UglifyJS.Uglify ...
- Google Closure Compiler 高级模式及更多思考(转)
前言 Google Closure Compiler 是 Google Closure Tools 的一员,在 2009 年底被 Google 释出,早先,有 玉伯 的 Closure Compile ...
- JavaScript代码压缩工具UglifyJS和Google Closure Compiler的基本用法
网上搜索了,目前主流的Js代码压缩工具主要有Uglify.YUI Compressor.Google Closure Compiler,简单试用了UglifyJS 和Google Closure Co ...
- 使用jsCompress压缩混淆js代码的一些常见的问题和技巧
不同的团队使用的js混淆器或压缩工具不一样,jsCompress是一款绿色的免费的js压缩工具,时代定制的UI团队推荐大家使用,不仅性能优越,而且操作非常人性化. 使用jsCompress.exe时, ...
- 【转】使用Jasob混淆javascript代码
在平常的web开发中,我们时常需要写一些js的类库,当我们发布自己产品的时候,不得不把源代码分发出去:但是这样就会泄露自己的代码.今天使用了一下Jasob感觉不错: 使用Jasob,我们的JavaSc ...
- bootstrap-datetimepicker在经过GC(Google Closure Compiler)压缩后无法使用的解决方案
将压缩级别由simple改成whitespace 问题就是这样之后压缩后的文件大了很多 <?xml version="1.0"?> <project name=& ...
- 使用Google的Closure Compiler,在本机上压缩javascript
2011-12-05 13:47:39 1.JAVA JDK下载地址: http://download.oracle.com/otn-pub/java/jdk/7u1-b08/jdk-7u1-wi ...
随机推荐
- Java开发笔记(三十九)日期工具Date
Date是Java最早的日期工具,编程中经常通过它来获取系统的当前时间.当然使用Date也很简单,只要一个new关键字就能创建日期实例,就像以下代码示范的那样: // 创建一个新的日期实例,默认保存的 ...
- 数据结构(java版)学习笔记(一)——线性表
一.线性表的定义 线性表是n(n>=0)个具有相同特性的数据元素的有限序列. 线性表是最简单.最常用的一种数据结构 线性表属于线性结构的一种 如果一个数据元素序列满足: (1)除第一个和最后一个 ...
- win10安装ubuntu16.04双系统
前话:因为感兴趣吧也是专业需要,所以自学了U盘重装系统以及在win10的情况下安装Ubuntu16.04双系统.借此博客,记录下我安装Ubuntu的过程,方便日后回忆. 正因如此,本篇博客会写的十分简 ...
- SAP MM 无价值物料管理的一种实现思路
SAP MM 无价值物料管理的一种实现思路 笔者所在的项目,客户工厂处于先期试生产阶段,尚未开始大规模的商业化生产,但是这并不影响客户集团总部的SAP项目实施.笔者于7月初加入该工厂的第2期SAP项目 ...
- SpringBoot集成mybatis配置
一个有趣的现象:传统企业大都喜欢使用hibernate,互联网行业通常使用mybatis:之所以出现这个问题感觉与对应的业务有关,比方说,互联网的业务更加的复杂,更加需要进行灵活性的处理,所以myba ...
- C# 一款属于自己的音乐播放器
本文利用C# 调用Windows自带的Windows Media Player 打造一款属于自己的音乐播放器,以供学习分享使用,如有不足之处,还请指正. 概述 Windows Media Player ...
- Android下获取FPS的几种方法
FPS(Frames Per Second)是关乎Android用户体验最为重要的指标之一,而在VR中更是如此.为了评估VR系统.VR SDK及Unity应用的性能,通常会实时获取FPS并将其显示出来 ...
- Spring 事务与脏读、不可重复读、幻读
索引: 目录索引 参看代码 GitHub: 1.Spring 事务 2.事务行为 一.Spring 事务: Spring 的事务机制是用统一的机制来处理不同数据访问技术的事务处理. Spring 的事 ...
- lnmp环境里安装mssql及mssql的php扩展
小活中用到mssql,于是在自己lnmp环境中安装各mssql数据库 步骤如下: 源码编译安装 (1)下载freetds-stable-0.91源码:http://download.csdn.net/ ...
- adb.exe 安卓测试桥的使用
一.android SDK提供了几个工具 (在SDK下build-tools目录下的工具) dx.bat ----------->把java编译器编译生成的.class 文件 ,变成一个文件,让 ...