使用gulp和cordova hook发布ionic程序

发布ioinc程序主要通过gulp任务和cordova hook方式进行,前者是目前前端最流行的构建工具,后者在cordova(ionic框架底层的实现)构建过程中插入自定义的任务,从而通过对构建过程的干预达到最终发布的目的。通常来说,正式发布ionic程序需要做以下工作:

  • 对js代码进行语法检验(Lint)(cordova hook),保证js代码的正确性,才能在后面进行正确的混淆处理
  • 把html模板文件转换为angular模板(gulp任务),从而加快程序的运行速度
  • 开启agular的严格注入模式(gulp任务),相当于对angular进行lint检验,这一点也是为了保证后面正确的混淆处理
  • 合并css和js文件并替换html中的引用(gulp任务),将代码中的css和js文件进行合并
  • 压缩和混淆代码(cordova hook),因为ionic基于Cordova框架,因此这里使用cordova hook的方式进行,也可以使用gulp任务具体来写

下面分别进行详细的描述:
1. 对js代码进行语法检验(Lint)(cordova hook)
首先在项目根目录下执行下面的命令安装jshint

npm install jshint --save-dev
npm install async --save-dev

然后在工程目录下面创建hooks目录,这里里面是存放cordova hook的文件,然后创建before_prepare目录并将这里的文件放入其中,主要有一个02_jshint.js文件。

2. 把html模板文件转换为angular模板(gulp任务)
首先在项目根目录下执行下面的命令安装gulp-angular-templatecache

npm install gulp-angular-templatecache --save-dev

接下来打开gulpfile.js,增加下面的代码:

var templateCache = require('gulp-angular-templatecache');

// 在paths下面增加对tempate目录的设置
var paths = {
sass: ['./scss/**/*.scss'],
templatecache: ['./www/templates/**/*.html']
};

gulp.task('templatecache', function (done) {
gulp.src(paths.templatecache)
.pipe(templateCache({standalone:true, root: 'templates'}))
.pipe(gulp.dest('./www/js')) // 将处理好的js文件放在www/js下面,方便后面的合并
.on('end', done);
});

在app.js中增加对上面自动生成的templates模块的引用:

angular.module('app', ['ionic', 'controllers', 'templates'])

在index.html中引入对templates.js文件的引用


3. 开启agular的严格注入模式(gulp任务)
首先在项目根目录下执行下面的命令安装gulp-ng-annotate

npm install gulp-ng-annotate --save-dev

然后编写gulpfile.js文件,增加ng_annotate任务:

var ngAnnotate = require('gulp-ng-annotate');

// 在paths下面增加ng_annotate的目录
var paths = {
sass: ['./scss/**/*.scss'],
templatecache: ['./www/templates/**/*.html'],
ng_annotate: ['./www/js/*.js']
};

// angular注入验证
gulp.task('ng_annotate', function(done) {
gulp.src(paths.ng_annotate)
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest('./www/dist/dist_js/app'))
.on('end', done);
});

上面的ng_annotate任务会自动将js中的angular用的引用加上,比如原始代码为

angular.module('app.controllers', []).controller('LoginCtrl', function($scope) {});

经过上面的插件会自动处理成

angular.module('app.controllers', []).controller('LoginCtrl', '$scope', function($scope) {});

并将新的文件放在www/dist/dist_js/app目录下,因此接下来需要在index.html文件中修改对原来js的引用并在body标签中添加上ng-strict-di属性:


...


...

4. 合并css和js文件并替换html中的引用(gulp任务)
合并和替换css、js文件需要使用gulp-useref模块,在项目根目录下执行下面命令进行安装:

npm install gulp-useref --save-dev

然后编写gulpfile.js文件增加useref任务:

var useref = require('gulp-useref');

// 在paths下面增加ng_annotate的目录
var paths = {
sass: ['./scss/**/*.scss'],
templatecache: ['./www/templates/**/*.html'],
ng_annotate: ['./www/js/*.js'],
useref: ['./www/*.html']
};

// useref任务
gulp.task('useref', function (done) {
var assets = useref.assets();
gulp.src(paths.useref)
.pipe(assets)
.pipe(assets.restore())
.pipe(useref())
.pipe(gulp.dest('./www/dist'))
.on('end', done);
});

useref使用特殊的注释标签对标签内的css或js文件进行合并,因此修改index.html文件










对于不需要合并的资源文件可以不加build:xx注释。

5. 压缩和混淆代码(cordova hook)
最后使用cordova hook的方式压缩和混淆代码,需要用到cordova-uglify和mv模块,在项目根目录下执行下面的命令进行安装:

npm install cordova-uglify --save-dev
npm instal mv --save-dev
npm instal uglify-js --save-dev
npm instal clean-css --save-dev
npm instal ng-annotate --save-dev

然后将这个里面的js文件下载下来放到hooks/after_prepare目录下,在安装cordova-uglify的时候,会自动在hooks/after_prepare目录下创建一个uglify.js文件,因为上面的文件中已经有了060_uglify.js,因此将uglify.js文件删除即可。

经过上面的设置之后,就对整个的发布流程进行了修改和处理,最后还需要做一些后续的工作。首先将上面的gulp任务加入到default和watch任务中,修改gulpfile.js如下:

gulp.task('default', ['sass', 'templatecache', 'ng_annotate', 'useref']);

gulp.task('watch', function() {
gulp.watch(paths.sass, ['sass']);
gulp.watch(paths.templatecache, ['templatecache']);
gulp.watch(paths.ng_annotate, ['ng_annotate']);
gulp.watch(paths.ng_annotate, ['useref']);
});

然后还需要在ionic.project文件中加入gulpStartupTasks,让ionic项目启动的时候自动执行gulp任务:

{
"name": "hello",
"app_id": "",
"gulpStartupTasks": [
"sass",
"templatecache",
"ng_annotate",
"useref",
"watch"
]
}

另外,如果是在linux或mac系统下,还需要使用chmod +x 命令启用hooks目录下面的所有js文件的执行权限。

最后执行正确的ionic命令就会自动执行上述的过程并进行发布,比如ioinc build browser。如果发现Errors in file www/js/xxx.js的提示,则说明代码不太严格,出现了错误,根据提示对代码进行修改,直到执行成功为止。另外,在开发的时候执行ioinc serve browser命令的时候,也会自动监控文件的变化并执行gulp任务。

gulpfile.js文件内容如下:

var gulp = require('gulp');
var gutil = require('gulp-util');
var bower = require('bower');
var concat = require('gulp-concat');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
var sh = require('shelljs');
var templateCache = require('gulp-angular-templatecache');
var ngAnnotate = require('gulp-ng-annotate');
var useref = require('gulp-useref');

var paths = {
sass: ['./scss/**/*.scss'],
templatecache: ['./www/templates/**/*.html'],
ng_annotate: ['./www/js/*.js'],
useref: ['./www/*.html']
};

gulp.task('default', ['sass', 'templatecache', 'ng_annotate', 'useref']);

gulp.task('sass', function(done) {
gulp.src('./scss/ionic.app.scss')
.pipe(sass())
.on('error', sass.logError)
.pipe(gulp.dest('./www/css/'))
.pipe(minifyCss({
keepSpecialComments: 0
}))
.pipe(rename({ extname: '.min.css' }))
.pipe(gulp.dest('./www/css/'))
.on('end', done);
});

// 将模板进行合并
gulp.task('templatecache', function (done) {
gulp.src(paths.templatecache)
.pipe(templateCache({standalone:true, root: 'templates'}))
.pipe(gulp.dest('./www/js'))
.on('end', done);
});

// angular注入验证
gulp.task('ng_annotate', function(done) {
gulp.src(paths.ng_annotate)
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest('./www/dist/dist_js/app'))
.on('end', done);
});

// 压缩合并css/js文件
gulp.task('useref', function (done) {
gulp.src(paths.useref)
.pipe(useref())
.pipe(gulp.dest('./www/dist'))
.on('end', done);
});

gulp.task('watch', function() {
gulp.watch(paths.sass, ['sass']);
gulp.watch(paths.templatecache, ['templatecache']);
gulp.watch(paths.ng_annotate, ['ng_annotate']);
gulp.watch(paths.useref, ['useref']);
});

gulp.task('install', ['git-check'], function() {
return bower.commands.install()
.on('log', function(data) {
gutil.log('bower', gutil.colors.cyan(data.id), data.message);
});
});

gulp.task('git-check', function(done) {
if (!sh.which('git')) {
console.log(
' ' + gutil.colors.red('Git is not installed.'),
'\n Git, the version control system, is required to download Ionic.',
'\n Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
'\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
);
process.exit(1);
}
done();
});

参考资料:
Production ready apps with Ionic Framework
如何制作一个发布版的ionic应用?
Quick tip: using gulp to customize the 'serve', 'run' and 'build' process for your Ionic framework apps
gulp自动化任务脚本在HybridApp开发中的使用
Can't get Gulp to run: cannot find module 'gulp-util'
gulp-useref

发表评论

电子邮件地址不会被公开。 必填项已用*标注