打包並壓縮seajs代碼

背景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/站點提供的功能.

相關文章
相關標籤/搜索