原文链接:http://blog.csdn.net/lovelyelfpop/article/details/56014300
Cordova App 添加的各种plugin插件,每个plugin都有自己的js文件。
App入口index.html中只引入了一个www目录下的cordova.js文件,此文件会在同一级目录下寻找cordova_plugins.js,然后根据这个文件中描述的各个plugin的路径,找到它们的js,并加载。
www目录结构如下:
注意:
如果我们用了很多的plugin,那么最后app需要加载的js文件就会变得非常多,加载变慢就拖慢了app的启动速度。如下图:
那么,如何才能把这些js文件整合成为一个js文件呢?其实,cordova-cli命令行提供了参数--browserify,具体可以查看官方文档:
https://cordova.apache.org/docs/en/latest/reference/cordova-cli/#cordova-prepare-command
cordova prepare、cordova build、cordova run命令都可以使用--browserify参数,以build为例:
cordova build android --browserify
这就是因为cordova.js、cordova_plugins.js以及cordova-js-src目录和plugins目录下的js,都打包到了一起。
最后App加载的结果是这样:
是不是少多了?
当然,上面的--browserify参数只是把插件js打包进了cordova.js,但是并没有把cordova_plugins.js、cordova-js-src目录和plugins目录下的js删除掉。
如果你想把这些无用的js删掉的话,变成下面的结构:
此时,cordova hooks就派上用场了。
hooks,中文意思是钩子。
cordova在build过程中分为各个阶段,如下表格:
Hook 类型 | 相关命令 | 描述 |
---|---|---|
before_platform_add | cordova platform add |
To be executed before and after adding a platform. |
after_platform_add | ||
before_prepare | cordova prepare cordova platform add cordova build cordova run |
To be executed before and after preparing your application. |
after_prepare | ||
before_compile | cordova compile cordova build |
To be executed before and after compiling your application. |
after_compile | ||
before_deploy | cordova emulate cordova run |
To be executed before deploying your application. |
before_build | cordova build |
To be executed before and after building your application. |
after_build |
每个hook就相当于一个事件,我们可以监听它,然后执行我们的自定义操作。
我们要做的就是在after_prepare阶段,把www目录下的无用文件删除掉,并且压缩cordova.js。
我就直接提供代码了。
1、建立目录cordova/scripts/after_prepare,把下面的代码保存为minify.js,放到after_prepare目录下
#!/usr/bin/env node
module.exports = function(ctx) {
var fs = ctx.requireCordovaModule('fs'),
path = ctx.requireCordovaModule('path'),
shell = ctx.requireCordovaModule("shelljs"),
UglifyJS = require('uglify-js'),
CleanCSS = require('clean-css'),
htmlMinify = require('html-minifier').minify,
cssOptions = {
keepSpecialComments: 0
},
cssMinifier = new CleanCSS(cssOptions),
rootDir = ctx.opts.projectRoot,
platformPath = path.join(rootDir, 'platforms'),
platforms = ctx.opts.cordova.platforms,
platform = platforms.length ? platforms[0] : '',
cliCommand = ctx.cmdLine,
debug = true, //false
htmlOptions = {
removeAttributeQuotes: true,
removeComments: true,
minifyJS: true,
minifyCSS: cssOptions,
collapseWhitespace: true,
conservativeCollapse: true,
removeComments: true,
removeEmptyAttributes: true
},
successCounter = 0,
errorCounter = 0,
notProcessedCounter = 0,
pendingCounter = 0,
hasStartedProcessing = false,
processRoot = false,
isBrowserify = (cliCommand.indexOf('--browserify') > -1), //added
//isRelease = true;
isRelease = (cliCommand.indexOf('--release') > -1); // comment the above line and uncomment this line to turn the hook on only for release
function processFiles(dir, _noRecursive) {
fs.readdir(dir, function (err, list) {
if (err) {
// console.error('processFiles - reading directories error: ' + err);
return;
}
list.forEach(function(file) {
file = path.join(dir, file);
fs.stat(file, function(err, stat) {
hasStartedProcessing = true;
if (stat.isDirectory()) {
if (!_noRecursive) processFiles(file);
} else {
compress(file);
}
});
});
});
}
function processFile(file) {
fs.stat(file, function(err, stat) {
hasStartedProcessing = true;
compress(file);
});
}
function compress(file) {
var ext = path.extname(file);
switch(ext.toLowerCase()) {
case '.js':
(debug) && console.log('Compressing/Uglifying JS File: ' + file);
var result = UglifyJS.minify(file, {
compress: {
dead_code: true,
loops: true,
if_return: true,
keep_fargs: true,
keep_fnames: true
}
});
if (!result || !result.code || result.code.length == 0) {
errorCounter++;
console.error('\x1b[31mEncountered an error minifying a file: %s\x1b[0m', file);
}
else {
successCounter++;
fs.writeFileSync(file, result.code, 'utf8');
(debug) && console.log('Optimized: ' + file);
}
break;
case '.css':
(debug) && console.log('Minifying CSS File: ' + file);
var source = fs.readFileSync(file, 'utf8');
if (!source || source.length == 0) {
errorCounter++;
console.error('Encountered an empty file: ' + file);
}
else {
var result = cssMinifier.minify(source).styles;
if (!result || result.length == 0) {
errorCounter++;
console.error('\x1b[31mEncountered an error minifying a file: %s\x1b[0m', file);
}
else {
successCounter++;
fs.writeFileSync(file, result, 'utf8');
(debug) && console.log('Optimized: ' + file);
}
}
break;
case '.html':
(debug) && console.log('Minifying HTML File: ' + file);
var source = fs.readFileSync(file, 'utf8');
if (!source || source.length == 0) {
errorCounter++;
console.error('Encountered an empty file: ' + file);
}
else {
var result = htmlMinify(source, htmlOptions);
if (!result || result.length == 0) {
errorCounter++;
console.error('\x1b[31mEncountered an error minifying a file: %s\x1b[0m', file);
}
else {
successCounter++;
fs.writeFileSync(file, result, 'utf8');
(debug) && console.log('Optimized: ' + file);
}
}
break;
default:
console.error('Encountered file with ' + ext + ' extension - not compressing.');
notProcessedCounter++;
break;
}
}
function checkIfFinished() {
if (hasStartedProcessing && pendingCounter == 0) console.log('\x1b[36m%s %s %s\x1b[0m', successCounter + (successCounter == 1 ? ' file ' : ' files ') + 'minified.', errorCounter + (errorCounter == 1 ? ' file ' : ' files ') + 'had errors.', notProcessedCounter + (notProcessedCounter == 1 ? ' file was ' : ' files were ') + 'not processed.');
else setTimeout(checkIfFinished, 10);
}
switch (platform) {
case 'android':
platformPath = path.join(platformPath, platform, "assets", "www");
break;
case 'ios':
platformPath = path.join(platformPath, platform, "www");
break;
default:
console.error('Hook currently supports only Android and iOS');
return;
}
if(isBrowserify) {
shell.rm('-rf', path.join(platformPath, 'cordova-js-src'));
shell.rm('-rf', path.join(platformPath, 'plugins'));
shell.rm('-f', path.join(platformPath, 'cordova_plugins.js'));
}
if (!isRelease) {
return;
}
console.log('cordova-minify STARTING - minifying your js, css, html. Sit back and relax!');
//minify files inside these directories
//var foldersToProcess = ['javascript', 'style', 'js', 'css', 'html'];
var foldersToProcess = isBrowserify ? [] : ['cordova-js-src', 'plugins'];
if (processRoot) processFiles(platformPath, true);
foldersToProcess.forEach(function(folder) {
processFiles(path.join(platformPath, folder));
});
//minify files one by one
var filesToProcess = ['cordova.js'];
if(!isBrowserify) filesToProcess.push('cordova_plugins.js');
filesToProcess.forEach(function(file) {
processFile(path.join(platformPath, file));
});
checkIfFinished();
};
上述代码来自:https://github.com/adamerny/cordova-minify-v2
2、打开cordova/plugins.xml文件,在其中加一句
如下图:
3、打开命令行界面,全局安装下面的npm包
npm install -g clean-css html-minifier uglify-js
minify.js 会用到上面的包好了,现在执行Cordova的打包命令
Debug 打包:运行cordova build android --browserify,完成后就没有多余的插件js文件了;
Release打包:运行cordova build android --release --browserify,不仅删除了多余的插件js文件,还把cordova.js压缩了。
ps: 如果你想要在Debug打包时,也压缩cordova.js文件,那就把上面hook脚本中的isRelease设为true。
上面是针对cordova项目来说的,如果你是Sencha项目(Touch或ExtJS6 Modern),需要修改文件:
Sencha项目\.sencha\app\cordova-impl.xml
在每个命令后面加上--browserify
这样,以后Sencha app build xxx就可以整合压缩cordova.js了。
实际测试,app的加载速度提升不到1秒。
应该设备越低端,提升越明显吧。(忽略ios,ios本来就快)