实现前
实现之前,我们先来了解下 gulp 自动构建工具的具体流程
- 具体工作流程可以简化为
读取文件流 --> 转化流文件 --> 写入流文件
- 完整的实现流程如下
- 确定需求,需要构建的任务
- 初始化项目 yarn init
- 安装项目依赖 yarn add --dev gulp | yarn add -g gulp
- 在项目的根目录下创建 gulpfile.js 文件
- 在 gulpfile.js 中实现我们的任务
- 导出需要使用的任务 module.exports = {start, build, ...}
- 根据团队需求确定是否在 package.json 文件的 scripts 中构建命令
- 测试 gulp + symbolName || yarn + scriptsName
- 输出结果
工作流程图markdown语法画不出来,将就着看下
一、需求
- yarn lint 用于处理 scripts & styles 文件的格式问题
- yarn compile 用于生成对应的 styles & scripts & pages 文件
- yarn serve 用于app的 开发运行 对应的配置传入 open port
- yarn build 用于打包 对应的配置传入 production prod
- yarn start 运行当前项目 生成环境 对应的配置传入 open port
- yarn deploy 将当前文件推送到 github 的分支 默认 gh-pages
- yarn clean 用于清除 dist temp 两个目录下的文件
二、按照需求定义相应的任务
API说明见备注
- 初始化我们的项目
- yarn init
- 安装 gulp 依赖 yarn add --dev gulp
- 安装 gulp 脚手架 yarn add -g gulp-cli 考虑到后续会多次使用
- 定义一个 lint 任务用于 实现对 js scss 代码格式的校验
- 此处使用eslint stylelint 来校验我们的代码
- 安装相应的依赖
yarn add --dev gulp-eslint gulp-stylelint stylelint stylelint-scss gulp-load-plugins
- 安装完依赖,接下来来实现对应的任务,以下为实现任务的代码片段
// 样式校验任务 需要在项目根目录下 添加相应的规则文件 .stylelintrc.json const lintStyles = () => { // dest() 写入流文件 return src(config.paths.styles, { cwd: config.src }).pipe(plugins.stylelint()) } // js校验任务 需要在项目根目录下 添加相应的规则文件 .eslintrc.json const lintScripts = () => { return src(config.paths.scripts, { base: config.src, cwd: config.src }).pipe(plugins.eslint()) .pipe(plugins.eslint.format()) .pipe(plugins.eslint.failAfterError()) } // 因为两个任务可以并行执行 所有选择 parallel const lint = parallel(lintStyles, lintScripts)
- scripts配置对应的命令
lint: gulp lint
运行对应的命令yarn lint
校验是否如预期的效果一样
-
定义一个 compile 任务 用于处理 html | js | scss 文件,并打包到 temp 文件下
- 重复流程
- 安装需要用到的依赖
yarn add --dev gulp-sass gulp-babel @babel/preset-env gulp-swig browser-sync
- 定义一个 pages 任务用于对 html 文件的处理;定义一个 scripts 任务用于对 js 文件的处理;定义一个 styles 任务用于对 scss 文件的处理转换;其次通过 parallel 构建 gulp compile 命令, 最后配置对应的 scripts 任务即可;以下为实现任务的代码片段
const pages = () => { return src(config.paths.pages, { cwd: config.src, ignore: ['{layouts,partials}/**'] }) // 将 data 数据渲染到 html 模板中 .pipe(plugins.swig(data)) .pipe(dest(config.temp)) } const scripts = () => { return src(config.paths.scripts, { base: config.src, cwd: config.src, sourcemaps: !isProd }) .pipe(plugins.babel({presets: [require('@babel/preset-env')]})) .pipe(dest(config.temp, { sourcemaps: '.' })) // 如果 流文件 有变动 刷新当前的 页面 .pipe(bs.reload({stream: true})) } const styles = () => { return src(config.paths.styles, { base: config.src, cwd: config.src, sourcemaps: !isProd }) .pipe(plugins.sass()) .pipe(dest(config.temp, { sourcemaps: '.' })) .pipe(bs.reload({stream: true})) } const compile = parallel(pages, scripts, styles)
- 测试 yarn compile
-
为了便于调试,优先实现 yarn clean 命令用于删除生成的缓存文件
- 重复流程,安装 del 依赖,用于删除对应的文件
- 具体实现代码如下
const clean = () => { return del([config.temp, config.dist]) }
- 导出 clean 命令,测试 yarn clean
-
定义一个 serve 任务 用于开发调试使用 可传入参数 --port 端口号 --open 布尔值
- 重复流程,安装 minimist 依赖 用于处理 node 命令将 --open --port 转换为参数
- 具体实现代码如下
const argv = minimist(process.argv.slice(2)) const devServe = () => { watch(config.paths.pages, {cwd: config.src}, pages) watch(config.paths.scripts, {cwd: config.src}, scripts) watch(config.paths.styles, {cwd: config.src}, styles) watch([ config.paths.images, config.paths.fonts ], {cwd: config.src}, bs.reload ) watch('**', {cwd: config.public}, bs.reload) bs.init({ notify: false, open: argv.open ? true : false, port: argv.port ? argv.port : 2080, plugins: [`bs-html-injector?files[]=${config.temp}/*.html`], server: { baseDir: [config.temp, config.src, config.public], // 'dist', // 优先级高于 baseDir,路由映射 使用useref解决对应的打包问题 routes: { '/node_modules': 'node_modules' } } }) } const compile = parallel(pages, scripts, styles) const serve = series(compile, devServe)
- 测试功能 yarn serve | year serve --port 8088 --open true
-
定义一个 build 任务,用于对 我们即将要发布的 文件进行 打包压缩 可传入传输 --prod --production
- 重复流程,安装 gulp-uglify gulp-html gulp-clean-css gulp-imagemin gulp-size gulp-if 等依赖,用于压缩对应的 js & html & css & images & fonts 等文件的压缩
const isProd = process.env.NODE_ENV ? process.env.NODE_ENV === 'production' : argv.production || argv.prod || false const images = () => { return src(config.paths.images, { base: config.src, cwd: config.src }) .pipe(plugins.imagemin()) .pipe(dest(config.dist)) } const fonts = () => { return src(config.paths.fonts, { base: config.src, cwd: config.src }) .pipe(plugins.imagemin()) .pipe(dest(config.dist)) } const extra = () => { return src('**', { base: config.public, cwd: config.public }) .pipe(dest(config.dist)) } const measure = () => { return src('**', { cwd: config.dest }) .pipe(plugins.size({ gzip: true })) } const useref = () => { return src(config.paths.pages, {base: config.temp, cwd: config.temp}) .pipe(plugins.useref({searchPath: [config.temp, '.']})) .pipe(plugins.if(/\.js$/, plugins.uglify())) .pipe(plugins.if(/\.css$/, plugins.cleanCss())) .pipe(plugins.if(/\.html$/, plugins.html( { indent_size: 2, max_preserve_newlines: 1 } ))) .pipe(dest(config.dist)) } const compile = parallel(pages, scripts, styles) const build = series( clean, parallel( series(compile, useref), fonts, images, extra ), measure )
- 测试功能 yarn build | year build --prod | year build --production
-
构建一个 start 任务, 运行当前项目生成环境 对应的配置传入 --open 布尔值 --port 端口号
- 重复流程具体实现代码如下:
const prodServe = () => { bs.init({ notify: false, open: argv.open ? true : false, port: argv.port ? argv.port : 2080, server: config.dist }) } const build = series( clean, parallel( series(compile, useref), fonts, images, extra ), measure ) const start = series(build, prodServe)
- 测试功能 yarn start | year start --port 8088 --open true
-
构建一个 deploy 任务,将当前文件推送到 github 的分支 默认 gh-pages
- 重复流程,安装项目依赖 gulp-gh-pages 具体实现代码如下:
const push = () => { return src('**', {cwd: config.dist}) .pipe(plugins.ghPages({ // 提交到 github 的分支名称 branch: argv.branch ? argv.branch : 'gh-pages', // 本地构建的缓存目录 cacheDir: `${config.temp}/publish` })) }
- 测试功能 yarn deploy
到此,我们就完成了一个gulp脚手架的构建任务了
备注
src()
属性 | 作用 |
---|---|
globs | 返回一个可以在管道中使用的流 |
options | 配置文件的详细说明 |
options
属性 | 作用 |
---|---|
base | 在流文件中设置对应的属性 |
cwd | 与相对路径结合形成绝对路径 |
sourcemaps | 加载内部sourcemaps 解析外部的sourcemaps |
ignore | 从匹配中排除对应的文件 |
pipe 转换对应的流文件
dest()
属性 | 作用 |
---|---|
directory | 将文件写入的输出目录的路径 |
options | 配置文件的详细说明 |
options
属性 | 作用 |
---|---|
cwd | 与相对路径结合形成绝对路径 |
overwrite | 是否覆盖相同路径的文件 default:true |
sourcemaps | 将内部sourcemaps写入输出文件 外部sourcemaps |
watch()
监听globs并在发生更改时运行任务,任务与任务系统的其余部分被统一处理
属性 | 作用 |
---|---|
globs | 用来监听文件系统 |
options | 配置文件的详细说明 |
task | 一个任务函数 |