1

使用Browserify打包js时如果项目变得越来越大,编译时间就会相应变得越来越长。使用官方的插件watchify是个比较有效的提高速度方案。

提速原理

watchify的用法和gulp的watch方法比较类似,都是监控文件的改动来触发一些操作。在gulp中我们可以把一个完整的任务拆分成很多个局部任务,然后使用gulp.watch对这些局部任务进行监听,例如:

gulp.task('build-js1', ...);
gulp.task('build-js2', ...);
gulp.task('build-all-js', ['build-js1', 'build-js2']);

gulp.task('watch-js1', function () {
  gulp.watch('./src/models/**/*.js', ['build-js1']);
});

gulp.task('watch-js2', function () {
  gulp.watch('./src/views/**/*.js', ['build-js2']);
});

//gulp.task('watch-js', function () {
//  gulp.watch('./src/**/*.js', ['build-all-js']);
//});

如上例所示,在监测不同局部位置的js文件发生改动后,则只会自动执行相应的build-js1或build-js2等局部任务;而如果直接监测所有的js文件,就必须每次执行build-all-js任务了。

watchify的提速原理和这个思路有点类似,它可以监测个别文件的改动,从而触发只将需要更新的文件打包。它须要先执行一次完整的打包,首次打包的速度和正常速度是一样的;然后每次用户改变某个和browserify关联的js文件时,会自动执行打包,而这次打包的速度却非常快。

具体实例

watchify结合gulp的实例如下:

var gulp = require('gulp'),
  browserify = require('browserify'),
  source = require('vinyl-source-stream'),
  buffer = require('vinyl-buffer'),
  watchify = require('watchify'),
  concat = require('gulp-concat'),
  gulpif = require('gulp-if'),
  argv = require('yargs').argv,
  ...;

function getJsLibName() {
  ...
}

//初始化browserify
var b = browserify({
  entries: './src/base.js'
})
.plugin(...)
.transform(...);

//执行打包js
function bundle() {
  var jsLibName = getJsLibName();

  return b.bundle()
    .pipe(source(jsLibName))
    .pipe(buffer())
    .pipe(gulp.dest('./dist/js').on('end', function() {  //打包js后继续进行一些后续操作
      gulp.src(['./vendor/babelHelpers.js', './dist/js/' + jsLibName])
      .pipe(concat(jsLibName))
      .pipe(gulpif(argv.min, uglify()))
      .pipe(gulp.dest('./dist/js'))
    }));
}

//定义打包js任务
gulp.task('build-all-js', bundle);

//启动watchify监测文件改动
gulp.task('watch-js', function() {
  b.plugin(watchify);  //设置watchify插件
  b.on('update', function(ids) {  //监测文件改动
    ids.forEach(function(v) {
      console.log('bundle changed file:' + v);  //记录改动的文件名
    });

    gulp.start('build-all-js');  //触发打包js任务
  });

  return bundle();  //须要先执行一次bundle
});
  • 例中可以在gulpfile.js中将browserify的实例定义在全局,这样在browserify实例的update事件中就可以正常调用到bundle方法了。

  • 定义通常的打包js任务build-all-js,例如需要整个项目打包执行它即可。

  • 单独定义监测文件改动的任务watch-js,使用gulp启动这个任务后,就可以启动watchify的文件改动监测功能了。需要为browserify实例注册update事件,在该事件中触发build-all-js任务即可。另外在这个任务中须要先执行一次browserify实例的bundle方法,但这次打包的速度和直接执行build-all-js是一样的。

关于watchify的更多细节大家可以参考官方文档及这篇文章:Fast browserify builds with watchify

测试打包速度

首先在启动watch-js任务时,会执行首次打包:

图片描述

本次打包共花费了6.2秒。

然后在用户改动某个browserify关联的js文件时,都会自动触发build-all-js任务:

图片描述

可以看出,这次打包只花费了203毫秒,速度提高了很多。

更多细节大家可参考实例的源代码


joe_sky
269 声望19 粉丝

FE Developer JD.com