最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Gulp4(二)——手撕一个gulp构建案例

    正文概述 掘金(顽皮的雪狐七七)   2020-12-27   509

    目录

    • Gulp案例
    • 自动化构建诉求
      • 样式编译
        • gulp-sass
        • gulp-less
      • 脚本编译
        • gulp-babel
      • 页面模板编译
        • gulp-swig
      • 图片和文字转换
        • gulp-imagemin
      • 其他原本文件输出
      • 清除文件
      • 自动加载插件
      • 热更新开发服务器
      • useref文件引用处理
      • html/css/js文件压缩
      • 对所有的插件和目录进行调整

    Gulp案例

    模板下载 gulp-pro-demo

    自动化构建诉求

    • 所有的scssless文件编译成css(scss中下划线开头的不会被编译)
    • 将所有的js文件中的ES6语法进行适配
    • html中的模板要进行编译
    • 图片和文字要进行压缩
    • 公共文件原封不动输出
    • 在输出文件之前要对之前的输出目录进行删除
    • 可以实现开发时浏览器热更新
    • 第三方文件引用处理
    • 对html/css/js文件进行压缩
    • 导出内容发布到dist文件夹

    样式编译

    关于样式这里的操作我们需要将所有的scssless文件编译成css文件,所以下面进行具体操作。

    gulp-sass

    sass转化成css

    1. 下载模块npm install gulp-sass
    2. gulpfile.js里面写
    const { src, dest } = require('gulp')
    // 引入sass模块
    const sass = require('gulp-sass')
    
    // 创建style任务
    const style = () => {
      // 输入scss的文件路径,并且指定根目录是src,在dist输出目录中,以src目录的结构输出
      return src('src/assets/styles/*.scss', { base: 'src'})
        // 进行sass向css转换,并且指定的样式是完全展开
        // (如果不设置完全展开,那么默认css样式的右花括号不折行)
        .pipe(sass({ outputStyle: 'expanded' }))
        // 输出到dist文件夹
        .pipe(dest('dist'))
    }
    
    module.exports = {
      style
    }
    
    1. 在命令行输入gulp style可以看到样式已经编译成css文件
    gulp-less

    less转化成css

    1. 下载模块npm install gulp-less
    2. 进行私有前缀匹配,下载less插件npm install less-plugin-autoprefix
    3. gulpfile.js里面写
    const { src, dest} = require('gulp')
    // 引入less模块
    const less = require('gulp-less')
    // 引入less插件,私有前缀兼容
    const LessAutoprefix = require('less-plugin-autoprefix')
    const autoprefix = new LessAutoprefix({browsers: ["last 2 versions"]});
    
    const lessStyle = () => {
      return src('src/assets/styles/*.less', { base: 'src'})
      // 进行less向css转换,并且引用插件私有前缀适配
      .pipe(less({
        plugins: [autoprefix]
      }))
      // 输出到dist文件夹
      .pipe(dest('dist'))
    }
    
    module.exports = {
      lessStyle
    }
    
    1. 命令行写gulp lessStyle可以看到文件进行了编译
    /* hello.less */
    @bg : #000;
    @fontColor: #fff;
    
    .main{
      background-color: @bg;
      color: @fontColor;
      transform: translateX(30px);
    }
    
    
    /* hello.css */
    .main {
      background-color: #000;
      color: #fff;
      -webkit-transform: translateX(30px);
              transform: translateX(30px);
    }
    
    

    脚本编译

    我们还需要将ES6的语法进行编译

    gulp-babel
    1. 下载模块npm install gulp-babel
    2. 使用还需要下载插件npm install @babel/core @babel/preset-env
    3. gulpfile.js里面写
    const { src, dest} = require('gulp')
    // 引入babel模块
    const babel = require('gulp-babel')
    
    // 创建babel任务
    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src'})
      // 使用babel转换ES6语法
      .pipe(babel({
        // 插件集合,最新特性的全部打包,不写这个转换没有效果
        presets: ['@babel/preset-env']
      }))
      // 输出到dist文件夹
      .pipe(dest('dist'))
    }
    
    module.exports = {
      script
    }
    
    1. 命令行写gulp script可以看到文件进行了编译
    /* 编译前main.js */
    // TODO: site logics
    
    $(($) => {
      const $body = $('html, body')
    
      $('#scroll_top').on('click', () => {
        $body.animate({ scrollTop: 0 }, 600)
        return false
      })
    })
    
    
    
    /* 编译后main.js */
    "use strict";
    
    // TODO: site logics
    $(function ($) {
      var $body = $('html, body');
      $('#scroll_top').on('click', function () {
        $body.animate({
          scrollTop: 0
        }, 600);
        return false;
      });
    });
    
    

    页面模板编译

    gulp-swig
    1. 下载模块npm install gulp-swig
    2. gulpfile.js里面写
    const { src, dest} = require('gulp')
    // 引入swig模块
    const swig = require('gulp-swig')
    
    // 创建模板引擎任务
    const page = () => {
      // 通配符匹配src下main的所有子目录中的html
      return src('src/**/*.html', { base: 'src' })
        .pipe(swig())
        .pipe(dest('dist'))
    }
    
    module.exports = {
      page
    }
    
    1. 命令行写gulp page可以看到文件进行了编译
    2. 可以添加固定的参数,也可以加一个json文件去写项目长用常数参数
    const data = {
        a: 1,
        b: 2
    }
    
    const page = () => {
      return src('src/**/*.html', { base: 'src' })
        // 通过参数传递进去
        .pipe(swig({data: data}))
        .pipe(dest('dist'))
    }
    

    图片和文字转换

    gulp-imagemin

    这个插件可以压缩图片,字体文件如果是svg也可以进行压缩

    1. 下载模块npm i gulp-imagemin --save-dev
    1. gulpfile.js里面写
    const { src, dest} = require('gulp')
    // 引入imagemin模块
    const imagemin = require('gulp-imagemin');
    
    // 图片压缩任务
    const image = () => {
      // 匹配images下面的所有文件
      return src('src/assets/images/**', { base: 'src' })
        .pipe(imagemin())
        .pipe(dest('dist'))
    }
    
    // 图片压缩任务
    const font = () => {
      // 匹配images下面的所有文件
      return src('src/assets/fonts/**', { base: 'src' })
        .pipe(imagemin())
        .pipe(dest('dist'))
    }
    
    module.exports = {
      image,
      font
    }
    
    1. 命令行写gulp image可以看到文件进行了压缩,图片压缩26.5%
    gulp image
    # Using gulpfile E:\professer\Gulp\gulpfile.js
    # Starting 'image'...
    # gulp-imagemin: Minified 2 images (saved 22.8 kB - 26.5%)
    # Finished 'image' after 985 ms
    
    1. 命令行写gulp font可以看到文字的svg进行了压缩,其他的不能被压缩的文件原封不动被输出
    gulp font
    # Using gulpfile E:\professer\Gulp\gulpfile.js
    # Starting 'font'...
    # gulp-imagemin: Minified 1 image (saved 679 B - 5.9%)
    # Finished 'font' after 503 ms
    

    其他原本文件输出

    项目中都有public目录,这些存放一些静态的公共目录,直接输出到dist文件即可。

    // 将public的文件进行额外输出
    const extra = () => {
      return src('public/**', { base: 'pubilc' })
        .pipe(dest('dist'))
    }
    

    清除文件

    在编译输出文件之前,需要把之前的目录删掉,使用del模块进行操作。这个不是gulp插件,但是因为其返回一个promise对象,所以在gulp中也可以使用。

    1. 下载模块npm i del --save-dev

    2. gulpfile.js里面写

    const { src, dest, parallel, series } = require('gulp')
    // 引入清除文件模块
    const del = require('del')
    
    const clean = () => {
      return del(['dist'])
    }
    
    module.exports = {
      clean
    }
    
    1. 命令行写gulp clean可以把对应文件进行删除

    自动加载插件

    上面引用了那么多的模块,那么需要安装一个自动加载插件的模块,可以减少很多代码

    1. 下载模块npm i gulp-load-plugins --save-dev
    2. gulpfile.js里面写
    const { src, dest, parallel, series } = require('gulp')
    // 引入加载文件模块
    const loadPlugins = require('gulp-load-plugins')
    
    // 调用方法,也可以引用的时候直接调用
    // const plugins = require('gulp-load-plugins')()
    const plugins = loadPlugins()
    
    // 输出结构可以看到
    console.log(plugins)
    /* 
    默认匹配gulp-后面所有的插件
    如果有gulp-clean-css的后面采用驼峰命名为键
    这些模块在使用的时候必须都安装好
    {
      babel: [Getter],
      cleanCss: [Getter],
      imagemin: [Getter],
      less: [Getter],
      rename: [Getter],
      sass: [Getter],
      swig: [Getter]
    }
    */
    
    // 不是gulp开头的要单独安装,或者修改loadPlugins的匹配规则
    const LessAutoprefix = require('less-plugin-autoprefix')
    const autoprefix = new LessAutoprefix({browsers: ["last 2 versions"]});
    
    // 创建sass任务
    const style = () => {
      return src('src/assets/styles/*.scss', { base: 'src'})
        // 之后使用的时候就用plugins点出来即可
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest('dist'))
    }
    
    // 创建less任务
    const lessStyle = () => {
      return src('src/assets/styles/*.less', { base: 'src'})
      .pipe(plugins.less({
        plugins: [autoprefix]
      }))
      .pipe(dest('dist'))
    }
    
    
    // 创建babel任务
    const script = () => {
      ...
    }
    
    // 创建模板引擎任务
    const page = () => {
      ...
    }
    
    // 图片压缩任务
    const image = () => {
      ...
    }
    
    // 图片压缩任务
    const font = () => {
     ...
    }
    

    热更新开发服务器browser-sync

    当我们修改的时候,这个插件可以让我们直接看到浏览器刷新

    1. 下载模块npm install browser-sync --save-dev
    2. gulpfile.js里面写
    const { src, dest, parallel, series } = require('gulp')
    // 引入开发服务器模块
    const browserSync = require('browser-sync')
    
    // 使用create方法会自动创建一个开发服务器
    const bs = browserSync.create()
    
    // 创建服务任务
    const serve = () => {
      // 进行初始化,里面可以指定一些配置
      bs.init({
        // 设置开屏右上角链接提示:false去掉
        notify: false,
        // 端口,默认3000
        port: 2080,
        // 是否会自动打开浏览器:false是关闭,默认是开启
        // open: false,
        // 启动过后监听的文件,如果文件有修改就主动刷新
        files: 'dist/*',
        // 核心配置
        server: {
          // 网站根目录
          baseDir: 'dist',
          // 优先于baseDir,会先匹配这个配置,没有就会去baseBir中获取,如果引用的css,js文件中有不在dist文件夹里面的,可以匹配这个。如果没有可以不用写
          routes: {
            '/node_modules': 'node_modules'
          }
        }
      })
    }
    
    module.exports = {
      serve
    }
    
    1. 使用命令行执行gulp serve,可以看到浏览器自动执行,而且修改dist下面的文件,会自动热更新。
    2. 是监听dist文件,但是我们需要在开发的目录下面,修改之后自动编译文件再更新到浏览器。需要用到gulp的方法watch
    3. gulpfile.js中这样写
    const { src, dest, parallel, series, watch } = require('gulp')
    
    const browserSync = require('browser-sync')
    const bs = browserSync.create()
    
    const serve = () => {
      // 监听文件变化并执行对应任务
      watch('src/assets/styles/*.scss', style)
      watch('src/assets/styles/*.less', lessStyle)
      watch('src/assets/scripts/*.js', script)
      watch('src/**/*.html', page)
      
      // 开发阶段不需要每一次修改都压缩文件,这些只是修改的时候重新加载即可
      watch([
        'src/assets/images/**',
        'src/assets/fonts/**',
        'public/**'
      ], bs.reload)
      
      
      bs.init({
        notify: false,
        port: 2080,
        files: 'dist/*',
        server: {
          // 网站根目录,多个的时候写成数组,如果路径找不到会依此去路径中寻找
          baseDir: ['dist', 'src', 'public'],
          routes: {
            '/node_modules': 'node_modules'
          }
        }
      })
    }
    

    当然更多的是这么用的,在任务后面手动调用更新,就可不用写init里面的files

    // 创建sass任务
    const style = () => {
      return src('src/assets/styles/*.scss', { base: 'src'})
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        .pipe(dest('dist'))
        // 以流的方式往浏览器推,每次任务执行完,都自动reload一下
        .pipe(bs.reload({ stream: true }))
    }
    
    

    useref文件引用处理

    如果项目中有引入dist里面没有的文件,上线会有问题,所以需要进行处理

    1. 下载模块npm i gulp-useref --save-dev
    2. gulpfile.js里面写
    const { src, dest } = require('gulp')
    const loadPlugins = require('gulp-load-plugins')
    const plugins = loadPlugins()
    
    const useref = () => {
      // dist当中的所有文件注释,进行打包压缩
      return src('dist/*.html', { base: 'dist' })
        // 文件寻找路径依此进行查找,找到之后根据写的文件注释进行打包
        .pipe(plugins.useref({ searchPath: ['dist', '.']}))
        // 读和写如果是一个文件夹可能会有问题
        .pipe(dest('release'))
    }
    
    module.exports = {
      useref
    }
    
    1. 命令行写gulp useref可以把对应注释文件进行了打包处理。并且在release文件夹中出现了vender.jsvender.css的一系列打包文件
    <!-- build:css assets/styles/vendor.css -->
    <link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
    <!-- endbuild -->
    
    <!-- build:css assets/styles/main.css -->
    <link rel="stylesheet" href="assets/styles/main.css">
    <!-- endbuild -->
    
    <!-- build:js assets/scripts/vendor.js -->
    <script src="/node_modules/jquery/dist/jquery.js"></script>
    <script src="/node_modules/popper.js/dist/umd/popper.js"></script>
    <script src="/node_modules/bootstrap/dist/js/bootstrap.js"></script>
    <!-- endbuild -->
    
    <!-- build:js assets/scripts/main.js -->
    <script src="assets/scripts/main.js"></script>
    <!-- endbuild -->
    

    变成了

    <link rel="stylesheet" href="assets/styles/vendor.css">
    <link rel="stylesheet" href="assets/styles/main.css">
    <script src="assets/scripts/vendor.js"></script>
    <script src="assets/scripts/main.js"></script>
    

    但是这些都是未压缩过的文件,还需要进行压缩操作

    html/css/js文件压缩

    上面生成的文件都是未压缩过的,所以下面要进行压缩

    1. 安装压缩插件压缩html/css/js 文件,npm i gulp-htmlmin gulp-uglify gulp-clean-css --save-dev
    2. 为了进行区分文件的不同,还需要安装npm i gulp-if --save-dev
    3. gulpfile.js里面写
    const { src, dest } = require('gulp')
    const loadPlugins = require('gulp-load-plugins')
    const plugins = loadPlugins()
    
    const useref = () => {
      return src('dist/*.html', { base: 'dist' })
        .pipe(plugins.useref({ searchPath: ['dist', '.']}))
        // 在这里会生成html js css三种类型的文件,需要对这三种文件进行压缩操作
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        // 不加collapseWhitespace只是压缩一些空格,加上会把这行等空白字符都压缩
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({ 
          collapseWhitespace: true,
          // 行内样式里面的css和js用这个参数可以进行压缩
          minifyCSS: true,
          minifyJS: true
         })))
        .pipe(dest('release'))
    }
    
    module.exports = {
      useref
    }
    
    1. 命令行写gulp useref可以把所有的文件都压缩完成

    对所有的插件和目录进行调整

    • 我们的目标是在src目录下开发,使用dist目录上线,中间的转换利用临时目录temp保存
    • 有一个开发环境的任务develop,有一个生产环境的任务build
    • develop任务需要编译cssjstemplate,还需要本地起服务进行热更新
    • build任务需要编译cssjstemplate,需要压缩css,js,template,image,font和其他文件,需要外联文件进行打包压缩
    • 最后在package.json中注册script,直接用命令行就可以运行

    下面是完整的代码

    // gulpfile.js
    // src 输入、dest 输出、parallel 并行、series 串行、watch 监听
    const { src, dest, parallel, series, watch } = require('gulp')
    
    // 引入清除文件模块
    const del = require('del')
    // if有less引入兼容适配
    const LessAutoprefix = require('less-plugin-autoprefix')
    // 引入浏览器监听服务模块
    const browserSync = require('browser-sync')
    // 引入gulp插件管理模块
    const loadPlugins = require('gulp-load-plugins')
    const plugins = loadPlugins()
    
    // 使用create方法会自动创建一个开发服务器
    const bs = browserSync.create()
    const autoprefix = new LessAutoprefix({browsers: ["last 2 versions"]});
    
    // 创建清除文件任务
    const clean = () => {
      // 每次执行的时候,先把之前的dist目录删除,再删除临时目录temp
      return del(['dist', 'temp'])
    }
    
    // 创建sass任务
    const style = () => {
      // 输入scss的文件路径,并且指定根目录是src,在dist输出目录中,以src目录的结构输出
      return src('src/assets/styles/*.scss', { base: 'src'})
        // 进行sass向css转换,并且指定的样式是完全展开
        // (如果不设置完全展开,那么默认css样式的右花括号不折行)
        .pipe(plugins.sass({ outputStyle: 'expanded' }))
        // 输出到temp临时文件夹
        .pipe(dest('temp'))
        // 以流的方式往浏览器推
        .pipe(bs.reload({ stream: true }))
    }
    
    // 创建less任务
    const lessStyle = () => {
      return src('src/assets/styles/*.less', { base: 'src'})
      // 进行sass向css转换,并且指定的样式是完全展开
      // (如果不设置完全展开,那么默认css样式的右花括号不折行)
      .pipe(plugins.less({
        plugins: [autoprefix]
      }))
      // 输出到temp临时文件夹
      .pipe(dest('temp'))
      // 以流的方式往浏览器推
      .pipe(bs.reload({ stream: true }))
    }
    
    
    // 创建babel任务
    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
      // 使用babel转换ES6语法
      .pipe(plugins.babel({
        // 插件集合,最新特性的全部打包,不写这个转换没有效果
        presets: ['@babel/preset-env']
      }))
      // 输出到temp临时文件夹
      .pipe(dest('temp'))
      // 以流的方式往浏览器推
      .pipe(bs.reload({ stream: true }))
    }
    
    // 创建模板引擎任务
    const page = () => {
      // 通配符匹配src下main的所有子目录中的html
      return src('src/**/*.html', { base: 'src' })
        //swig因为模板缓存的关系无法热更新,所以需要默认设置里面关闭缓存
        .pipe(plugins.swig({defaults: { cache: false }}))
        // 不需要进行临时文件夹中操作
        .pipe(dest('temp'))
        // 以流的方式往浏览器推
        .pipe(bs.reload({ stream: true }))
    }
    
    // 图片压缩任务
    const image = () => {
      // 匹配images下面的所有文件
      return src('src/assets/images/**', { base: 'src' })
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
    }
    
    // 图片压缩任务
    const font = () => {
      // 匹配images下面的所有文件
      return src('src/assets/fonts/**', { base: 'src' })
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
    }
    
    // 将public的任务进行额外输出
    const extra = () => {
      return src('public/**', { base: 'pubilc' })
        .pipe(dest('dist'))
    }
    
    // 创建服务任务
    const serve = () => {
      // 监听文件变化并执行对应任务,写这个就不用写bs.reload()了
      watch('src/assets/styles/*.scss', style)
      watch('src/assets/styles/*.less', lessStyle)
      watch('src/assets/scripts/*.js', script)
      watch('src/**/*.html', page)
      // 开发阶段不需要每一次修改都压缩文件,这些只是修改的时候重新加载即可
      watch([
        'src/assets/images/**',
        'src/assets/fonts/**',
        'public/**'
      ], bs.reload)
      
      // 进行初始化
      bs.init({
        // 设置开屏右上角链接提示:false去掉
        notify: false,
        // 端口
        port: 2080,
        // 是否会自动打开浏览器:false是关闭
        // open: false,
        // 启动过后监听的文件,如果有修改就主动刷新,有reload就不需要这个files配置
        // files: 'temp/*',
        // 核心配置
        server: {
          // 网站根目录,多个的时候写成数组,如果路径找不到会依此去路径中寻找
          // 文件先从temp中寻找
          baseDir: ['temp', 'src', 'public'],
          // 优先于baseDir,会先匹配这个配置,没有就会去baseBir中获取
          routes: {
            '/node_modules': 'node_modules'
          }
        }
      })
    }
    
    // 根据文件注释打包外联文件并且产出代码进行压缩任务
    const useref = () => {
      // dist当中的所有文件注释,进行打包压缩
      return src('temp/*.html', { base: 'temp' })
        // 文件寻找路径依此进行查找
        .pipe(plugins.useref({ searchPath: ['temp', '.']}))
        // 在这里会生成html js css三种类型的文件,需要对这三种文件进行压缩操作
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        // 不加collapseWhitespace只是压缩一些空格,加上会把这行等空白字符都压缩
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({ 
          collapseWhitespace: true,
          // 行内样式里面的css和js用这个参数可以进行压缩
          minifyCSS: true,
          minifyJS: true
         })))
        // 不要和dist一个目录,边读边写会有问题
        .pipe(dest('dist'))
    }
    
    // 执行编译的组合任务
    const compile = parallel(style, lessStyle, script, page)
    // 生产环境时候的构建任务
    /* - 先删除所有的文件夹
       - 下面的东西都可以并行,但是其中应该先编译sass,less,es6,template到temp临时目录,然后再压缩到dist目录
       - 图片、文字和其他的东西可以直接放到dist目录下
    */
    const build = series(
      clean, 
      parallel(
        series(compile, useref),
        image, 
        font, 
        extra
        )
      )
    
    // 开发时候的构建任务
    // 只需要编译之后发布到本地服务器上即可
    const develop = series(compile, serve)
    
    // 暴露开发和生产打包的任务命令
    module.exports = {
      clean, // 删除文件可以暴露
      build,
      develop
    }
    

    package.json中注册一下命令

    //package.json
    {
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "clean": "gulp clean",
        "build": "gulp build",
        "develop": "gulp develop"
      }
    }
    
    

    在命令行中直接运行npm run buildnpm run develop即可。然后在.gitignore中把disttemp目录加上提交忽略。


    起源地下载网 » Gulp4(二)——手撕一个gulp构建案例

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元