日期:2014-05-16  浏览次数:20515 次

nodejs版seajs压缩部署工具

项目中seajs模块化的使用开发的时候来的确省事很多,但seajs的机制导致的请求过多不适合线上直接部署,玉伯那儿有一个spm部署的工具,但后来得知当前这个spm项目可用性还不是很高。所以准备自行搞一套发布的机制。

?

seajs有两种define的形式:

?

define(function(require, exports, module){});

?

?

define("friend-middleware.js",["lib/jquery.js","lib/underscore.js"],function(){});
?

下面一种是上面一种的简略写法。多了模块定义,和依赖模块数组两个参数,这两个参数是可选的,但其实机制是有些区别的,第一种在内部闭包内require模块的时候直接向指定路径的去getSrcipt,这一种方式得保证一个文件一个模块,而下面一种书写方式可以多个模块放在同一个文件中,在模块定义后,另一个模块同一个文件调用改模块只要在依赖列表中增加需要模块的定义就可以了。这样就可以使用这个特性对模块进行依赖压缩了,另外要压缩的话要对css进行查找并另外压缩一个css文件。

?

为了方便发布,用了nodejs进行编写,趁机学习下node;js压缩用了node版本的uglifyJs,这个压缩工具跟google压缩有的一拼,jQuery的压缩也是用了它。css的压缩还是用了yc的css压缩工具node版。

?

?

(function(){
	var fs = require('fs'),
		jsp = require('./lib/uglify-js').parser,
		pro = require('./lib/uglify-js').uglify,
		cssmin = require('./lib/node-css-compressor').cssmin,
		_ = require('./lib/underscore.js');
		
	var	compressCode = '',
		compressCss = '',
		dependCssList = [],
		jsPath = 'D:/Workspace/BB/deploy/htdocs/js/' //模块下css依赖绝对path补齐
		
		pubilcJsFile = [
			//公共文件列表
		],
		jsFileArray = [
			//待压缩文件列表
		];
	
		
	
	var log = function(arg){
		console.log(arg);
	};
	
	var replaceForDepend = function(filename, code){
		var dependenceArray = [];
		var modulename = filename.replace(/^.*\/js\//i,'');
		code.replace(/require\('(.+)'\)/ig, function(){
			var match = arguments[1];
			if(/\.css$/i.test(match)){
				dependCssList.push(jsPath + match);
				return;
			}
			if(!(/\.js$/i.test(match))){
				match += '.js';
			}
			dependenceArray.push('"' + match + '"');
		});
		code = code.replace(/define\(function\(/, 'define(\'' + modulename + '\', [' + dependenceArray.join(',') + '], function(');
		code = code.replace("/require\('(.+\.css)'\)/i", '', code);
		return code;
	};
	
	var compress = function(str ,type){
		if (type === 'javascript') {
			var orig_code = str;
			var ast = jsp.parse(orig_code);
			ast = pro.ast_lift_variables(ast);
			ast = pro.ast_mangle(ast);
			ast = pro.ast_squeeze(ast);
			var finalCode = pro.gen_code(ast);
			return finalCode;
		}else if(type === 'css'){
			return cssmin(str);
		}else{
			return str;
		}
	};
	

	var writeFinalCode = function(file, str){
		fs.writeFile(file, str, 'utf8', function (err) {
		  if (err) throw err;
		  console.log('It\'s saved to ' + file + '!');
		});
	};

	var _init = function(argv0,argv1){
		var minJsFile = argv0 || 'babylon.js';
		var minCssFile = argv1 || 'babylon.css';
		var i, pdata, data, rdata;
		
		log('Javascript analyze start!');
		for(i = 0; i < pubilcJsFile.length ; ++i){
			pdata = fs.readFileSync(pubilcJsFile[i], 'utf8');
			compressCode += pdata;
			log(pubilcJsFile[i] + ' complete!');
		}
		for(i = 0; i < jsFileArray.length; ++i){
			data = fs.readFileSync(jsFileArray[i], 'utf8');
			rdata = replaceForDepend(jsFileArray[i], data);
			compressCode += rdata;
			log(jsFileArray[i]  + ' complete!')
		}
		
		log('Javascript compress start!');
		compressCode = compress(compressCode, 'javascript');

		log('CSS analyze start!');
		dependCssList = _.uniq(dependCssList)
		for (i = 0; i < dependCssList.length; ++i) {
			cdata = fs.readFileSync(dependCssList[i], 'utf8');
			compressCss += cdata;
			log(dependCssList[i] + ' complete!');
		}
		log('Css compress start!');
		compressCss = compress(compressCss, 'css');
		
		writeFinalCode(minJsFile, compressCode);
		
		writeFinalCode(minCssFile, compressCss);
	}

	return _init;
})()(process.argv[2],process.argv[3]);

?

核心就是code = code.replace(/define\(function\(/, 'define(\'' + modulename + '\', [' + dependenceArray.join(',') + '], function(');语句一