邂逅Gulp

在之前学习webpack时,了解到webpack的核心理念是模块化打包工具。

  • 使用各种各样的loader来加载各个模块。
  • 然后在webpack的生命周期中完成各种各样的plugins。

gulp的核心理念是task runner

  • 可以定义自己的一系列任务,等待任务被执行;
  • 可以在任务中插入gulp的插件体系
  • 基于 Node.js 流;

使用场景

  • gulp相对于webpack思想更加的简单、易用,更适合编写一些自动化的任务
  • 目前对于大型项目(Vue、React、Angular)并不会使用gulp来构建,比如默认gulp是不支持模块化的;

Gulp的基本知识

安装

  1. npm install gulp

gulp任务

在根目录下创建gulpfile.js文件,在这个文件里编写gulp任务

每个gulp任务都是一个异步的JavaScript函数:

  • 此函数可以接受一个callback作为参数,调用callback函数那么任务会结束;
  • 或者是一个返回stream、promise、event emitter、child process或observable类型的函数; ```javascript const { series, parallel } = require(‘gulp’);

const task1 = (cb) => { console.log(“task1”); cb(); }

const task2 = (cb) => { console.log(“task2”); cb(); }

const task3 = (cb) => { console.log(“task3”); cb(); }

//series:串行任务组合(将任务按照串行的方式组合起来,从前往后一个个执行) const seriesTask = series(task1, task2, task3); //parallel:并行任务组合(将任务按照并行的方式组合起来,会并行地同时执行) const parallelTask = parallel(task1, task2, task3);

module.exports = { seriesTask, parallelTask, }


<a name="7bb8f0da"></a>
### 任务组合:series、parallel

- pseries():串行任务组合;
- pparallel():并行任务组合;

他们都可以接受任意数量的任务函数或者已经组合的操作;

<a name="275d3348"></a>
### steam 流的相关api

- **src(读取文件) :**将所有匹配的文件读取到内存中,然后生成一个Node流(Stream);
- **dest(将内容输出到文件) :**接受一个输出目录作为参数,并且它还会产生一个 Node流(stream);
- **pipe(连接流与流) :**接收一个流,再次传递给下一个流
```javascript
const myTask = () => {
  return src("./src/*.html", {base: "./src"})
    .pipe(dest("./dist"))
}

glob文件匹配

src() 方法接受一个 glob 字符串或由多个 glob 字符串组成的数组作为参数,用于确定哪些文件需要被操作。
glob的匹配规则如下:

  1. (一个星号*):在一个字符串中,匹配任意数量的字符,包括零个匹配;

    src("./src/*.js")
    
  2. (两个星号**):在多个字符串匹配中匹配任意数量的字符串,通常用在匹配目录下的文件;

    src("./src/**/*.js")
    
  3. (取反!):

    • 由于 glob 匹配时是按照每个 glob 在数组中的位置依次进行匹配操作的;
    • 所以 glob 数组中的取反(negative)glob 必须跟在一个非取反(non-negative)的 glob 后面;
    • 第一个 glob 匹配到一组匹配项,然后后面的取反 glob 删除这些匹配项中的一部分
      src("./src/*.js", '!./src/vendor/')
      

Gulp的文件监听

watch() 方法利用文件系统的监控程序(file system watcher)将文件与任务进行关联。

const myTask = () => {
  return src("./src/*.html", {base: "./src"})
    .pipe(dest("./dist"))
}  

watch("./src/js/*.js", mytask);

自动化构建案例

接下来,我们编写一个案例,通过gulp来开启本地服务和打包:

  • 打包html文件;
  • 打包JavaScript文件;
  • 打包less文件;
  • Html资源注入
  • 删除生成目录
  • 创建打包任务
  • 创建开发任务// ```javascript //gulpfile.js const { src, dest, watch, series, parallel } = require(‘gulp’);

const htmlMin = require(‘gulp-htmlmin’); const babel = require(‘gulp-babel’); const terser = require(‘gulp-terser’); const less = require(‘gulp-less’); const postcss = require(‘gulp-postcss’); const postcssPresetEnv = require(‘postcss-preset-env’); const inject = require(‘gulp-inject’); const browserSync = require(‘browser-sync’); const del = require(‘del’);

//处理html文件,使用gulp-htmlmin插件进行压缩 const htmlTask = () => { //base的作用:要打包的文件如果在src下还有目录,也会在dist后创建目录 return src(“./src/*.html”, {base: “./src”}) .pipe(htmlMin({ collapseWhitespace: true })) .pipe(dest(“./dist”)) }

//处理js文件,使用了babel、terser插件 const jsTask = () => { return src(“./src/js/**.js”, {base: “./src”}) .pipe(babel({presets: [“@babel/preset-env”]})) .pipe(terser({mangle: {toplevel: true}})) .pipe(dest(“./dist”)) }

//处理less文件,使用了gulp-less、gulp-postcss插件 const lessTask = () => { return src(“./src/css/*.less”, {base: “./src”}) .pipe(less()) .pipe(postcss([postcssPresetEnv()])) .pipe(dest(“./dist”)) }

//对打包出来的文件导入,自动注入到index中 //注意点:在html文件中,要在想要进行文件注入的位置声明注释: const injectHtml = () => { return src(“./dist/.html”) .pipe(inject(src([“./dist/js/.js”, “./dist/css/*.css”]), {relative: true})) .pipe(dest(‘./dist’)) }

// 搭建本地服务器 //创建服务器对象 const bs = browserSync.create();

const serve = () => { //监听文件发生变化后自动编译 watch(“./src/.html”, series(htmlTask, injectHtml)); watch(“./src/js/.js”, series(jsTask, injectHtml)); watch(“./src/css/*.less”, series(lessTask));

//配置本地服务器对象 bs.init({ //端口号 port: 8080, //自动打开浏览器 open: true, //哪些资源文件发生变化时自动刷新 files: “./dist/*”, //服务器上的资源 server: { baseDir: “./dist” } }) }

//每次打包前可以清空之前的打包文件 const clean = () => { return del([“dist”]) }

const buildTask = series(clean, parallel(htmlTask, jsTask, lessTask), injectHtml); const serveTask = series(buildTask, serve);

module.exports = { serveTask, buildTask }

```json
//package.json
"scripts": {
  "serve": "gulp serveTask",
  "build": "gulp buildTask"
},