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