年底將至,不少閒適的時間,因而刷刷微博,接觸各類紛雜的信息——美其名曰「學習」。運氣不錯,遇到了一個新名詞,uglifyjs. 聽說是用來壓縮JS文件的,聽說還能優化JS,聽說是基於node的,還聽說比Google Closure Compiler更帶感,哦?激起了個人好奇心。百之谷之,喲,相關的介紹還很多。而後折騰了個把小時,基本上知道了是個怎麼回事。javascript
我以爲吧,仍是有些用的,即便是否是從事node開發的人,抽個小空,share之,因而就有了本文。人總有浮躁的時候,我也不例外,uglifyjs內部深刻的運做是如何的,唉,我是有氣無力,不想去折騰,因此,本文更可能是停留在應用層面。不過嘛,這樣反而受衆面廣一些。畢竟喜歡看《泰囧》的人要比《一代宗師》的多。php
凡事說起node應用,無非免不了相似下面的流程:html
前兩個網上太多示意了,我以前也講過,sorry, 我很懶。
uglifyjs安裝以下code:前端
npm install uglify-js -g
一個回車,因而啪啪啪,就有下圖所示的東東:
java
因而,下面就能夠壓縮JS了。node
uglifyjs壓縮有不少的參數,詳見其github託管項目。其中有一些可選參數,以下部分截圖:
jquery
什麼美化壓縮,空格多長,變量名是否變成短名字等……您有興趣能夠本身去看看,若是今天不是星期五,若是不是要趕回去買菜,我就會翻譯下的——諸位,請原諒我吧,阿門!git
下面演示如何使用uglifyjs壓縮JS.github
個人桌面上有個名叫formini的文件夾,我會把要壓縮的文件放在其中,而後再壓縮。如今,我從內部拷貝了一個名叫inet.js的JS文件到這個文件夾中,而後:sql
uglifyjs inet.js -o inet-min.js
-m
可選參數:
uglifyjs inet.js -m -o inet.min.js
以下截圖:
噢啦,如今就是看結果了,見下截圖:
90K的是沒有運行-m
參數的,70K(69.4)的是運行的。-m
參數因此就是把變量名變成a, b, c, d, ...
從實際應用角度講,上線的JS顯然要壓縮變量,減少必定的文件尺寸。
跟YUICompressor相比,大小隻小了0.6K, 不過網上反映uglifyjs相比YUI壓縮很明顯,我這裏的大小僅優化了0.6÷174=0.345%
,這隻能說明我寫的代碼還算比較優化,哈哈(忽然想起了老婆的話,不要得瑟,深呼吸……深呼吸……)!
咱們不可能每次都打開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文件啦!
對於本身來說,本文內容算做備忘。目前而言,我仍是uglifyjs不能壓縮CSS文件。不過嘛,瞭解下總會有幫助的。行文匆忙,文中要是有表述不許確的地方歡迎指正。
另一篇文章介紹
作Web前端開發,老是要考慮頁面的打開速度,若是文件數量越少、文件長度越小,就能夠直接的提高網頁的訪問速度。
但在開發的時候,爲了保證代碼的可讀性,咱們寫的程序文件會不少並且很大,這樣就與部署的要求發生背離,經過UglifyJS2這個工具,咱們能夠在開發完成時,對代碼文件進行 合併、混淆、壓縮 等的操做,達到最優的訪問性能。
開始UglifyJS2介紹以前,咱們先要說一下UglifyJS。 UglifyJS 是UglifyJS2的前身,是一個Javascript開發的通用的語法分析、代碼壓縮、代碼優化的一個工具包。UglifyJS是基於Nodejs環境開發,支持CommonJS模塊系統的任意的Javascript平臺。
UglifyJS的實現主要分爲2部分:
UglifyJS2 是做者對UglifyJS的重寫,是徹底的重寫,而不只僅是升級。從UglifyJS2官司方網頁介紹看,UglifyJS2把整個的JS壓縮過程,作了更進一步的細化。
上述全部的功能代碼API是 在6500行的左右,比其餘的相同功能的開發包都要小。做者還提供了一個在線版本UglifyJS2的JS壓縮工具, http://lisperator.net/uglifyjs/,你們能夠測試一下。
系統環境:
UglifyJS2的安裝很是簡單,和Nodejs的其餘包同樣,全局安裝使用以下命令。
npm install uglify-js -g
也能夠經過github下載源代碼安裝。
git clone git://github.com/mishoo/UglifyJS2.git cd UglifyJS2
咱們在使用UglifyJS2的時候主要有2種方式,一種是經過命令行操做,對指定的JS文件進行壓縮;另外一種是經過程序的API調用,對文件或內存中的JS代碼進行壓縮。下面我將分兩種狀況進行介紹。
在全局安裝好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]
對命令參數進行解釋:
經過對命令行各類參數的解釋,咱們基本上知道了這些參數都是幹什麼的了,下面我就試一下。
寫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左右。
另外一種使用方式是,把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個問題。
經過本文的介紹,咱們基本上了解了uglifyJS2包的功能和使用方法,而後就能夠放心大膽地對JS代碼進行壓縮了。在實際的前端項目中,通常不用本身配置uglifyJS2包,而是經過grunt來調用uglifyJS2進行代碼發佈前的壓縮,關於grunt使用,請參考文章: grunt讓Nodejs規範起來 。