自动化构建

在开发阶段应用提高效率的语法、标准和规范,将源代码主动构建为生产代码

NPM Script

每当执行 npm run,就会主动新建一个 Shell,在这个 Shell 外面执行指定的脚本命令。因而,只有是 Shell(个别是 Bash)能够运行的命令,就能够写在 npm 脚本外面。这意味着,当前目录的node_modules/.bin 子目录外面的所有脚本,都能够间接用脚本名调用,而不用加上门路。
"build": "sass sass/main.sass css/style.css --watch",

不必写成

"build": "./node_modules/.bin/sass sass/main.sass css/style.css --watch",

默认值

一般来说,npm 脚本由用户提供。然而,npm 对两个脚本提供了默认值。也就是说,这两个脚本不必定义,就能够间接应用。

"start": "node server.js","install": "node-gyp rebuild"

下面代码中,npm run start 的默认值是 node server.js,前提是我的项目根目录下有 server.js 这个脚本;npm run install 的默认值是 node-gyp rebuild,前提是我的项目根目录下有 binding.gyp文件。

钩子

npm 脚本有 prepost 两个钩子。举例来说,build 脚本命令的钩子就是 prebuildpostbuild

"prebuild": "echo I run before the build script","build": "cross-env NODE_ENV=production webpack","postbuild": "echo I run after the build script"

用户执行 npm run build 的时候,会主动依照上面的程序执行。

npm run prebuild && npm run build && npm run postbuild

npm package

  • npm-run-all:同时启动运行多个命令

    • parallel: 并行运行多个命令,例如:npm-run-all --parallel lint build
    • serial: 多个命令按排列程序执行,例如:npm-run-all --serial clean lint build:**
    • continue-on-error: 是否疏忽谬误,增加此参数 npm-run-all 会主动退出出错的命令,持续运行失常的
    • race: 增加此参数之后,只有有一个命令运行出错,那么 npm-run-all 就会完结掉全副的命令
  • browser-sync

Grunt

根本应用

装置依赖

yarn add grunt

创立入口文件 gruntfile.js

// grunt 入口文件,用于定义须要 grunt 主动执行的工作// 须要导出一个函数,此函数接管一个 grunt 的形参,外部提供一些创立工作时能够用到的 apimodule.exports = (grunt) => {  // 注册一个名为 foo 的工作  grunt.registerTask("foo", () => {    console.log("hello grunt");  });  // 注册一个名为 bar, 形容为 工作形容 的工作  grunt.registerTask("bar", "工作形容", () => {    console.log("other task");  });  // 注册一个 default 工作, 执行时不须要指定工作名称 yarn grunt  // grunt.registerTask("default", () => {  //   console.log("default task");  // });  // 注册一个 default 工作, 顺次执行 foo 和 bar 工作  grunt.registerTask("default", ["foo", "bar"]);  // 注册一个 async-task 的异步工作  grunt.registerTask("async-task", function () {    // 申明这是一个异步工作    this.async();    setTimeout(() => {      console.log("async task");    }, 1000);  });};

通过命令执行

yarn grunt ${taskName}

标记工作失败

grunt 中标记工作失败后,后续工作个别将不会在执行。能够通过 --force 参数强制执行失败工作的后续工作

yarn grunt --force
  • 同步工作:通过返回 false 标记失败
module.exports = (grunt) => {  grunt.registerTask("foo", () => {    console.log("hello grunt");    return false;  });};
  • 异步工作:通过执行状态
module.exports = (grunt) => {  grunt.registerTask("async-task", function () {    // 申明这是一个异步工作    const done = this.async();    setTimeout(() => {      console.log("async task");      done(false);    }, 1000);  });};

配置选项办法

能够通过 grunt.initConfig 办法配置 grunt 属性

module.exports = (grunt) => {  grunt.initConfig({    foo: { name: "jasper" },  });  grunt.registerTask("foo", () => {    console.log(grunt.config().foo.name);  });};

多指标工作

initConfig 配置中,每一个和工作同名的配置下的属性就是一个指标,通过运行该工作能够执行配置下的所有指标。

module.exports = (grunt) => {  grunt.initConfig({    foo: {      options: {        sex: "男",      },      name: "jasper",      age: 25,    },  });  // 多指标  grunt.registerMultiTask("foo", function () {    console.log(this.options());    console.log(`target: ${this.target}, data: ${this.data}`);  });};

插件应用

装置插件

yarn add grunt-contrib-clean --dev

加载插件

grunt.loadNpmTasks("grunt-contrib-clean");

配置指标

grunt.initConfig({  clean: {    temp: "temp/**",  },});

执行

yarn grunt clean
module.exports = (grunt) => {  grunt.loadNpmTasks("grunt-contrib-clean");  grunt.initConfig({    clean: {      temp: "temp/**",    },  });};

罕用插件

  • load-grunt-tasks
  • grunt-sass
  • grunt-babel
  • grunt-contrib-watch

Gulp

根本应用

装置 gulp

yarn add gulp --dev

创立 gulpfile.js 文件

在最新的 gulp 中约定每个工作都是异步工作,因而咱们须要标记工作实现通过 done 参数

exports.foo = (done) => {  console.log("foo task working...");  done();};// 默认工作exports.default = (done) => {  console.log("this is default task");  done();};// gulp 4.0 以前通过注册一个工作,不举荐const gulp = require("gulp");gulp.task("old", (done) => {  console.log("old gulp task..");  done();});

执行工作

yarn gulp foo

组合工作

咱们能够依据具体场景抉择工作是并行执行(paralle)还是串行执行(series)。

  • 部署须要先执行编译工作,在执行部署工作,那么应该是串行执行
  • 编译时,less/sass 和 js 的编译并没有先后依赖关系,那么能够并行执行,提高效率
const { series, parallel } = require("gulp");const task1 = (done) => {  setTimeout(() => {    console.log("task1 working~");    done();  }, 1000);};const task2 = (done) => {  setTimeout(() => {    console.log("task2 working~");    done();  }, 1000);};const task3 = (done) => {  setTimeout(() => {    console.log("task3 working~");    done();  }, 1000);};exports.foo = series(task1, task2, task3); //串行顺次执行exports.bar = parallel(task1, task2, task3); //并行执行

异步工作

回调函数

exports.callback = (done) => {  console.log("callback task~");  done();};//如果多个工作执行,前面不会再执行exports.callback_error = (done) => {  console.log("callback_error task~");  done(new Error("task Failed"));};

promise

exports.promise = () => {  console.log("promise task~");  return Promise.resolve("ok"); //要返回一个promise对象};exports.promise_error = () => {  console.log("promise_error task~");  return Promise.reject(new Error("task Failed")); //要返回一个promise对象};

async/await

const timeout = (time) => {  return new Promise((resolve) => {    setTimeout(resolve, time);  });};exports.async = async () => {  await timeout(1000);  console.log("async task~");};

Gulp 构建过程外围工作原理

  • 基于流的构建零碎
const fs = require("fs");const { Transform } = require("stream");exports.default = () => {  //文件读取流  const read = fs.createReadStream("normalize.css");  //文件写入流  const write = fs.createWriteStream("normalize.min.css");  //文件转换流  const transform = new Transform({    //    transform: (chunk, encoding, callback) => {      //外围转换过程      //外围转换过程实现      //chunk => 读取流中读到的内容(Buffer)toString转化程字符串      const input = chunk.toString();      const output = input.replace(/\s+/g, "").replace(/\/\*.+?\*\//g, "");      callback(null, output); //谬误优先,没有谬误传null    },  });  //把读取进去的文件流导入写入文件流  read.pipe(transform).pipe(write);  return read;};

Gulp 文件操作 API

转换流个别都是通过插件提供 src().pipe(转换流).pipe(dest(目标目录))
const { src, dest } = require("gulp");const cleanCss = require("gulp-clean-css");const rename = require("gulp-rename");exports.default = () => {  return src("src/*.css") //创立文件读取流    .pipe(cleanCss())    .pipe(rename({ extname: ".min.css" })) //重命名扩展名    .pipe(dest("dist")); //导出到dest写入流中  参数写入目标目录};

FIS

根本应用

装置

yarn add fis3 --dev

增加 fis 配置文件 fis-conf.js

//资源定位fis.match("*.{js,scss,png}", {  release: "/assets/$0", //以后文件原始目录构造});//编译压缩//yarn global add fis-parser-node-sassfis.match("**/*.scss", {  rExt: ".css",  parser: fis.plugin("node-sass"),  optimizer: fis.plugin("clean-css"),});//yarn global add fis-parser-babel-6.xfis.match("**/*.js", {  parser: fis.plugin("babel-6.x"),  optimizer: fis.plugin("uglify-js"),});

执行,fis3 inspect 查看转换文件

fis3 release -d output