Gulp

作者: 浅忆_0810 | 来源:发表于2020-12-29 22:36 被阅读0次

    1. Gulp

    1. 初始化package.json文件

      yarn init # or npm init
      
    2. 安装gulp模块

      yarn add gulp --dev
      
    3. 在项目根目录下创建gulpfile.js入口文件,在里面定义一些需要gulp执行的构建任务


    2. 基本使用

    /*
      gulpfile.js
      gulp 的入口文件
      gulp 的任务函数都是异步的
    */
    // 可以通过调用回调函数标识任务完成
    exports.foo = done => {
      console.log('foo task working~')
      done() // 标识任务执行完成
    }
    
    // default 是默认任务
    // 在运行可以省略任务名参数
    exports.default = done => {
      console.log('default task working~')
      done()
    }
    
    // 注意  v4.0 之前需要通过 gulp.task() 方法注册任务
    const gulp = require('gulp');
    
    gulp.task('bar', done => {
      console.log('bar task working~');
      done();
    });
    
    gulp-basis

    3. 组合任务

    const { series, parallel } = require('gulp');
    
    const task1 = done => {
      setTimeout(() => {
        console.log('task1 working~');
        done();
      }, 1000)
    }
    
    const task2 = done => {
      setTimeout(() => {
        console.log('task2 working~');
        done();
      }, 1000)  
    }
    
    const task3 = done => {
      setTimeout(() => {
        console.log('task3 working~');
        done();
      }, 1000); 
    }
    
    // 让多个任务按照顺序依次执行
    exports.foo = series(task1, task2, task3);
    
    // 让多个任务同时执行
    exports.bar = parallel(task1, task2, task3);
    
    series parallel

    4. 异步任务

    exports.callback = done => {
      console.log('callback task~');
      done();
    }
    
    exports.callback_error = done => {
      console.log('callback task');
      done(new Error('task failed'));
    }
    
    exports.promise = () => {
      console.log('promise task');
      // resolve()中不需要传入值,因为gulp会自动忽略
      return Promise.resolve();
    }
    
    // or
    exports.promise_error = () => {
      console.log('promise task')
      return Promise.reject(new Error('task failed'))
    }
    
    const timeout = time => {
      return new Promise(resolve => {
        setTimeout(resolve, time)
      })
    }
    exports.async = async () => {
      await timeout(1000);
      console.log('async task');
    }
    
    exports.stream = () => {
      const readStream = fs.createReadStream('package.json');
      const writeStream = fs.createWriteStream('temp.txt');
      readStream.pipe(writeStream);
      return readStream;
    }
    
    // => 等价于
    exports.stream = () => {
      const readStream = fs.createReadStream('package.json');
      const writeStream = fs.createWriteStream('temp.txt');
      readStream.pipe(writeStream);
      readStream.on('end', () => {
        done();
      });
    }
    

    5. Gulp核心工作原理

    读取流 -> 插件转换流做处理 -> 写入流
    
    yarn add gulp-clean-css gulp-rename --dev
    
    const { src,dest } = require('gulp');
    const cleanCSS = require('gulp-clean-css');
    const rename = require('gulp-rename');
    
    exports.default = () => {
      return src('src/*.css')
        .pipe(cleanCSS()) // 转换为压缩后的代码
        .pipe(rename({ extname: '.min.css' })) // 重命名扩展名
        .pipe(dest('dist'))
    }
    

    6. 样式编译任务

    6.1 对所有 scss文件进行拷贝

    const { src,dest } = require('gulp');
    const rename = require('gulp-rename');
    
    const style = () => {
      return src('src/assets/styles/*.scss', { base: 'src' }) // 第二个参数:转换的基本路径
        .pipe(dest('dist'))
    }
    
    module.exports = {
      style
    }
    

    6.2 安装gulp-sass对style进行转换

    yarn add gulp-sass --dev
    

    安装gulp-sass时,会安装node-sass

    解决办法

    const sass = require('gulp-sass');
    const style = () => {
      return src('src/assets/styles/*.scss', { base: 'src' }) // 第二个参数:转换的基本路径
        .pipe(sass({ outputStyle: 'expanded' })) // expanded: 将转换后的样式代码完全展开
        .pipe(dest('dist'))
    }
    

    注意:sass模块工作时会忽略以_开头的文件,因此这些文件不会被转换


    7. js编译任务

    7.1 对所有 js文件进行拷贝

    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(dest('dist'))
    }
    
    module.exports = {
      style,
      script
    }
    

    7.2 安装gulp-babel对js进行转换

    const babel = require('gulp-babel');
    
    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(babel())
        .pipe(dest('dist'))
    }
    

    注意:这里命令行使用yarn gulp script后会报Error: Cannot find module '@babel/core'

    因为 babel安装时候不像gulp-sass那样自动安装了css的转换模块node-sass

    babel只是一个转换平台,我们需要自己去安装转换模块

    7.3 安装@babel/core转换模块和@/babel/preset-env(会将ECMAScript全部的新特性进行转换)

    yarn add @babel/core @babel/preset-env --dev
    

    7.4 对js进行转换

    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('dist'))
    }
    

    8. HTML模板文件编译任务

    8.1 安装模板引擎转换插件

    # 这里使用的是swig模板
    yarn add gulp-swig --dev
    

    8.2 对html进行转换

    const swig = require('gulp-swig');
    
    const data = {
      menus: [
        {
          name: 'Home',
          icon: 'aperture',
          link: 'index.html'
        },
        {
          name: 'Contact',
          link: '#',
          children: [
            {
              name: 'About',
              link: 'https://weibo.com/zceme'
            }
          ]
        }
      ],
      pkg: require('./package.json'),
      date: new Date()
    }
    
    const page = () => {
      // 如果要转换的 html 目录不只在src下,可以使用 src/**/*.html
      return src('src/*.html', { base: 'src' })
        .pipe(swig({ data }))
        .pipe(dest('dist'))
    }
    
    module.exports = {
      style,
      script,
      page
    }
    

    9. 组合任务

    const { src,dest,parallel } = require('gulp');
    
    // paralle 里的任务可以同时执行
    const compare = paralle(style, script, page);
    
    module.exports = {
      compare
    }
    

    10. 图片和字体文件编译任务

    10.1 安装gulp-imagemin

    yarn add gulp-imagemin --dev
    

    注意:这里可能会报一些 c++的二进制文件没安装成功

    解决办法

    10.2 对图片进行压缩

    const imagemin = require('gulp-imagemin');
    
    const image = () => {
      return src('src/assets/images/**', { base: 'src' })
        .pipe(imagemin())
        .pipe(dest('dist'))
    }
    

    10.3 对字体进行压缩

    const font = () => {
      return src('src/assets/fonts/**', { base: 'src' })
        .pipe(imagemin())
        .pipe(dest('dist'))
    }
    
    // paralle 里的任务可以同时执行
    const compare = parallel(style, script, page, image, font);
    

    11. 其它文件及文件清除编译任务

    11.1 对其它文件进行拷贝

    const extra = () => {
      return src('public/**', { base: 'public' })
        .pipe(dest('dist'))
    }
    
    const build = parallel(compare, extra);
    
    module.exports = {
      build
    }
    

    11.2 自动清除dist下的文件

    1. 安装 del
    yarn add del --dev
    
    2. 清除dist下的文件
    const { src,dest,parallel, series } = require('gulp');
    const del = require('del');
    
    const clean = () => {
      return del(['dist'])
    }
    
    // series 按顺序依次执行
    const build = series(clean, parallel(compare, extra));
    
    module.exports = {
      build
    }
    

    12. 自动加载插件

    12.1 安装gulp-load-plugins

    yarn add gulp-load-plugins --dev
    

    12.2 使用

    const loadPlugin = require('gulp-load-plugins');
    
    const plugins = loadPlugin();
    // 将所有通过 gulp-xx 引入的文件 可以全部替换成  plugins.xx
    
    // example
    const babel = require('gulp-babel');
    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('dist'))
    }
    
    // =>
    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('dist'))
    }
    

    13 热更新开发服务器

    13.1 安装browser-sync(支持修改代码后自动热更新到浏览器中)

    yarn add browser-sync --dev
    

    13.2 使用

    const browserSync = require('browser-sync');
    
    const bs = browserSync.create(); // 会自动创建一个开发服务器
    
    const serve = () => {
      bs.init({
        notify: false, // 取消右上角提示
        port: 2000, // 端口,默认 3000
        // open: false, // 是否自动打开浏览器
        files: 'dist/**', // 监听哪些文件改变后浏览器自动更新
        server: {
          baseDir: 'dist', // 网站根目录
          routes: {
            '/node_modules': 'node_modules' // 对打包后的 /node_modules 路径进行处理
          }
        }
      })
    }
    
    module.exports = {
      build,
      serve
    }
    

    14. 监视 src变化以及构建过程优化

    14.1 监视 src各文件变化

    const { src,dest,parallel, series, watch } = require('gulp');
    
    const serve = () => {
      watch('src/assets/styles/*.scss', style);
      watch('src/assets/scripts/*.js', script);
      watch('src/*.html', page);
      watch('src/assets/image/**', image);
      watch('src/assets/fonts/**', font);
      watch('public/**', extra);
    
      bs.init({
        notify: false,
        port: 2000,
        // open: false,
        files: 'dist/**',
        server: {
          baseDir: 'dist',
          routes: {
            '/node_modules': 'node_modules'
          }
        }
      })
    }
    

    14.2 构建优化

    const serve = () => {
      watch('src/assets/styles/*.scss', style);
      watch('src/assets/scripts/*.js', script);
      watch('src/*.html', page);
      /*
        watch('src/assets/image/**', image);
        watch('src/assets/fonts/**', font);
        watch('public/**', extra);
      */
      watch([
        'src/assets/image/**',
        'src/assets/fonts/**',
        'public/**'
      ], bs.reload);
    
      bs.init({
        notify: false,
        port: 2000,
        // open: false,
        files: 'dist/**',  // 下面介绍不使用 files 来监听
        server: {
          baseDir: ['dist','src','public'],
          routes: {
            '/node_modules': 'node_modules'
          }
        }
      })
    }
    
    const compare = parallel(style, script, page);
    
    // 上线之前执行的任务
    const build = series(clean, parallel(compare, extra, image, font));
    
    // 应该先编译脚本,样式等  在编译 serve
    const develop = series(compare, serve);
    
    module.exports = {
      clean,
      build,
      develop
    }
    
    // 注意:这部分不是优化,只是有些代码写法不是用 files监听,而是用的以下方式
    
    const style = () => {
      return src('src/assets/styles/*.scss', { base: 'src' }) // 第二个参数:转换的基本路径
        .pipe(plugins.sass({ outputStyle: 'expanded' })) // expanded: 将转换后的样式代码完全展开
        .pipe(dest('dist'))
        .pipe(bs.reload({ stream: true }))
    }
    
    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('dist'))
        .pipe(bs.reload({ stream: true }))
    }
    
    const page = () => {
      return src('src/*.html', { base: 'src' })
        .pipe(plugins.swig({ data }))
        .pipe(dest('dist'))
        .pipe(bs.reload({ stream: true }))
    }
    
    const serve = () => {
      watch('src/assets/styles/*.scss', style);
      watch('src/assets/scripts/*.js', script);
      watch('src/*.html', page);
      watch([
        'src/assets/image/**',
        'src/assets/fonts/**',
        'public/**'
      ], bs.reload);
    
      bs.init({
        notify: false,
        port: 2000,
        // open: false,
        server: {
          baseDir: ['dist','src','public'],
          routes: {
            '/node_modules': 'node_modules'
          }
        }
      })
    }
    

    15. useref文件引用处理

    15.1 安装gulp-userg

    yarn add gulp-useref --dev
    

    15.2 使用

    const useref = () => {
      return src('dist/*.html', { base: 'dist' })
        .pipe(plugins.useref({ searchPath: ['dist', '.'] })) // 将代码中的构建注释转换
        .pipe(dest('dist'))
    }
    
    module.exports = {
      clean,
      build,
      develop,
      useref
    }
    

    16. 文件压缩

    16.1 安装htmljscss压缩插件

    yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev
    

    16.2 安装gulp-if插件对不同文件类型进行判断

    yarn add gulp-if --dev
    

    16.3 使用

    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()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({ 
          collapseWhitespace: true,
          minifyCSS: true,
          minifyJS: true 
        })))
        .pipe(dest('release')) // 这里不能也写 'dist' 避免读写冲突
    }
    

    17. 重新规划构建过程

    // gulp 的入口文件
    const { src,dest,parallel, series, watch } = require('gulp');
    
    const loadPlugin = require('gulp-load-plugins');
    const plugins = loadPlugin();
    
    const del = require('del');
    const browserSync = require('browser-sync');
    
    const bs = browserSync.create();
    
    // 网页所需要的数据
    const data = {  }
    
    const clean = () => {
      return del(['dist', 'temp']) // temp: 临时生成的目录
    }
    
    const style = () => {
      return src('src/assets/styles/*.scss', { base: 'src' }) // 第二个参数:转换的基本路径
        .pipe(plugins.sass({ outputStyle: 'expanded' })) // expanded: 将转换后的样式代码完全展开
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true }))
    }
    
    const script = () => {
      return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true }))
    }
    
    const page = () => {
      return src('src/*.html', { base: 'src' })
        .pipe(plugins.swig({ data }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true }))
    }
    
    const image = () => {
      return src('src/assets/images/**', { base: 'src' })
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
    }
    
    const font = () => {
      return src('src/assets/fonts/**', { base: 'src' })
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
    }
    
    const extra = () => {
      return src('public/**', { base: 'public' })
        .pipe(dest('dist'))
    }
    
    const serve = () => {
      watch('src/assets/styles/*.scss', style);
      watch('src/assets/scripts/*.js', script);
      watch('src/*.html', page);
      /* watch('src/assets/image/**', image);
      watch('src/assets/fonts/**', font);
      watch('public/**', extra);
     */
      watch([
        'src/assets/image/**',
        'src/assets/fonts/**',
        'public/**'
      ], bs.reload);
    
      bs.init({
        notify: false,
        port: 2000,
        // open: false,
        // files: 'dist/**',
        server: {
          baseDir: ['temp','src','public'],
          routes: {
            '/node_modules': 'node_modules'
          }
        }
      })
    }
    
    const useref = () => {
      return src('temp/*.html', { base: 'dist' })
        .pipe(plugins.useref({ searchPath: ['dist', '.'] })) // 将代码中的构建注释转换
        // html js css
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({ 
          collapseWhitespace: true,
          minifyCSS: true,
          minifyJS: true 
        })))
        .pipe(dest('dist'))
    }
    
    const compare = parallel(style, script, page);
    
    // 上线之前执行的任务
    const build = series(
      clean, 
      parallel(
        series(compare, useref), 
        extra, 
        image, 
        font
      )
    );
    
    const develop = series(compare, serve);
    
    module.exports = {
      clean,
      build,
      develop
    }
    
    // package.json
    {
      "name": "gulp-cli",
      "version": "1.0.0",
      "main": "index.js",
      "license": "MIT",
      "scripts": {
        "clean": "gulp clean",
        "build": "gulp build",
        "develop": "gulp develop"
      },
      "dependencies": {
        "bootstrap": "4.4.1"
      },
      "devDependencies": {
        "@babel/core": "^7.12.3",
        "@babel/preset-env": "^7.12.1",
        "browser-sync": "^2.26.13",
        "del": "^6.0.0",
        "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.1.0",
        "gulp-load-plugins": "^2.0.5",
        "gulp-sass": "^4.1.0",
        "gulp-swig": "^0.9.1",
        "gulp-uglify": "^3.0.2",
        "gulp-useref": "^4.0.1"
      }
    }
    
    // .gitignore
    dist
    
    temp
    

    相关文章

      网友评论

        本文标题:Gulp

        本文链接:https://www.haomeiwen.com/subject/yfqubktx.html