使用gulp

本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-05-21

安装

安装:npm install -g gulp

在根目录创建配置文件gulpfile.js

编写测试代码:

var gulp = require('gulp');

gulp.task('default', function() {
  console.log('Hello gulp');
})

// 在根目录执行gulp命令,会在当前目录搜索gulpfile.js文件,然后执行default任务

使用插件gulp-tslint检查代码的质量:

// 安装 npm install gulp-tslint --save-dev

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

gulp.task('lint', function() {
  return gulp.src([
    './source/ts/**/**.ts', './test/**/**.test.ts'
  ]).pipe(tslint())
  .pipe(tslint.report('verbose'));
})

// gulp的src函数会查找./source/ts目录及其子目录下的所有ts文件
// 以及.test目录以及其子目录下的所有扩展名为.test.ts的文件
// src函数的输出流将会被pipe函数重定向tslint函数的输入
// tslint函数的输出重定向为tslint.report函数的输入

gulp.task('default', ['lint']); // 指明lint为default任务的第一个子任务

许多插件允许我们使用!来忽略一些文件,例如!path/*.d.ts会忽略path目录下的所有扩展名为.d.ts的文件;

编译TypeScript代码:

// 安装gulp-typescript插件  npm install gulp-typescript --save-dev

var ts = require('gulp-typescript');

var tsProject = ts.createProject({
  removeComments: true,
  noImplicitAny: true,
  target: 'ES3',
  module: 'common.js',
  declarationFiles: false
})

// gulp-typescript插件宣布通过tsconfig.json的文件进行配置

gulp.task('tsc', function() {
  return gulp.src('./source/ts/**/**.ts')
          .pipe(ts(tsProject))
          .js.pipe(gulp.dest('./temp/source/js'));
})
// tsc任务会去查找./source/ts目录及其子目录下的ts文件将其交给编译器
// 编译器根据tsProject对象的属性为编译时的参数,将编译后的JavaScript代码保存在./temp/source/js录下

// 对于测试文件,应该有专门的编译配置
var tsTestProject = ts.createProject({
  // ...
});

gulp.task('tsc-tests', function() {
  return gulp.src('./test/**/**.test.ts')
          .pipe(ts(tsTestProject))
          .js.pipe(gulp.dest('./temp/test/'));
})

// 更新default任务
gulp.task('default', ['lint', 'tsc', 'tsc-tests']);

优化打包成高度优化的js文件,使用Browserify插件:

// 安装依赖 npm install browserify vinyl-transform gulp-uglify gulp-sourcemaps

var browserify = require('browserify'),
    transform = require('vinyl-transform'),
    uglify = require('gulp-uglify'),
    sourcemaps = require('gulp-sourcemaps');

var browserified = transform(function (filename) {
  var b = browserify({
    entries: filename,
    debug: true
  });

  return b.bundle();
})
// browserified函数用来将普通的Node.js流转换为Gulp流

gulp.task('bundle-js', function() {
  return gulp.src('./temp/source/js/main.js')
          .pipe(browserified)
          .pipe(sourcemaps.init({ loadMaps: true}))
          .pipe(uglify())
          .pipe(sourcemaps.write('./'))
          .pipe(gulp.dest('./dist/source/js/'))
})

// 将main.js作为入口,Browserify会从这个入口出发,追踪应用里所有的模块和依赖
// 生成一个高度优化的JavaScript文件流
// 接着使用uglify插件来最小化输出 (压缩),但是这样会让bug难以追踪
// 所以生成source map来简化追踪bug的过程

// 打包优化test代码 因为不需要优化单元测试代码的下载时间 所以不需要uglify和source map
gulp.task('bundle-test', function() {
  return gulp.src('./temp/test/**/**.test.js') // 允许多个入口
          .pipe(browserified)
          .pipe(gulp.dest('./dist/test/'))
})

// 更新default任务
gulp.task('default', ['lint', 'tsc', 'tsc-tests', 'bundle-js', 'bundle-test']);

实际项目中,应该是编译之后直接优化打包,而不是编译之后存放在temp临时目录,然后再写任务去打包;这样分开步骤描述只是为了方便理解;、

此时执行gulp的default任务,会遇到一些问题,因为所有的子任务是并行执行的;下面学习如何控制任务的执行顺序:

// 使用回调
gulp.task('sync', function (cb) {
  setTimeout(function () {
    cb();
  }, 100)
})

// 或者 返回一个流
gulp.task('sync', function () {
  return gulp.src('js/*.js')
          .pipe(concat('script/min/js'))
          .pipe(uglify())
          .pipe(gulp.dest('../dist/js'));
})

// 同步任务放在sync任务后面
gulp.task('secondTask', ['sync'], function() {
  // 这个任务在sync任务完成前都不会执行,这个回调会在任务数组中的所有任务执行完成后执行

  // 第二个参数 任务数组中还可以添加别的任务 但是里面的任务是并行执行的
})

可以使用run-sequence插件来更好的控制任务顺序

// 安装 npm install run-sequence
var runSequence = require('run-sequence');
gulp.task('default', function(sb) {
  runSequence(
    'lint',
    ['tsc', 'tsc-tests'],
    ['bundle-js', 'bundle-test'],
    'karma',
    'browser-sync',
    cb
  )
})

// 先执行lint,再并行执行tsc, tsc-tests,... 这样依次执行

但是,最新版的gulp已经不再支持同步任务,需要使用回调,Promise, async/await来完成相关同步操作;

自动化测试代码

单元测试:是指针对代码中的某个函数或某个部分(单元)进行的测试,通过单元测试,可以保证函数按照预期在工作;

使用自动化测试工具Karma以及测试框架Mocha、断言库Chai、数据模拟框架Sinon,可以自动在多个浏览器执行应用内的测试套件,而不必手动打开浏览器进行测试;

// 安装测试框架 npm install mocha chai sinon --save-dev
// 安装Karma相关包 npm install karma karma-mocha karma-chai karma-sinon karma-coverage karma-phantomjs-launcher gulp-karma --save-dev

// 在gulpfile.js中添加一个新任务

var karma = require('karma');
gulp.task('karma', function(cb) {
  gulp.src('./dist/test/**/**.test.js')
  .pipe(karma({
    configFile: 'karma.conf.js',
    action: 'run'
  }))
  .on('end', cb)
  .on('error', function(err) {
    throw err;
  })
})

// karma.conf.js
module.exports = function(config) {
  'use strict';
  config({
    basePath: '',
    frameworks: ['mocha', 'chai', 'sinon'],
    browsers: ['PhantomJs'],
    reporters: ['progress', 'coverage'],
    plugins: [
      'karma-coverage',
      'karma-mocha',
      'karma-chai',
      'karma-sinon',
      'karma-phantomjs-launcher'
    ],
    preprocessors: {
      './dist/test/*.test.js': ['coverage']
    },
    port: 9876,
    colors: true,
    autoWatch: false,
    singleRun: false,
    logLevel: config.LOG_INFO
  })
}
// 这个配置文件告诉karma应用的根目录、框架(Mocha、Chai、Sinon)、浏览器(PhantomJS)、插件和需要报告的测试执行期间的信息
// PhantomJS是一个无界面的web浏览器,使用它就无须打开一个真正的web浏览器,而可以执行单元测试代码
// karma-coverage 用来检测代码中到底有百分之几的代码被测试到,即覆盖率,会在根目录生成一个coverage目录。

使跨设备测试同步

// 安装 browser-sync包 npm install browser-sync

// 先创建两个任务,即在修改了部分代码之后,执行测试、编译打包,然后再刷新浏览器查看效果

gulp.task('bundle', function(cb) {
  runSequence('build', ['bundle-js', 'bundle-test'], cb);
})

gulp.task('test', function(cb) {
  runSequence('bundle', ['karma'], cb);
})

var browserSync = require('browser-sync');
gulp.task('browser-sync', ['test'], function() {
  browserSync({
    server: {
      baseDir: './dist'
    }
  });

  return gulp.watch([
    './dist/source/js/**/*.js',
    './dist/source/css/**.css',
    './dist/test/**/**.test.js',
    './dist/data/**/**',
    './index.html'
  ], [browserSync])
})

// gulp.watch用来监控文件是否有变化,监听到变化后调用reload
// 重新执行test任务,test任务调用bundle任务,最后刷新浏览器

// 当我们执行browser-sync任务就会在默认浏览器中自动打开应用
// 默认为localhost:3000
// 同时browser-sync工具管理页面在localhost:3001上启动
// 打开3001,即可以配置远程调试参数和设备同步参数,将手机连接到本地的网络环境就能实现跨设备测试
// 能够做到在一台设备执行测试,自动在其他多台设备上重复系列动作
// 官方文档: http://www.browsersync.io/docs