邂逅Gulp
在之前学习webpack时,了解到webpack的核心理念是模块化打包工具。
- 使用各种各样的loader来加载各个模块。
- 然后在webpack的生命周期中完成各种各样的plugins。
gulp的核心理念是task runner
- 可以定义自己的一系列任务,等待任务被执行;
- 可以在任务中插入gulp的插件体系
- 基于 Node.js 流;
使用场景
- gulp相对于webpack思想更加的简单、易用,更适合编写一些自动化的任务;
- 目前对于大型项目(Vue、React、Angular)并不会使用gulp来构建,比如默认gulp是不支持模块化的;
Gulp的基本知识
安装
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的匹配规则如下:
(一个星号*):在一个字符串中,匹配任意数量的字符,包括零个匹配;
src("./src/*.js")
(两个星号**):在多个字符串匹配中匹配任意数量的字符串,通常用在匹配目录下的文件;
src("./src/**/*.js")
(取反!):
- 由于 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"
},