在每次开发前,先把要做的事项一一列出来,或者把流程图画一下,有助于梳理思路
Gulp简介
Gulp 是目前最流行的前端构建系统,高效易用,是一个基于流的构建系统。它将开发流程中让人痛苦或耗时的任务自动化,从而减少浪费的时间,创造更大的价值。
Gulp官网给出了它的三大特性,如下图:
安装使用
node.js版本需要 >=12 || 14.13.1 || >= 16
使用步骤如下:
-
把gulp安装到全局环境
安装 gulp 命令行工具
npm install --global gulp-cli
安装 gulp,作为开发时依赖项npm install --save-dev gulp
-
建立gulpfile.js配置文件,编写构建任务,在运行gulp命令时会被自动加载
打开需要构建的项目代码,使用包管理工具初始化一下项目环境,生成package.json文件,在同级目录新建一个
gulpfile.js
的文件,作为gulp自动化构建的配置文件。Vscode里可以在终端运行code gulpfile.js
快速生成并打开这个文件。 -
在命令行终端运行gulp任务
在项目根目录下运行
gulp
命令测试,看到以下提示证明gulp安装成功,只是我们还没有配置任务。
gulp自动化构建的主要过程
读取文件 ---》 压缩文件 ---》 写入文件 (都是以流的方式进行)
gulp 暴露了 src() 和 dest() 方法用于处理计算机上存放的文件。
src( )
: 读取文件生成一个Node流
dest( )
:生成一个Node流,通常作为终止流
流(stream)
所提供的主要的 API 是 .pipe()
方法,用于连接转换流或可写流。
创建任务前,需要把 src 和 dest 引入进来
// 使用Common JS 规范引入
const { src, dest } = require('gulp')
创建任务
创建任务主要使用gulp提供的一些插件实现,可以根据实际需要通过glup官网插件库进行搜索,基本上,每个插件提供的都是一个函数,函数调用结果会返回一个转换流,这样就可以实现一个文件里的转换。
创建一个压缩css的任务,这里用到插件gulp-clean-css
全局安装开发依赖 yarn gulp-clean-css --dev
const { src, dest } = require('gulp');
// 压缩css
const cleanCss = require('gulp-clean-css');
function streamTask() {
return src('src/*.css', { base: 'src' }) // base:基准路径,指定按src原有目录输出
.pipe(cleanCss())
.pipe(dest('dist'))
}
exports.default = streamTask; // 导出默认任务
// 或
module.export = { streamTask } // 导出命名任务
执行命令行指令yarn gulp
执行gulpfile.js的默认任务(yarn gulp streamTask
执行指定任务),下图可见src目录下的index.css文件被压缩成功。
通配符 *
src/*.css
: src根目录下的css
src/**/*css
: 子文件的通配方式,src任意子目录下的css
src/**
: src任意子目录下所有文件
组合任务
Gulp 提供了两个强大的组合方法: series()
和 parallel()
,允许将多个独立的任务组合为一个更大的操作
series()
:串联,按先后顺序执行任务
parallel()
: 并行,同时执行多个任务
const { src, dest, series, parallel } = require('gulp');
function css() {...}
function html() {...}
function js() {...}
// css、html、js 互不影响,可以同时执行,创建一个组合任务并行执行
const complicate = parallel(cssStyle, sassStyle, js, page)
module.exports = {
complicate
};
配置热更新开发服务器
使用 browser-sync
const browserSync = require('browser-sync')
const bs = browserSync.create()
function serve() {
bs.init({
server: {
baseDir: 'dir'
}
})
}
一个基础的自动化构建完整配置如下:
主要实现功能:
- 转换SCSS、html模板、ES6
- 压缩css、html、js、图片、字体文件
- 输出静态文件
- 清除文件
- 文件引用处理(构建注释转换)
- 监听文件变化
- 配置热更新开发服务器
- 对外暴露公有任务(clean、dev、build)
/**
* src 读取流,dest 终止/输出流;
* 组合任务:series 串联; parallel 并行
* watch 监听文件,发生变化了就执行对应任务,把dist目录对应的文件覆盖
**/
const { src, dest, series, parallel, watch } = require('gulp');
// // 清除文件,串联操作,需要先删除后执行构建任务
const del = require('del')
// 压缩css
const cleanCss = require('gulp-clean-css');
// 重命名
const rename = require('gulp-rename');
// gulp-sass sass:把sass转换成css
const sass = require('gulp-sass')(require('sass'));
// gulp-babel @babel/core @babel/preset-env :转换脚本,转换ES6及以上的新特性
const babel = require('gulp-babel')
// html模板文件转换
const swig = require('gulp-swig')
// 图片文件转换,imagemin通过C++完成的模块,需要同时下载二进制的程序集(github上下载)
/**
* gulp-imagemin安装最新版可能发生一下错误信息,此时重装一个低版本的就可以
node_modules\.bin\gulp image
Error [ERR_REQUIRE_ESM]: require() of ES Module
gulpfile.js not supported.
Instead change the require of index.js
* */
const imagemin = require('gulp-imagemin')
// 文件引用处理、压缩合并
const useref = require('gulp-useref')
// 条件插件
const ifPlugin = require('gulp-if')
// 文件压缩
const htmlmin = require('gulp-htmlmin')
const uglify = require('gulp-uglify')
// 创建开发服务器
const browserSync = require('browser-sync')
const bs = browserSync.create()
function serve() {
watch('./src/assets/styles/*.css', cssStyle)
watch('./src/assets/styles/*.scss', sassStyle)
watch('./src/**/*.js', js)
watch('./src/**/*.html', page)
// watch('./src/assets/images/**', image)
// watch('./src/assets/fonts/**', font)
// watch('public/**', extra)
// 尽量减少构建次数,此处设置监听images、fonts、public文件,发生变化时通知浏览器,触发bs.reload重新获取最新文件
watch([
'src/assets/images/**',
'src/assets/fonts/**',
'public/**'
], bs.reload)
bs.init({
port: 2000, // 端口
files: 'dist/**', // dist文件发生变化时,自动通知浏览器,实现源代码修改时会自动同步到浏览器
server: {
// 提高构建效率:启动开发服务器需要先从temp里找,temp里面才是打包好的html、css、js
baseDir: ['temp', 'src', 'public'],
routes: {
'/node_modules': 'node_modules'
}
}
})
}
// 清空正式环境目录dist,临时目录/语法编译的中间目录temp(开发环境构建文件放在临时目录temp)
function clean () {
return del(['dist', 'temp'])
}
function cssStyle() {
return src('./src/assets/styles/*.css', { base: 'src' })
.pipe(cleanCss())
.pipe(rename({ extname: ".min.css" }))
.pipe(dest('temp'))
}
// _. 开头的scss文件,会被默认为是mian.css的依赖文件,被打包在mian.css文件内
function sassStyle() {
return src('./src/assets/styles/*.scss', { base: 'src' })
.pipe(sass({ outputStyle: 'expanded' })) // 设置输出样式完全展开
.pipe(cleanCss())
.pipe(rename({ extname: ".min.css" }))
.pipe(dest('temp'))
}
function js() {
return src('./src/**/*.js', { base: 'src' })
.pipe(babel({ presets: ['@babel/preset-env'] })) // babel 只是一个ES的转换平台,本身不做转换,只是提供一个环境,实现转换的是内部的一些插件,preset是插件的集合
.pipe(dest('temp'))
}
// html模板内部使用的数据,通过swig({ data })传入
const data = {
pkg: {
name: 'lili',
description: '第一次自动化构建'
}
}
function page() {
return src('./src/**/*.html', { base: 'src' })
.pipe(swig({data}))
.pipe(dest('temp'))
}
// 无损压缩,只是删减一些图片信息
function image() {
return src('./src/assets/images/**', { base: 'src' })
.pipe(imagemin())
.pipe(dest('dist'))
}
// 字体文件同样采用imagemin插件,可以压缩里面的svg图片,其他字体文件默认不处理直接输出
function font() {
return src('./src/assets/fonts/**', { base: 'src' })
.pipe(imagemin())
.pipe(dest('dist'))
}
// 对额外的静态文件做拷贝--只在部署正式环境打包的时候需要
function extra() {
return src('public/**', { base: 'public' })
.pipe(dest('dist/public'))
}
function userefTask() {
return src('temp/*.html', { base: 'temp' })
.pipe(useref({ searchPath: ['temp', '.'] })) // 对代码中的构建注释做转换
.pipe(ifPlugin(/\.js$/, uglify()))
.pipe(ifPlugin(/\.css$/, cleanCss()))
.pipe(ifPlugin(/\.html$/, htmlmin(
{
// 对html内联js、css压缩
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true
}
)))
.pipe(dest('temp'))
}
const complicate = parallel(sassStyle, cssStyle, js, page)
const build = series(clean, parallel(series(complicate, userefTask), image, font, extra))
const dev = series(complicate, serve)
module.exports = {
clean,
build,
dev
};
自动加载所有gulp插件
在gulpfile.js
文件中,我们避免不了引入各种各样的gulp插件,因此需要编写很多重复性的引入代码,这里可以使用gulp-load-plugins
一次性自动加载所有gulp插件。同样在终端运行命令行安装这个开发依赖。
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
上文中所有使用到gulp插件的地方,可以做如下示例优化:
cleanCss()
改为 plugins.cleanCss()
,这样可以省略单独引入插件的代码
function cssStyle() {
return src('./src/assets/styles/*.css', { base: 'src' })
.pipe(plugins.cleanCss())
.pipe(dest('dist'))
}
配置package.json,便于协作开发和使用
把暴露出来的任务,在package.json
中scripts
选项进行配置。这样我们终端就可以使用快捷方式执行gulp这些任务。如yarn clean
、yarn build
、yarn start
"scripts": {
"clean": "gulp clean",
"build": "gulp build",
"start": "gulp dev"
},
封装工作流
提取数据
- 上文data数据不应该放在gulpfile.js文件中,需要把这个数据提取出来放在一个文件中,再使用require引入
- 提供可配置的能力,配置中写死的绝对路径如
'./src/assets/images/**'
抽象成可配置
创作不易,麻烦动动手指头点个赞,欢迎给我留言~~~