背景css
seajs是一款優秀的模塊開發插件,可是當咱們使用它來進行模塊化開發的時候,因爲它的每一個模塊的加載都會進行一次http請求,那麼當模塊數量倍增的時候,會拖慢頁面的加載速度。
java
一般咱們爲了能加快頁面的加載速度,都會對js進行壓縮並把關聯的模塊打包爲一個獨立的js文件,這樣能夠大大減小js的文件大小而且減小http請求的次數,這樣能夠提高到頁面的加載速度。node
咱們能夠是用spm來對js文件進行打包、壓縮(使用spm-build),可是當咱們編寫兼容多種環境的js的時候(既能夠直接用script引用又可使用seajs來引用),那麼咱們就沒辦法使用前面的方法來對js進行打包和壓縮了。git
其次就是使用spm-build還要先了解package.json文件配置,仍是有少量麻煩的,爲了減輕上手的難度和簡化功能,這裏咱們將介紹另類的使用nodejs來對js腳本進行壓縮。github
實現ajax
http://tool.css-js.com/站點提供了多種腳本壓縮,經過使用YUI壓縮,咱們發現它其實是使用http的POST來實現代碼壓縮的,如圖:json
接着咱們使用ajax來進行測試,代碼以下:閉包
$.post('http://tool.css-js.com/!java/?type=js&munge=true&preserveAllSemiColons=false&disableOptimizations=false', { code: 'var x = (function() { var foo = 1, bar = 2; return (foo + bar) }())' }, function(res){ console.log(res); });
結果跟截圖的效果是相同的,接下來使用nodejs來編寫一個用於讀取js文件併發起http而後把壓縮的拼接到一個獨立的js文件中去。併發
使用原生的nodejs的http來發起post的代碼以下:app
var m_http = require('http'); var m_qs = require('querystring'); var options = { host: 'tool.css-js.com', port: 80, method: 'POST', path: '/!java/?type=js&munge=true&preserveAllSemiColons=false&disableOptimizations=false', headers: { 'Content-Type':'application/x-www-form-urlencoded' } }; exports.compress = function (str, callback){ var req = m_http.request(options, function(res) { res.setEncoding('utf-8'); var compressed = ''; res.on('data', function(chunk){ compressed += chunk; }); res.on('end', function(){ callback(compressed) }); }); req.write(m_qs.stringify({ code: str })); req.end(); };
有了壓縮的方法,接下來咱們須要提供一個能夠循環讀取文件夾內的全部js文件並壓縮合併到獨立的js文件的函數,代碼大體以下:
var m_fs = require('fs'); var m_path = require('path'); //其餘代碼略 exports.combineDir = function (dir, output){ var self = this; m_fs.readdirSync(dir).forEach(function (filename) { if (filename.indexOf('.') === -1) { self.compressDir(m_path.join(dir, filename)); return; } var path = m_path.join(dir, filename); m_fs.readFile(path, 'utf8', function (err, content){ if (err) { return; } self.compress(content, function (compressed){ var id = filename.substr(0, filename.indexOf('.')); compressed = compressed.replace('this.define(', ['this.define(\'', id, '\','].join('')); m_fs.appendFileSync(output, compressed); }); }); }); };
以上代碼之因此要替換'this.define'字符串是由於咱們編寫的兼容腳本中,會使用閉包將腳本包含在內部,並在內部對this.define進行判斷,當this.define存在的狀況下,纔會將編碼的模塊賦值給module.exports來完成模塊,示例代碼以下:
//a.js (function(){ var a = (function() { var foo = 1, bar = 2; return (foo + bar) }()) if (this.define) { this.define(function (require, exports, module) { 'require:nomunge,exports:nomunge,module:nomunge'; module.exports = a; }); } }).call(this); //b.js (function(){ var b = (function() { var foo = 1, bar = 2; return (foo + bar) }()) if (this.define) { this.define(function (require, exports, module) { 'require:nomunge,exports:nomunge,module:nomunge'; module.exports = a; }); } }).call(this);
使用編碼好的函數來進行合併後,結果以下:
(function(){var b=(function(){var c=1,a=2;return(c+a)}());if(this.define){this.define('a',function(require,exports,module){module.exports=b})}}).call(this); (function(){var c=(function(){var d=1,b=2;return(d+b)}());if(this.define){this.define('b',function(require,exports,module){module.exports=a})}}).call(this);
擴展
對於建立請求,咱們可使用nodegrass來完成咱們的功能,它內部封裝了http和https的get、post的函數,簡化了調用,你們可使用看看。
其次對於循環文件夾內的js文件,當存在多層嵌套的時候,因爲沒有將父級文件夾添加到seajs定義的id內,所以調用合併後的js文件的時候,會出現錯誤,這裏就不詳細解說如何解決了,這個問題就留給你們去解決啦。
對於以上代碼因爲使用了異步方法,形成了多層文件嵌套,若是你們以爲嵌套太多致使代碼難看、難以閱讀,可使用wind.js或者eventproxy.js或者其餘的異步js來解決多層嵌套的問題。
結尾
此次的文章就到這裏了,內容中有任何問題不吝賜教,謝謝各位!
另外感謝http://tool.css-js.com/站點提供的功能.