关于gulp的那些事

148 阅读5分钟

gulp是大家比较熟悉的一个打包编译工具,这里介绍下它的基本使用和封装

gulp基本使用

首先我们捋一下思路:

开发环境:

  1. 增加js,css,html相关编译任务,把编译文件存放到开发环境文件夹
  2. 增加启动服务,请求文件地址按照 生产环境文件夹 => src => public 的顺序查找
  3. 增加watch实时监控,监控src下html,js,css,images,fonts的文件变化,其中html,css,js调用相关编译任务,全部重载浏览器页面

生产环境:

  1. 增加images,fonts,其他文件的相关压缩任务(不包括js,css,html,js,css,html开发环境直接存放到存放到开发环境文件夹,生产环境通过读取开发环境文件夹html找到引用的js,css,然后进行合并压缩),把压缩文件存放到生产环境文件夹
  2. 读取 开发环境文件夹 里面html,对html及其引用文件用相应插件合并,压缩
  3. 把压缩后的文件存放到 生产环境文件夹
  1. 在建相应的任务之前,我们可以根据文件的目录结构,增加一个配置文件,比如文件目录结构如截图,则可增加配置文件

image.png

let config={
  build:{
    src:'src',
    temp:'.temp', //开发环境压缩文件存放目录
    dist:'release', //生产环境压缩文件存放目录
    public:'public',
    paths:{
      styles:'assets/styles/*.scss', //匹配当前文件夹所有scss文件
      scripts:'assets/scripts/*.js',//匹配当前文件夹所有js文件
      pages:'*.html',//匹配当前文件夹所有html文件
      images:'assets/images/**',//匹配当前文件夹所有图片文件
      fonts:'assets/fonts/**'//匹配当前文件夹所有字体文件文件
    }
  }
}
  1. 安装需要的模块
  • 安装gulp模块
yarn add gulp --dev
  • 安装编译sass的插件
yarn add gulp-sass@^4.0.0 --dev //有坑,这里要安装4.0.0版本,否则提示你要再安装一遍node-sass
  • 安装编译js的插件
yarn add gulp-babel --dev
yarn add @babel/core @babel/preset-env --dev
  • 安装编译html的插件
yarn add gulp-swig --dev
  • 安装压缩image,fonts的插件
//有坑,这里要安装7.0.0版本,否则报错:require() of ES modules is not supported.
yarn add gulp-imagemin@^7.0.0 --dev
  • 最后安装一下gulp-load-plugins,这个插件可以一次性包括 package.json 里面的所有的 gulp 依赖包,无需在 gulpfile.js 使用require 关键字一个一个的把依赖包导入进去
yarn add gulp-imagemin --dev

3.开发环境编译

let config={
  data:{ //data是传给html的数据,可以通过{{}}在html模板中直接嵌套
    menus: [
      {
        name: 'Home',
        icon: 'aperture',
        link: 'index.html'
      },
      {
        name: 'Features',
        link: 'features.html'
      },
      {
        name: 'About',
        link: 'about.html'
      },
      {
        name: 'Contact',
        link: '#',
        children: [
          {
            name: 'Twitter',
            link: 'https://twitter.com/w_zce'
          },
          {
            name: 'About',
            link: 'https://weibo.com/zceme'
          },
          {
            name: 'divider'
          },
          {
            name: 'About',
            link: 'https://github.com/zce'
          }
        ]
      }
    ],
    pkg: require('./package.json'),
    data: new Date()
  },
  build:{//路径配置
    src:'src',
    temp:'.temp',
    dist:'release',
    public:'public',
    paths:{
      styles:'assets/styles/*.scss',
      scripts:'assets/scripts/*.js',
      pages:'*.html',
      images:'assets/images/**',
      fonts:'assets/fonts/**'
    }
  }
}

const {src,dest,series,parallel}=require('gulp')
const del=require('del')
const loadPlugins=require('gulp-load-plugins')
const plugins=loadPlugins();

//style编译任务
const style=()=>{
  return src(config.build.paths.styles,{base:config.build.src,cwd:config.build.src}).pipe(plugins.sass({outputStyle:'expand'})) 
    .pipe(dest(config.build.temp))
//base:copy的时候按照该文件夹的目录结构,cwd:查找从哪开始找
}

//js编译任务
const script=()=>{
  return src(config.build.paths.scripts,{base:config.build.src,cwd:config.build.src}).pipe(plugins.babel({presets:[require('@babel/preset-env')]}))
    .pipe(dest(config.build.temp))
//@babel/preset-env:是一个智能预设,它允许你使用最新的 JavaScript ,无须语法转换
}

//html编译任务
const page=()=>{
  return src(config.build.paths.pages,{base:config.build.src,cwd:`${config.build.src}/**`}).pipe(plugins.swig({data:config.data,defaults:{cache:false}}))
    .pipe(dest(config.build.temp))
}

//image编译任务
const image=()=>{
  return src(config.build.paths.images,{base:config.build.src,cwd:config.build.src}).pipe(plugins.imagemin())
    .pipe(dest(config.build.temp))
}

//字体编译任务
const font=()=>{
  return src(config.build.paths.fonts,{base:config.build.src,cwd:config.build.src}).pipe(plugins.imagemin())
    .pipe(dest(config.build.temp))
}

//public的其他文件,直接copy到.temp文件夹内
const extra=()=>{
  return src('**',{base:config.build.public,cwd:config.build.public}).pipe(plugins.imagemin())
}

//编译之前先删掉这些文件夹内的文件
const clean=()=>{
  return del([config.build.temp])
}

//需要先clean所以用series串联任务,style,script,page,image,font,extra这些任务用parallel串联
const develop=series(clean,parallel(style,script,page,image,font,extra))

//导出develop任务
module.exports={
  develop
}

运行命令编译

yarn gulp develop

得到如下

image.png

  1. 开发环境增加服务器及监视变化

Browsersync能让浏览器实时、快速响应您的文件更改(html、js、css、sass、less等)并自动刷新页面。

  • 安装插件Browsersync
yarn add browser-sync --dev
  • 引入browser-sync插件,并监视相应的html,js,css,images,fonts
const browserSync=require('browser-sync')
const bs=browserSync.create();
  • html,js,css发生变化调用对应的编译方法
const {src,dest,series,parallel,watch}=require('gulp')
const server = ()=>{

//watch 实时监控
  watch(config.build.paths.styles,{cwd:config.build.src},style)
  watch(config.build.paths.scripts,{cwd:config.build.src},script)
  watch(config.build.paths.pages,{cwd:`${config.build.src}/**`},page)
  watch([config.build.paths.images,config.build.paths.fonts],{cwd:config.build.src},bs.reload)
  watch('**',{cwd:config.build.public},bs.reload)
  bs.init({
    port:'2099',
    server:{
      baseDir:[config.build.temp,config.build.src,config.build.public],
      routes:{
        '/node_modules':'node_modules'
      }
    }
  })
}
  • html,js,css调用编译方法后需要重载,故style,scrpit,page方法需要加上bs.reload({stream:true}),代码更改后如下
const style=()=>{
  return src(config.build.paths.styles,{base:config.build.src,cwd:config.build.src}).pipe(plugins.sass({outputStyle:'expand'}))
    .pipe(dest(config.build.temp)).pipe(bs.reload({stream:true}))
}
const script=()=>{
  return src(config.build.paths.scripts,{base:config.build.src,cwd:config.build.src}).pipe(plugins.babel({presets:[require('@babel/preset-env')]}))
    .pipe(dest(config.build.temp)).pipe(bs.reload({stream:true}))
}
const page=()=>{
  return src(config.build.paths.pages,{base:config.build.src,cwd:`${config.build.src}/**`}).pipe(plugins.swig({data:config.data,defaults:{cache:false}}))
    .pipe(dest(config.build.temp)).pipe(bs.reload({stream:true}))
}
  • images,fonts发生改变,直接重载,不需要重新编译,为了节省编译时间,images,fonts到生产环境才需要编译,故page,font方法可以直接copy到config.build.dist里面,且develop里面移除page、font方法
const image=()=>{
  return src(config.build.paths.images,{base:config.build.src,cwd:config.build.src}).pipe(plugins.imagemin())
    .pipe(dest(config.build.dist))
}
const font=()=>{
  return src(config.build.paths.fonts,{base:config.build.src,cwd:config.build.src}).pipe(plugins.imagemin())
    .pipe(dest(config.build.dist))
}

const extra=()=>{
  return src('**',{base:config.build.public,cwd:config.build.public}).pipe(plugins.imagemin())
    .pipe(dest(config.build.dist))
}
const develop=series(clean,parallel(style,script,page),server)
  1. 生产环境文件的合并和压缩
  • 合并:把config.build.temp里面的相关文件进行合并,需要安装gulp-useref。如图中圈住的部分,注释内多个文件会被合并成一个文件

image.png

yarn add gulp-useref --dev
  • 安装条件判断插件 gulp-if
yarn add gulp-if --dev
  • 安装css的压缩插件gulp-clean-css,html的压缩插件gulp-htmlmin,js的压缩插件gulp-uglify
yarn add gulp-clean-css gulp-htmlmin gulp-uglify --dev
  • 读取config.build.temp里面的html文件,根据文件类型进行压缩,最后存放到dist文件
const useRef=()=>{
  return src(config.build.paths.pages,{base:config.build.temp,cwd:config.build.temp})
    .pipe(plugins.useref({searchPath:['.','..',config.build.temp]}))
    .pipe(plugins.if(/\.css$/,plugins.cleanCss()))
    .pipe(plugins.if(/\.js$/,plugins.uglify()))
    .pipe(plugins.if(/.html$/,plugins.htmlmin({
      collapseWhitespace:true,
      minifyCss:true,
      minifyJs:true
    })))
}
  • 构建生产环境的build任务
const compile=parallel(style,script,page,image,font,extra)
const build=series(clean,compile,useRef)

gulp的封装

思路:zce-pages-lulu为封装的脚手架文件,pages-boilerplate为需要编译压缩的项目,我们现在把写过的gulpfile.js文件抽取成一个脚手架文件并在npm上发布,然后在pages-boilerplate安装使用

  1. 新建一个文件夹,并且初始化配置文件,初始化git配置
mkdir zce-pages-lulu
cd zce-pages-lulu
yarn init
git init
  1. 把我们安装过的插件全部copy到zce-pages-lulu的package.json的依赖里面

image.png

  1. 新建入口文件lib/index.js
  • 把我们上次写的gulpfile.js里面的文件全部拷进去 image.png
  1. 抽取gulpfile.js的配置项文件
  • 把原本gulpfile.js的配置项文件抽取成config.pages.js文件,放到执行pages-boilerplate项目中

image.png

--在index.js中引入执行项目的配置文件

let config={
}
try {
  const loadConfig=require(`${process.cwd()}/pages.config.js`)
  config=Object.assign({},config,loadConfig)
}catch (e) {
}
  1. 新建执行命令文件bin-zce-pages.js,增加执行代码
#!/usr/bin/env node 
//必填,指明执行环境node

process.argv.push('--cwd')
process.argv.push(process.cwd())  //增加执行时所在项目的路径
process.argv.push('--gulpfile')
process.argv.push(require.resolve('..')) //增加执行的gulpfile文件
console.log(process.argv)
require('gulp/bin/gulp')  //载入gulp文件
  1. 在脚手架项目package.json文件内增加入口文件和执行文件
"main": "lib/index.js",
"bin": "bin/zce-pages.js"

package.json文件一览

{
  "name": "zce-pages-lulu", //npm publish的时候需要改成自己的名字,否则会提示没有权限
  "version": "0.3.1", //每次npm publish需要修改版本号
  "description": "Awesome node modules.",
  "keywords": [
    "zce-pages",
    "zce"
  ],
  "repository": "zce/zce-pages",
  "license": "MIT",
  "author": "lilulu <799335607@qq.com> (https://zce/me)",
  "main": "lib/index.js", //项目入口文件
  "files": [ //npm publish的时候包括的文件
    "lib",
    "bin"
  ],
  "scripts": {},
  "bin": "bin/zce-pages.js", //脚手架执行文件
  "renovate": {
    "extends": [
      "zce"
    ]
  },
  "standard": {
    "env": [
      "jest"
    ]
  },
  "dependencies": { //开发环境,生产环境的依赖
    "@babel/core": "^7.18.2",
    "@babel/preset-env": "^7.18.2",
    "browser-sync": "^2.27.10",
    "del": "^6.1.1",
    "gulp": "^4.0.2",
    "gulp-babel": "^8.0.0",
    "gulp-clean-css": "^4.3.0",
    "gulp-htmlmin": "^5.0.1",
    "gulp-if": "^3.0.0",
    "gulp-imagemin": "^7.0.0",
    "gulp-load-plugins": "^2.0.1",
    "gulp-sass": "^4.0.0",
    "gulp-swig": "^0.9.1",
    "gulp-uglify": "^3.0.2",
    "gulp-useref": "^5.0.0",
    "jquery": "3.4.1",
    "popper.js": "1.16.1",
    "sass": "^1.52.1"
  },
  "devDependencies": { //开发环境的依赖
    "gulp-imagemin": "^8.0.0",
    "jest": "27.5.1",
    "standard": "16.0.4"
  },
  "engines": {
    "node": ">=14"
  },
  "publishConfig": {
    "registry": "https://registry.npmjs.org"
  },
  "private": false 
}
  1. 在gitee/github上新建仓库,把地址和本地的脚手架项目zce-pages-lulu连接,并且发布

  2. 发布zce-pages-lulu到npm

  • registry记得切到npm
  • 登录npm
npm login
  • 输入账号,密码,邮箱及一次性密码后,发布项目
npm publish
  1. 项目内使用
  • cd到项目内后,直接在项目内安装,如果刚发布,国内淘宝镜像还没有更新,建议registry切换到npm,进行下载,运行以下命令安装
  yarn add zce-pages-lulu //zce-pages-lulu 需要换成你的脚手架名称
  • 执行相应命令即可
  yarn zce-pages-lulu clean//zce-pages-lulu 需要换成你的脚手架名称
  yarn zce-pages-lulu develop//zce-pages-lulu 需要换成你的脚手架名称
  yarn zce-pages-lulu build//zce-pages-lulu 需要换成你的脚手架名称