uglifyjs压缩JS的

1、故事总有其背景

年底将至,不少闲适的时间,因而刷刷微博,接触各类纷杂的信息——美其名曰“学习”。运气不错,遇到了一个新名词,uglifyjs. 听说是用来压缩JS文件的,听说还能优化JS,听说是基于node的,还听说比Google Closure Compiler更带感,哦?激起了个人好奇心。百之谷之,哟,相关的介绍还很多。而后折腾了个把小时,基本上知道了是个怎么回事。javascript

我以为吧,仍是有些用的,即便是否是从事node开发的人,抽个小空,share之,因而就有了本文。人总有浮躁的时候,我也不例外,uglifyjs内部深刻的运做是如何的,唉,我是有气无力,不想去折腾,因此,本文更可能是停留在应用层面。不过嘛,这样反而受众面广一些。毕竟喜欢看《泰囧》的人要比《一代宗师》的多。php

2、node相关的固定流程

凡事说起node应用,无非免不了相似下面的流程:html

  1. 安装node
  2. 安装nmpnpm
  3. 安装当前应用 – uglifyjs

前两个网上太多示意了,我以前也讲过,sorry, 我很懒。
uglifyjs安装以下code:前端

npm install uglify-js -g

一个回车,因而啪啪啪,就有下图所示的东东:
uglifyjs安装显示截图 张鑫旭-鑫空间-鑫生活java

因而,下面就能够压缩JS了。node

3、uglifyjs JS压缩

uglifyjs压缩有不少的参数,详见其github托管项目。其中有一些可选参数,以下部分截图:
uglifyjs的一些可选参数截图 jquery

什么美化压缩,空格多长,变量名是否变成短名字等……您有兴趣能够本身去看看,若是今天不是星期五,若是不是要赶回去买菜,我就会翻译下的——诸位,请原谅我吧,阿门!git

下面演示如何使用uglifyjs压缩JS.github

个人桌面上有个名叫formini的文件夹,我会把要压缩的文件放在其中,而后再压缩。如今,我从内部拷贝了一个名叫inet.js的JS文件到这个文件夹中,而后:sql

  1. 打开cmd, 这个不会我就没有办法了
  2. 目录引到formini文件夹,cd 而后什么什么的,这个不会我也没有办法了
  3. 以下代码:
    uglifyjs inet.js -o inet-min.js
  4. 再运行以下代码,测试-m可选参数:
    uglifyjs inet.js -m -o inet.min.js

    以下截图:
    压缩运行代码

噢啦,如今就是看结果了,见下截图:
压缩后的JS文件大小 张鑫旭-鑫空间-鑫生活

90K的是没有运行-m参数的,70K(69.4)的是运行的。-m参数因此就是把变量名变成a, b, c, d, ...

从实际应用角度讲,上线的JS显然要压缩变量,减少必定的文件尺寸。

跟YUICompressor相比,大小只小了0.6K, 不过网上反映uglifyjs相比YUI压缩很明显,我这里的大小仅优化了0.6÷174=0.345%,这只能说明我写的代码还算比较优化,哈哈(忽然想起了老婆的话,不要得瑟,深呼吸……深呼吸……)!
YUICompressor压缩后的大小

4、uglifyjs压缩批处理

咱们不可能每次都打开cmd去键入压缩执行代码,容易写错不说(如上面那个结果图),还耗时,想一想都会让人疯掉。懒人有懒法,花了点功夫,折腾了一个批处理文件,之后,想要压缩JS,只要双击运行这个.bat文件就能够了!完整代码以下:

@echo off
:: 设置压缩JS文件的根目录,脚本会自动按树层次查找和压缩全部的JS
SET JSFOLDER=C:\Users\Administrator\Desktop\formini
echo 正在查找JS文件
chdir /d %JSFOLDER%
for /r . %%a in (*.js) do (
    @echo 正在压缩 %%~a ...
    uglifyjs %%~fa  -m -o %%~fa
)
echo 完成!
pause & exit

新建一个txt文档,任意命名,将上面的代码粘贴进去,修改JSFOLDER后面的文件夹目录为你本身的,而后把.txt后缀改为.bat就能够啦!而后双击就能够批量使用uglifyjs压缩JS文件啦!

4、结束语

对于本身来说,本文内容算做备忘。目前而言,我仍是uglifyjs不能压缩CSS文件。不过嘛,了解下总会有帮助的。行文匆忙,文中要是有表述不许确的地方欢迎指正。

 

另一篇文章介绍

前言

作Web前端开发,老是要考虑页面的打开速度,若是文件数量越少、文件长度越小,就能够直接的提高网页的访问速度。

但在开发的时候,为了保证代码的可读性,咱们写的程序文件会不少并且很大,这样就与部署的要求发生背离,经过UglifyJS2这个工具,咱们能够在开发完成时,对代码文件进行 合并、混淆、压缩 等的操做,达到最优的访问性能。

目录

  1. UglifyJS介绍
  2. UglifyJS2介绍
  3. UglifyJS2安装
  4. UglifyJS2命令操做
  5. UglifyJS2的API使用

1. UglifyJS介绍

开始UglifyJS2介绍以前,咱们先要说一下UglifyJS。 UglifyJS 是UglifyJS2的前身,是一个Javascript开发的通用的语法分析、代码压缩、代码优化的一个工具包。UglifyJS是基于Nodejs环境开发,支持CommonJS模块系统的任意的Javascript平台。

UglifyJS的实现主要分为2部分:

  • 生成JS代码的抽象语法树(AST),经过parse-js.js完成。
  • 遍历AST语法树,作各类操做,好比自动缩进、缩短变量名、删除块括号{}、去空格、常量表达式、连续变量声明、语块合并、去掉没法访问的代码等,经过process.js完成。

2. UglifyJS2介绍

UglifyJS2 是做者对UglifyJS的重写,是彻底的重写,而不只仅是升级。从UglifyJS2官司方网页介绍看,UglifyJS2把整个的JS压缩过程,作了更进一步的细化。

上述全部的功能代码API是 在6500行的左右,比其余的相同功能的开发包都要小。做者还提供了一个在线版本UglifyJS2的JS压缩工具, http://lisperator.net/uglifyjs/,你们能够测试一下。

3. UglifyJS2安装

系统环境:

  • win7 64bit
  • Nodejs:v0.10.5
  • Npm:1.2.19

UglifyJS2的安装很是简单,和Nodejs的其余包同样,全局安装使用以下命令。

npm install uglify-js -g

也能够经过github下载源代码安装。

git clone git://github.com/mishoo/UglifyJS2.git cd UglifyJS2 

咱们在使用UglifyJS2的时候主要有2种方式,一种是经过命令行操做,对指定的JS文件进行压缩;另外一种是经过程序的API调用,对文件或内存中的JS代码进行压缩。下面我将分两种状况进行介绍。

4. UglifyJS2命令操做

在全局安装好UglifyJS2之后,咱们就可使用UglifyJS2的命令了。

打印uglifyjs命令行的帮助信息,会打出很长一段说明。

D:\workspace\javascript\nodejs-uglifyJS2>uglifyjs -h
D:\toolkit\nodejs\\node.exe D:\toolkit\nodejs\node_modules\uglify-js\bin\uglifyjs input1.js [input2.js ...] [options]
Use a single dash to read input from the standard input.

NOTE: by default there is no mangling/compression.
Without [options] it will simply parse input files and dump the AST
with whitespace and comments discarded.  To achieve compression and
mangling you need to use `-c` and `-m`.

Options:
  --source-map Specify an output file where to generate source map. [string] --source-map-root The path to the original source to be included in the source map. [string] --source-map-url The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map. [string] --source-map-include-sources Pass this flag if you want to include the content of source files in the source map as sourcesContent property. [boolean] --in-source-map Input source map, useful if you're compressing JS that was generated from some other original code. --screw-ie8 Pass this flag if you don't care about full compliance with Internet Explorer 6-8 quirks (by default UglifyJS will try to be IE-proof). [boolean] --expr Parse a single expression, rather than a program (for parsing JSON) [boolean] -p, --prefix Skip prefix for original filenames that appear in source maps. For example -p 3 will drop 3 directories from file names and ensure they are relative paths. You can also specify -p relative, which will make UglifyJS figure out itself the relative paths between original sources, the source map and the output file. [string] -o, --output Output file (default STDOUT). -b, --beautify Beautify output/specify output options. [string] -m, --mangle Mangle names/pass mangler options. [string] -r, --reserved Reserved names to exclude from mangling. -c, --compress Enable compressor/pass compressor options. Pass options like -c hoist_vars=false,if_return=false. Use -c with no argument to use the default compression options. [string] -d, --define Global definitions [string] -e, --enclose Embed everything in a big function, with a configurable parameter/argument list. [string] --comments Preserve copyright comments in the output. By default this works like Google Closure, keeping JSDoc-style comments that contain "@license" or "@preserve". You can optionally pass one of the following arguments to this flag: - "all" to keep all comments - a valid JS regexp (needs to start with a slash) to keep only comments that match. Note that currently not *all* comments can be kept when compression is on, because of dead code removal or cascading statements into sequences. [string] --preamble Preamble to prepend to the output. You can use this to insert a comment, for example for licensing information. This will not be parsed, but the source map will adjust for its presence. --stats Display operations run time on STDERR. [boolean] --acorn Use Acorn for parsing. [boolean] --spidermonkey Assume input files are SpiderMonkey AST format (as JSON). [boolean] --self Build itself (UglifyJS2) as a library (implies --wrap=UglifyJS --export-all) [boolean] --wrap Embed everything in a big function, making the “exports” and “global” variables available. You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser. [string] --export-all Only used when --wrap, this tells UglifyJS to add code to automatically export all globals. [boolean] --lint Display some scope warnings [boolean] -v, --verbose Verbose [boolean] -V, --version Print version number and exit. [boolean] --noerr Don't throw an error for unknown options in -c, -b or -m. [boolean] 

对命令参数进行解释:

  • –source-map [string],生成source map文件。
  • –source-map-root [string], 指定生成source map的源文件位置。
  • –source-map-url [string], 指定source map的网站访问地址。
  • –source-map-include-sources,设置源文件被包含到source map中。
  • –in-source-map,自定义source map,用于其余工具生成的source map。
  • –screw-ie8, 用于生成彻底兼容IE6-8的代码。
  • –expr, 解析一个表达式或JSON。
  • -p, –prefix [string], 跳过原始文件名的前缀部分,用于指定源文件、source map和输出文件的相对路径。
  • -o, –output [string], 输出到文件。
  • -b, –beautify [string], 输出带格式化的文件。
  • -m, –mangle [string], 输出变量名替换后的文件。
  • -r, –reserved [string], 保留变量名,排除mangle过程。
  • -c, –compress [string], 输出压缩后的文件。
  • -d, –define [string], 全局定义。
  • -e, –enclose [string], 把全部代码合并到一个函数中,并提供一个可配置的参数列表。
  • –comments [string], 增长注释参数,如@license、@preserve。
  • –preamble [string], 增长注释描述。
  • –stats, 显示运行状态。
  • –acorn, 用Acorn作解析。
  • –spidermonkey, 解析SpiderMonkey格式的文件,如JSON。
  • –self, 把UglifyJS2作为依赖库一块儿打包。
  • –wrap, 把全部代码合并到一个函数中。
  • –export-all, 和–wrap一块儿使用,自动输出到全局环境。
  • –lint, 显示环境的异常信息。
  • -v, –verbose, 打印运行日志详细。
  • -V, –version, 打印版本号。
  • –noerr, 忽略错误命令行参数。

经过对命令行各类参数的解释,咱们基本上知道了这些参数都是干什么的了,下面我就试一下。

写2个简单地JS文件,demo.js, main.js。

~ vi D:\workspace\javascript\nodejs-uglifyJS2\demo.js

'use strict'; function hello(name){  if(name==='fens.me'){   return "Long time no see, "+name;  }  return "hello "+name; } console.log(hello('Conan')); console.log(hello('fens.me')); 

main.js

~ vi D:\workspace\javascript\nodejs-uglifyJS2\main.js

'use strict'; function book(){ return [ {head:'前言',page:'/views/tpl/book-r1/preface.html',active:false}, {head:'目录',page:'/views/tpl/book-r1/contents.html',active:true}, {head:'代码',page:'/views/tpl/book-r1/code.html',active:false}, {head:'试读',page:'/views/tpl/book-r1/sample.html',active:false}, {head:'勘误',page:'/views/tpl/book-r1/mistake.html',active:false} ]; } var tab=function(arr,idx){  for(var i=0;i<arr.length;i++){   arr[i].active = (idx==i?true:false);  }  return arr; } console.log(tab(book(),3)); 

接下来,用UglifyJS2命令进行操做,合并两个文件,对变量名用单字母替换,进行压缩,全部代码合并到一个函数,生成source map,指定source map来源网站。

D:\workspace\javascript\nodejs-uglifyJS2>uglifyjs main.js demo.js -o foo.min.js --source-map foo.min.js.map --source-map-root http://onbook.me -p 5 -c -m --wrap --export-all 

在当前目录生成了2个新文件:foo.min.js.map, foo.min.js,分别查看这两个文件。

foo.min.js

!function(e,t){"use strict";function o(){return[{head:"前言",page:"/views/tpl/book-r1/preface.html",active:!1},{head:"目录",page:"/views/tpl/book-r1/contents.html",active:!0},{head:"代码",page:"/views/tpl/book-r1/code.html",active:!1},{head:"试读",page:"/views/tpl/book-r1/sample.html",active:!1},{head:"勘误",page:"/views/tpl/book-r1/mistake.html",active:!1}]}function n(e){return"fens.me"===e?"Long time no see, "+e:"hello "+e}t["true"]=e,console.log(a(o(),3));var a=function(e,t){for(var o=0;o 

foo.min.js.map

{"version":3,"file":"foo.min.js","sources":["?"],"names":["exports","global","book","head","page","active","hello","name","console","log","tab","arr","idx","i","length","this"],"mappings":"CAAC,SAASA,EAASC,GAAnB,YAEA,SAASC,KACL,QACKC,KAAK,KAAKC,KAAK,kCAAkCC,QAAO,IACxDF,KAAK,KAAKC,KAAK,mCAAmCC,QAAO,IACzDF,KAAK,KAAKC,KAAK,+BAA+BC,QAAO,IACrDF,KAAK,KAAKC,KAAK,iCAAiCC,QAAO,IACvDF,KAAK,KAAKC,KAAK,kCAAkCC,QAAO,IANjE,QAASC,GAAMC,GACd,MAAU,YAAPA,EACK,qBAAqBA,EAEtB,SAASA,EANWN,EAAO,QAAUD,EAY7CQ,QAAQC,IAAIC,EAAIR,IAAO,GADvB,IAAIQ,GAAI,SAASC,EAAIC,GACpB,IAAI,GAAIC,GAAE,EAAEA,EAAEF,EAAIG,OAAOD,IACxBF,EAAIE,GAAGR,OAAUO,GAAKC,GAAE,GAAK,CAE9B,OAAOF,GAGRH,SAAQC,IAAIH,EAAM,UAClBE,QAAQC,IAAIH,EAAM,mBAjBTJ,UAAAI,QASLI,MAX8E,WAAW,MAAOK","sourceRoot":"http://onbook.me"} 

经过一条简单的命令,就实现了对JS代码的合并、压缩等的操做,确实很是方便。

下载jquery-2.1.1.js文件本身压缩,并与官方的压缩文件进行对比。

# 下载 ~ wget http://code.jquery.com/jquery-2.1.1.js ~ wget http://code.jquery.com/jquery-2.1.1.min.js # 压缩 ~ uglifyjs jquery-2.1.1.js -o jquery-2.1.1.min.uglifyjs2.js -p 5 -c -m # 比较3个文件大小 ~ ls -l -rwx------ 1 4294967295 mkpasswd 247351 Jul 6 16:26 jquery-2.1.1.js -rwx------ 1 4294967295 mkpasswd 84245 Jul 6 16:32 jquery-2.1.1.min.js -rwx------ 1 4294967295 mkpasswd 84113 Jul 6 16:28 jquery-2.1.1.min.uglifyjs2.js 

我在本地压缩的文件jquery-2.1.1.min.uglifyjs2.js,与jquery官司网下载的压缩文件jquery-2.1.1.min.js大小差很少,都在84KB左右。

5. UglifyJS2的API使用

另外一种使用方式是,把UglifyJS2包放到程序中,经过API对JS文件或JS代码进行压缩。首先,新建一个NPM项目文件package.json,而后在是下载UglifyJS2依赖包。

新建文件package.json

~ vi D:\workspace\javascript\nodejs-uglifyJS2\package.json { "name": "nodejs-uglifyjs2", "version": "0.0.1", "description": "uglifyjs2", "author": "Conan Zhang ", "dependencies": { } } 

下载UglifyJS2依赖包

D:\workspace\javascript\nodejs-uglifyJS2>npm install uglify-js --save npm WARN package.json nodejs-uglifyjs2@0.0.1 No readme data! npm http GET https://registry.npmjs.org/uglify-js npm http 304 https://registry.npmjs.org/uglify-js npm http GET https://registry.npmjs.org/async npm http GET https://registry.npmjs.org/source-map npm http GET https://registry.npmjs.org/optimist npm http GET https://registry.npmjs.org/uglify-to-browserify npm http 304 https://registry.npmjs.org/uglify-to-browserify npm http 304 https://registry.npmjs.org/optimist npm http 304 https://registry.npmjs.org/async npm http 304 https://registry.npmjs.org/source-map npm http GET https://registry.npmjs.org/wordwrap npm http GET https://registry.npmjs.org/amdefine npm http 304 https://registry.npmjs.org/wordwrap npm http 304 https://registry.npmjs.org/amdefine uglify-js@2.4.14 node_modules\uglify-js ├── uglify-to-browserify@1.0.2 ├── async@0.2.10 ├── optimist@0.3.7 (wordwrap@0.0.2) └── source-map@0.1.34 (amdefine@0.1.0) 

咱们新建一个文件uglify2.js,用于编写程序。

~ vi D:\workspace\javascript\nodejs-uglifyJS2\uglify2.js

'use strict'; var UglifyJS = require('uglify-js'); //代码压缩 var result = UglifyJS.minify("var b = function () {};", {fromString: true}); console.log("\n==========================="); console.log(result); //文件压缩 result = UglifyJS.minify(["demo.js"]); console.log("\n==========================="); console.log(result.code); //多文件压缩,指定source map和网站来源 result = UglifyJS.minify(["main.js","demo.js"],{ outSourceMap: "out.js.map", sourceRoot: "http://onbook.me", mangle:true }); console.log("\n==========================="); console.log(result.code); console.log(result.map); 

程序输出:

D:\workspace\javascript\nodejs-uglifyJS2>node uglify2.js

===========================
{ code: 'var b=function(){};', map: 'null' } =========================== "use strict";function hello(e){return"fens.me"===e?"Long time no see, "+e:"hello "+e}var tab=function(e,o){for(var n=0;n <e.length;n++)e[n].active=o==n?!0:!1;return e};console.log(hello("Conan")),console.log(hello("fens.me")); =========================== "use strict";function book(){return[{head:"前言",page:"/views/tpl/book-r1/preface.html",active:!1},{head:"目录",page:"/v iews/tpl/book-r1/contents.html",active:!0},{head:"代码",page:"/views/tpl/book-r1/code.html",active:!1},{head:"试读",page :"/views/tpl/book-r1/sample.html",active:!1},{head:"勘误",page:"/views/tpl/book-r1/mistake.html",active:!1}]}function he llo(e){return"fens.me"===e?"Long time no see, "+e:"hello "+e}console.log(tab(book(),3));var tab=function(e,o){for(var t= 0;t<e.length;t++)e[t].active=o==t?!0:!1;return e};console.log(hello("Conan")),console.log(hello("fens.me")); //# sourceMappingURL=out.js.map {"version":3,"file":"out.js.map","sources":["main.js","demo.js"],"names":["book","head","page","active","hello","name"," console","log","tab","arr","idx","i","length"],"mappings":"AAAA,YAEA,SAASA,QACL,QACKC,KAAK,KAAKC,KAAK,kCAAkCC,QAAO,IACxD F,KAAK,KAAKC,KAAK,mCAAmCC,QAAO,IACzDF,KAAK,KAAKC,KAAK,+BAA+BC,QAAO,IACrDF,KAAK,KAAKC,KAAK,iCAAiCC,QAAO,IACvDF,KAAK,KAAKC ,KAAK,kCAAkCC,QAAO,ICNjE,QAASC,OAAMC,GACd,MAAU,YAAPA,EACK,qBAAqBA,EAEtB,SAASA,EDMjBC,QAAQC,IAAIC,IAAIR,OAAO,GCDvB,IAAIQ, KAAI,SAASC,EAAIC,GACpB,IAAI,GAAIC,GAAE,EAAEA,EAAEF,EAAIG,OAAOD,IACxBF,EAAIE,GAAGR,OAAUO,GAAKC,GAAE,GAAK,CAE9B,OAAOF,GAGR H,SAAQC,IAAIH,MAAM,UAClBE,QAAQC,IAAIH,MAAM","sourceRoot":"http://onbook.me"} 

咱们看到用操做uglifyJS2包的API,仍是挺简单的,若是对AST树有遍历需求,API提供了很是实用的函数支持。

不过我在测试API过程当中,发现有2个问题。

  • 经过API设置mangle选项,但输出没有效果。
  • 没有--wrap和--export-all 命令行参数对应的API。

经过本文的介绍,咱们基本上了解了uglifyJS2包的功能和使用方法,而后就能够放心大胆地对JS代码进行压缩了。在实际的前端项目中,通常不用本身配置uglifyJS2包,而是经过grunt来调用uglifyJS2进行代码发布前的压缩,关于grunt使用,请参考文章: grunt让Nodejs规范起来 。

相关文章
相关标签/搜索