使用 Gulp 完成项目的自动化构建

221 阅读3分钟

一、封装通用模块

初始化项目

  • 初始化 package.json
package init
  • gulp
yarn add gulp --dev
  • 集成gulp插件
yarn add gulp --dev
  • 本地服务器 browser-sync
yarn add gulp-load-plugins --dev
  • 清理编译的文件夹del
 yarn add del --dev
  • 编译sass
yarn add gulp-sass --dev
  • 编译ES+
yarn add @babel/core @babel/preset-env --dev

配置文件 gulpfile.js

// 本地服务器 安装browser-sync yarn add browser-sync --dev
// 安装gulp yarn add gulp --dev
// 安装 gulp-load-plugins、gulp-sass(处理Ssass)
// 安装del  yarn add del --dev  清理编译的文件夹
// 安装 @babel/core @babel/preset-env 编译JS
const broserSync = require('browser-sync')
const bs = broserSync.create() // 创建一个服务器
const { src, dest, watch, parallel, series } = require('gulp')
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins() // 新建一个插件
const cwd = process.cwd() // 工作目录
const del = require('del')
const config = {
    data: {
        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'),
        date: new Date()
    },
    build: {
        source: 'src', // 源文件夹
        dist: 'release', // 最终编译后存放的文件夹
        temp: '.temp', // 作为中间文件夹
        public: 'public', // 纯静态文件夹,
        paths: {
            styles: 'assets/styles/*.scss',
            scripts: 'assets/scripts/*.js',
            pages: '*.html',
            images: 'assets/images/**',
            fonts: 'assets/fonts/**'
        }
    }
}
// 结构配置文件
const { build: configBuild, data } = config
const { source, dist, temp, public, paths: { styles, scripts, pages, images, fonts } } = configBuild
// 获取读取流的公共部分
const getBase = (src) => {
    return { base: src, cmd: src }
}
// 创建编译styles下的scss的任务
const style = () => {
    return src(`${source}/${styles}`, getBase(source)) //读取文件流
    .pipe(plugins.sass({ outputStyle: 'expanded' })) // 压缩CSS
    .pipe(dest(temp)) // 写入流中, 写入到temp(半成品)目录下
    .pipe(bs.reload({ stream: true })) // 写入流变化, 重新加载资源
}
// 创建编译scripts下的js的任务
// babel编译使用babel的下一代ES 编译
const script = () => {
    return src(`${source}/${scripts}`, getBase(source))
    .pipe(plugins.babel({ presets: [ require('@babel/preset-env') ] }))
    .pipe(dest(temp)) // 写入到temp(半成品)目录下
    .pipe(bs.reload({ stream: true }))
}
// gulp-swig 编译EJS yarn add gulp-swig --dev
const page = () => {
    return src(`${source}/${pages}`, getBase(source))
    .pipe(plugins.swig({ // 编译EJS
        data, // 传参
        defaults: {
            cache: false
        }
    }))
    .pipe(dest(temp))
    .pipe(bs.reload({ stream: true }))
}

const image = () => {
  return src(`${source}/${images}`, getBase(source))
  .pipe(plugins.imagemin()) // 图片压缩
  .pipe(dest(dist)) // 只有最终生产编译时, 直接保存到dist, 开发阶段不需要编译
}
const font = () => {
  return src(`${source}/${fonts}`, getBase(source))
  .pipe(plugins.imagemin())
  .pipe(dest(dist)) // 只有最终生产编译时, 直接保存到dist, 开发阶段不需要编译
}
const extra = () => { // 拷贝所有文件
  return src('**', { base: public, cmd: public})
  .pipe(dest(dist))
}
// 开发服务器任务
const serve = () => {
  watch(`${source}/${styles}`, { cmd: src }, style) // 监听styles目录下文件改变, 改变就执行style任务
  watch(`${source}/${scripts}`, { cmd: src }, script) // 监听scripts目录下文件改变, 改变就执行style任务
  watch(`${source}/${pages}`, { cmd: src }, page) // 监听pages目录下文件改变, 改变就执行style任务
  watch([`${source}/${images}`, `${source}/${fonts}`], { cmd: src }, bs.reload) // 监听, 重新加载
  watch('**', { cmd: public }, bs.reload)
  bs.init({
    notify: false,
    port: 2080, // 端口
    open: false, // 启动服务器就打开浏览器
    server: {
      baseDir: [ temp, src, public ], // 依次按照目录顺序查找文件
      routes: {
        '/node_modules': 'node_modules'
      }
    }
  })
}
// gulp-useref这是一款可以将HTML引用的多个CSS和JS合并起来,减小依赖的文件个数,从而减少浏览器发起的请求次数
const useref = () => {
  return src(`${source}/${pages}`, getBase(source))
  .pipe(plugins.useref({ searchPath: [ temp, '.' ] })) // 从temp,.查找资源
  // HTML, JS, CSS 
  .pipe(plugins.if(/\.js$/, plugins.uglify()) // JS 代码压缩
  .pipe(plugins.if(/\.css$/, plugins.cleanCss())) // CSS 代码压缩
  .pipe(plugins.if(/\.html$/, plugins.htmlmin({ // html 代码压缩
    collapseWhitespace: true, // html展开空格
    minifyCSS: true,
    minifyJS: true
  })))
  .pipe(dest(dist)))
}
// 创建清理任务
const clean = () => {
  return del([dist, temp])
}
 // 编译任务 parallel 是并行执行顺序
 const compile = parallel(style, script, page)
 // 开发时执行的任务
 const develop = series(compile, serve)
 // 上线之前执行的任务
 const build = series(
   clean, // 清理文件夹
   image,
   font,
   extra,
   series(compile, useref) // 先编译好文件, 才能合并对应的资源
  )

module.exports = {
  develop,
    clean,
    build 
}

style 编译测试效果 yarn gulp style script 编译测试效果 yarn gulp script page 编译测试效果 yarn gulp page image 编译测试效果 yarn gulp image font 编译测试效果 yarn gulp font

  • 编译任务
 // 编译任务 parallel 是并行执行顺序
 const compile = parallel(style, script, page)
  • 开发服务器任务
//开发服务器任务
const serve = () => {
  watch(`${source}/${styles}`, { cmd: src }, style) // 监听styles目录下文件改变, 改变就执行style任务
  watch(`${source}/${scripts}`, { cmd: src }, script) // 监听scripts目录下文件改变, 改变就执行style任务
  watch(`${source}/${pages}`, { cmd: src }, page) // 监听pages目录下文件改变, 改变就执行style任务
  watch([`${source}/${images}`, `${source}/${fonts}`], { cmd: src }, bs.reload) // 监听, 重新加载
  watch('**', { cmd: public }, bs.reload)
  bs.init({
    notify: false,
    port: 2080, // 端口
    open: false, // 启动服务器就打开浏览器
    server: {
      baseDir: [ temp, dist, public ], // 依次按照目录顺序查找文件
      routes: {
        '/node_modules': 'node_modules'
      }
    }
  })
}
  • 开发时执行的任务
 // 开发时执行的任务
 const develop = series(compile, serve)
  • 上线之前执行的任务
 // 上线之前执行的任务
 const build = series(
   clean, // 清理文件夹
   image,
   font,
   extra,
   series(compile, useref) // 先编译好文件, 才能合并对应的资源
  )

配置package.json 的script

"scripts": {
    "clean": "gulp clean",
    "develop": "gulp develop",
    "build": "gulp build"
  }