sumeru
Version:
A Realtime Javascript RIA Framework For Mobile WebApp
308 lines (237 loc) • 10.3 kB
JavaScript
var path = require('path');
var fs = require('fs');
var _debug = false;
var baseDir = path.join(__dirname, '../../');
var sumeruDir = path.join(__dirname, '/../');
var dstDir = '';//加注释
var buildConfig = require(path.join(__dirname, 'buildList.json'));
var sumeru = require(__dirname + '/../src/newPkg.js')();
require(__dirname + '/../src/log.js')(sumeru);
/**BAE环境模拟测试用**/
//process.BAE = 'bae';
var appDir;
if (typeof process.BAE !== 'undefined'){
sumeru.dev('BAE MODE');
appDir = path.join(__dirname, '/../../app');
dstDir = path.join(baseDir, '/__bae__');
var serverDir = path.join(dstDir, '/server');
var binDir = path.join(dstDir, '/bin');
var tmpDir = path.join(serverDir, '/tmp');
var staticDir = path.join(dstDir,'/static');
!fs.existsSync(dstDir) && fs.mkdirSync(dstDir);
!fs.existsSync(serverDir) && fs.mkdirSync(serverDir);
!fs.existsSync(tmpDir) && fs.mkdirSync(tmpDir);
!fs.existsSync(binDir) && fs.mkdirSync(binDir);
!fs.existsSync(staticDir) && fs.mkdirSync(staticDir);
}else{
sumeru.dev('NON BAE MODE');
appDir = path.join(__dirname, '/../../app' + (process.argv[2] ? '/' +process.argv[2] : ''));
dstDir = appDir;//path.join(__dirname, '/../../app' + (process.argv[2] ? '/' +process.argv[2] : ''));
}
process.appDir = appDir;
process.baseDir = baseDir;
process.dstDir = dstDir;
sumeru.dev('build from :' + baseDir);
sumeru.dev('to :' + dstDir);
if (baseDir.charAt(baseDir.length-1) == '/'){
//去掉尾部的'/'
baseDir = baseDir.slice(0,baseDir.length - 1);
}
var buildDir = __dirname + '/';
var buildView = require(path.join(buildDir, 'buildServer.js'));
var buildSmrTargetDir = typeof process.BAE !== 'undefined' ? dstDir : sumeruDir;
require(path.join(buildDir, 'buildJavascript.js'))(sumeruDir, buildSmrTargetDir);
//---------------------------build Apps resourc--------------------------------
var shell = require('shelljs');
//build app resource
var manifestFileName = 'cache.manifest';
var buildAppResource = function(appDir, theBinDir){
var buildAppContent = '';
var buildAppCssContent = '';
var readPackage = function(path) {
var url = path + '/package.js';
var entireContent = fs.readFileSync(url, 'utf-8');
var contentReg = /packages\s*\(\s*(.*)\s*\)/mg;
var commentReg = /\/\/.*(\n|\r)|(\/\*(.*?)\*\/)/mg;
var dirnameList = [];
//去掉在package.js里的注释
entireContent = entireContent.replace(commentReg, '');
//去掉换行符、换页符、回车符等
entireContent = entireContent.replace(/\n|\r|\t|\v|\f/g, '');
//取出参数, 存于dirnameList
var result = contentReg.exec(entireContent);
if (result === null) {
return;
}
entireContent = result[1];
entireContent = entireContent.replace(/'|"/mg, '');
dirnameList = entireContent.split(',');
dirnameList.forEach(function(dirname) {
dirname = dirname.trim();
if (!dirname) {
return;
}
var reg = /.js$/g,
cssReg = /.css$/g;
var fileUrl = path + '/' + dirname;
if (reg.test(dirname)) {
buildAppContent += ';'+fs.readFileSync(fileUrl, 'utf-8');
} else if (cssReg.test(dirname)) {
buildAppCssContent += fs.readFileSync(fileUrl, 'utf-8');
} else {
readPackage(fileUrl);
}
});
}
readPackage(appDir);
var UglifyJS = require('uglify-js');
//压缩js代码
var orig_code = buildAppContent;
var ast = UglifyJS.parse(orig_code); // parse code and get the initial AST
/*
* Compressor options
*
* sequences : true, // join consecutive statemets with the “comma operator”
* properties : true, // optimize property access: a["foo"] → a.foo
* dead_code : true, // discard unreachable code
* drop_debugger : true, // discard “debugger” statements
* unsafe : false, // some unsafe optimizations (see below)
* conditionals : true, // optimize if-s and conditional expressions
* comparisons : true, // optimize comparisons
* evaluate : true, // evaluate constant expressions
* booleans : true, // optimize boolean expressions
* loops : true, // optimize loops
* unused : true, // drop unused variables/functions
* hoist_funs : true, // hoist function declarations
* hoist_vars : false, // hoist variable declarations
* if_return : true, // optimize if-s followed by return/continue
* join_vars : true, // join var declarations
* cascade : true, // try to cascade `right` into `left` in sequences
* side_effects : true, // drop side-effect-free statements
* warnings : true, // warn about potentially dangerous optimizations/code
* global_defs : {} // global definitions
*
* */
var compressor = UglifyJS.Compressor({
unused : false,
warnings: false
});
ast.figure_out_scope();
var compressed_ast = ast.transform(compressor);
compressed_ast.figure_out_scope();
compressed_ast.compute_char_frequency();
compressed_ast.mangle_names(); // get a new AST with mangled names
var packedAppContent = compressed_ast.print_to_string(); // compressed code here
//clean css
var cleanCSS = require('clean-css');
var packedAppCssContent = new cleanCSS().minify(buildAppCssContent);
if(typeof process.BAE !== 'undefined'){
fs.writeFileSync(binDir + '/app.js', packedAppContent, 'utf-8');
fs.writeFileSync(binDir + '/app.css', packedAppCssContent, 'utf-8');
buildView(appDir, binDir);
buildManifest(appDir, path.join(dstDir, 'bin'));
}else{
fs.writeFileSync(theBinDir + '/app.js', _debug?buildAppContent:packedAppContent, 'utf-8');
fs.writeFileSync(theBinDir + '/app.css', _debug?buildAppCssContent:packedAppCssContent, 'utf-8');
buildView(appDir, theBinDir);
buildManifest(appDir, theBinDir);
}
};
var buildManifest = function(appDir, theBinDir){
var first_line_str = 'CACHE MANIFEST \n#version:'+Date.now() + '\n';
var cache_title = 'CACHE:\n';
//扫描view目录并列入缓存清单
var baseViewDir = path.join(appDir, 'view');
var allFiles = [];
var cacheViewStr = '';
var readAllFileInView = function(bsvdir, httpBase){
if(fs.existsSync(bsvdir)){
var theDirFiles = fs.readdirSync(bsvdir);
if(theDirFiles && theDirFiles.length > 0){
for(var i=0; i < theDirFiles.length; i++){
if (theDirFiles[i] == '.svn' || theDirFiles[i] == '.git') {
continue;
};
if(fs.statSync(path.join(bsvdir, theDirFiles[i])).isFile()){
allFiles.push(httpBase + '/' + theDirFiles[i]);
}else{
readAllFileInView(bsvdir + '/' + theDirFiles[i], httpBase + '/' + theDirFiles[i]);
}
}
}
}
};
readAllFileInView(baseViewDir, '/view');
var cdir = buildConfig.cacheDirectory;
if(cdir){
var baseAppDir = path.join(baseDir, 'app');
cdir.forEach(function(dir){
var pt = path.join(baseAppDir, dir);
if(fs.existsSync(pt)){
readAllFileInView(pt, dir);
}
});
}
allFiles.forEach(function(cfile){
cacheViewStr += cfile + '\n';
});
var appManifest = path.join(appDir, 'app.manifest');
var appCache = appNetWork = appFallback = '';
if(fs.existsSync(appManifest)){
var customContent = fs.readFileSync(appManifest, 'utf-8');
if(customContent){
var cacheIndex = customContent.indexOf('CACHE:');
var networkIndex = customContent.indexOf('NETWORK:');
var fallbackIndex = customContent.indexOf('FALLBACK:');
if(cacheIndex != -1){
appCache = customContent.slice(cacheIndex + 6,
networkIndex == -1 ? (fallbackIndex == -1 ? customContent.length : fallbackIndex ) : networkIndex);
}
if(networkIndex != -1){
appNetWork = customContent.slice(networkIndex + 8,
fallbackIndex == -1 ? customContent.length : fallbackIndex);
}
if(fallbackIndex != -1){
appFallback = customContent.slice(fallbackIndex + 9,customContent.length);
}
}
}
var cache_res_list = 'sumeru.css\n';
cache_res_list += 'sumeru.js\napp.js\n';
cache_res_list += cacheViewStr;
cache_res_list += appCache;
var network_title = 'NETWORK:\n';
var network_res_list = '*'
var offline_manifest = theBinDir + '/cache.manifest';
var cache_content_str = first_line_str + cache_title + cache_res_list + network_title + network_res_list;
if(fs.existsSync(offline_manifest)){
fs.unlinkSync(offline_manifest);
}
fs.writeFileSync(offline_manifest, cache_content_str, 'utf-8');
};
var copySumeruFile2AppBin = function(){
var appDir = path.join(baseDir, 'app');
var apps = fs.readdirSync(appDir);
if(typeof process.BAE == 'undefined'){
apps = [''].concat(apps);
}else{
apps = [''];
}
apps.forEach(function(dir){
if(dir && dir.indexOf('.') > -1) return;
var dir = path.join(appDir, dir);
var theBinDir = path.join(dir, 'bin');
if(fs.existsSync(path.join(dir, 'package.js')) &&
fs.existsSync(path.join(dir, 'view'))){
if(typeof process.BAE === 'undefined'){
if(!fs.existsSync(theBinDir)){
fs.mkdirSync(theBinDir);
}
shell.cp('-rf', path.join(sumeruDir, 'bin/sumeru.js'), theBinDir);
shell.cp('-rf', path.join(sumeruDir, 'bin/sumeru.css'), theBinDir);
}
buildAppResource(dir, theBinDir);
}
});
};
copySumeruFile2AppBin();