欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

自动化构建的学习应用—Gulp

程序员文章站 2022-03-23 11:10:36
Gulp的基本使用通过导出函数成员的方式定义任务, 默认执行default 任务yarn add gulp –dev//gulp的入口文件exports.foo = done => { console.log('foo task working~') done() //标识任务完成}exports.default = done => { console.log("default~~~~~"); done()};// gulp4.0之前的写法...

Gulp的基本使用
通过导出函数成员的方式定义任务, 默认执行default 任务

yarn add gulp –dev
//gulp的入口文件
exports.foo = done => {
    console.log('foo task working~')
    done() //标识任务完成
}

exports.default = done => {
    console.log("default~~~~~");
    done()
};

// gulp4.0之前的写法
// const gulp=reguire('gulp');
// gulp.task('bar',done=>{
//     console.log('bar working~')
//     done()
// })

Gulp创建组合任务

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);

自动化构建的学习应用—Gulp
foo任务会依次执行task1,task2,task3.
Series是串行的任务
Parallel是并行的任务

Gulp异步任务的三种方式
返回promise
返回流的方式
当从任务(task)中返回 stream、promise、event emitter、child process 或 observable 时,成功或错误值将通知 gulp 是否继续执行或结束。如果任务(task)出错,gulp 将立即结束执行并显示该错误。
当使用 series() 组合多个任务(task)时,任何一个任务(task)的错误将导致整个任务组合结束,并且不会进一步执行其他任务。当使用 parallel() 组合多个任务(task)时,一个任务的错误将结束整个任务组合的结束,但是其他并行的任务(task)可能会执行完,也可能没有执行完。

const { series, parallel } = require("gulp");
const fs = require('fs')

exports.task_error = (done) => {
    console.log("task1...");
    // 任务出错 后续的任务不会执行
    // 如果任务出错,就将错误放在回调函数 done 中
  done(new Error('任务出错...'));
};

const time = (time) => {
    return new Promise(resolve =>{
        setTimeout(resolve, time)
    })
    
}
// 异步任务
exports.promise  = () => {
    // 执行 一个promise 的 resolve 状态也可以结束任务
  return time(1000)
};

// node 8+  可以使用  async/await   async 会隐式返回 promise  所以可以不用写return
exports.promise_async  = async () => {
    await time(4000)
    console.log('promise_async 任务完成...');
};


exports.promise_error  = () => {
    console.log('promise_error.........');
    // 返回 一个promise 的 reject 代表任务出错
    return Promise.reject(new Error('promise_error...'))
};


exports.stream  = () => {
    const readSteam = fs.createReadStream('./package.json')
    const writeSteam = fs.createWriteStream('./tem.txt')
    readSteam.pipe(writeSteam)
    // 一定要返回 流 不然会报错(任务未完成):  The following tasks did not complete:
    return readSteam
};

// 流的异步原理: 它自己监听的了流的 end 事件
exports.streamFunc  = (done) => {
    const readSteam = fs.createReadStream('./package.json')
    const writeSteam = fs.createWriteStream('./tem.txt')
    readSteam.pipe(writeSteam)

    readSteam.on('end', ()=>{
        done()
    })
    return readSteam
};

Gulp 构建过程核心工作原理
读取出来, 转换, 写入其他位置

const fs = require("fs");
const { Transform } = require("stream");
// 模拟 gulp 的原理:  读取流 => 转换流  => 写入流
exports.default = () => {
  const read = fs.createReadStream("normalize.css");

  // 转换流
  const transform = new Transform({
    transform(chunk, encoding, callback) {
      const input = chunk.toString();
      //  所有换行去除, 所有注释去除
            const output = input.replace(/\s+/g, "").replace(/\/\*.+?\*\//g, "");
            callback(null, output)
    },
  });
  const write = fs.createWriteStream("normalize.min.css");
  read.pipe(transform).pipe(write);
  return read;
};

自动化构建的学习应用—Gulp
文件操作API + 插件的使用

yarn add gulp-clean-css --dev
yarn add gulp-rename --dev 
const { src, dest } = require("gulp");
const cleanCss = require("gulp-clean-css");
const rename = require("gulp-rename");
// 模拟 gulp 的原理:  读取流 => 转换流  => 写入流
exports.default = () => {
  return (
    src("src/*.css")
      // 压缩 css  
      .pipe(cleanCss())
      // 后缀重命名 
      .pipe(rename({ extname: ".min.css" }))
      .pipe(dest("dist"))
  );
};

自动化构建的学习应用—Gulp
Gulp 案例
ps: 如果你yarn 就是下载不了包的话 ,可以换用npm \ cnpm

yarn add gulp --dev
// 处理 sass
yarn add gulp-sass --dev 
// 处理 es6+
yarn add gulp-babel @babel/core @babel/preset-env --dev 
// 模版引擎
yarn add gulp-swig --dev
// 图片处理
yarn add gulp-imagemin --dev
// 自动加载gulp插件 解决文件顶部插件引入很多,导致代码比较繁杂的问题
 yarn add gulp-load-plugins --dev 
 // 清除文件 
 yarn add del --dev 
 // 开发服务器  支持HMR
 yarn add browser-sync --dev 
 // 处理文件引用关系
 yarn add gulp-useref --dev 
 // 压缩文件
 yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev 
 // 判断 流的类型
 yarn add gulp-if --dev 
 
 
 项目启动的其他依赖
 yarn add bootstrap jquery popper.js 

grupfile.js

样式编译
scss 转 css
转 css 时 保留文件路径
输出到 dist 目录

const { src, dest } = require("gulp");
const sass = require("gulp-sass");

// scss 转 css
const style = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/styles/*.scss", { base: "src" })
      //  scss 处理 并保留花括号换行
      .pipe(sass({ outputStyle: "expanded" }))
      .pipe(dest("dist"))
  );
};

module.exports = {
  style,
};

测试:
yarn gulp style

脚本编译

const { src, dest } = require("gulp");
const sass = require("gulp-sass");
const babel = require('gulp-babel')

// scss 转 css
const style = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/styles/*.scss", { base: "src" })
      //  scss 处理 并保留花括号换行
      .pipe(sass({ outputStyle: "expanded" }))
      .pipe(dest("dist"))
  );
};

const script = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/scripts/*.js", { base: "src" })
      //  ES6+ 处理 注意这里要提供 babel 预设, 不然就不转换
      .pipe(babel({ presets: ['@babel/preset-env'] }))
      .pipe(dest("dist"))
  );
};

module.exports = {
    style,
    script
};

测试:
yarn gulp script

页面模板编译

const { src, dest, parallel } = require("gulp");
const sass = require("gulp-sass");
const babel = require("gulp-babel");
const swig = require("gulp-swig");

const 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(),
};

// scss 转 css
const style = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/styles/*.scss", { base: "src" })
      //  scss 处理 并保留花括号换行
      .pipe(sass({ outputStyle: "expanded" }))
      .pipe(dest("dist"))
  );
};

const script = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/scripts/*.js", { base: "src" })
      //  ES6+ 处理 注意这里要提供 babel 预设, 不然就不转换
      .pipe(babel({ presets: ["@babel/preset-env"] }))
      .pipe(dest("dist"))
  );
};

const page = () => {
  // src/**/*.html 匹配任意子目录
  return src("src/*.html", { base: "src" })
    .pipe(swig({ data }))
    .pipe(dest("dist"));
};

// 并行执行 样式-脚本-页面 编译
const compile = parallel(style, script, page)

module.exports = {
    compile
};

测试:
yarn gulp compile

图片和字体文件的转换

const { src, dest, parallel } = require("gulp");

const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
// const sass = require("gulp-sass");
// const babel = require("gulp-babel");
// const swig = require("gulp-swig");
// const imagemin = require("gulp-imagemin");


const 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(),
};

// scss 转 css
const style = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/styles/*.scss", { base: "src" })
      //  scss 处理 并保留花括号换行
      .pipe(plugins.sass({ outputStyle: "expanded" }))
      .pipe(dest("dist"))
  );
};

// 编译脚本文件
const script = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/scripts/*.js", { base: "src" })
      //  ES6+ 处理 注意这里要提供 babel 预设, 不然就不转换
      .pipe(plugins.babel({ presets: ["@babel/preset-env"] }))
      .pipe(dest("dist"))
  );
};

// 编译模板文件
const page = () => {
  // src/**/*.html 匹配任意子目录
  return src("src/*.html", { base: "src" })
    .pipe(plugins.swig({ data }))
    .pipe(dest("dist"));
};

// 转换图片文件
const image = () => {
  // 匹配文件下的所有文件
  return src("src/assets/images/**").pipe(plugins.imagemin()).pipe(dest("dist"));
};

// 转换字体文件, 一般的字体文件不需要压缩等处理, 但是有些svg格式的文件,还是可以稍微处理一下
const font = () => {
  // 匹配文件下的所有文件
  return src("src/assets/fonts/**").pipe(plugins.imagemin()).pipe(dest("dist"));
};

// 并行执行 样式-脚本-页面 编译
const compile = parallel(style, script, page, image, font);

module.exports = {
  compile,
};

其他文件清除

const { src, dest, parallel, series, watch } = require("gulp");
const del = require("del");
const loadPlugins = require("gulp-load-plugins");
const bs = require("browser-sync");
const plugins = loadPlugins();

// const sass = require("gulp-sass");
// const babel = require("gulp-babel");
// const swig = require("gulp-swig");
// const imagemin = require("gulp-imagemin");

const 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(),
};

// 清除文件
const clean = () => {
  // del 返回的是个 promise
  return del(["dist"]);
};

// scss 转 css
const style = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/styles/*.scss", { base: "src" })
      //  scss 处理 并保留花括号换行
      .pipe(plugins.sass({ outputStyle: "expanded" }))
      .pipe(dest("dist"))
      .pipe(bs.reload({ stream: true }))
  );
};

// 编译脚本文件
const script = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/scripts/*.js", { base: "src" })
      //  ES6+ 处理 注意这里要提供 babel 预设, 不然就不转换
      .pipe(plugins.babel({ presets: ["@babel/preset-env"] }))
      .pipe(dest("dist"))
      .pipe(bs.reload({ stream: true }))
  );
};

// 编译模板文件
const page = () => {
  // src/**/*.html 匹配任意子目录
  return src("src/*.html", { base: "src" })
    .pipe(plugins.swig({ data, defaults: { cache: false } })) // 防止模板缓存导致页面不能及时更新
    .pipe(dest("dist"))
    .pipe(bs.reload({ stream: true }));
};

// 转换图片文件
const image = () => {
  // 匹配文件下的所有文件
  return src("src/assets/images/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

// 转换字体文件, 一般的字体文件不需要压缩等处理, 但是有些svg格式的文件,还是可以稍微处理一下
const font = () => {
  // 匹配文件下的所有文件
  return src("src/assets/fonts/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

const serve = () => {
  watch("src/assets/styles/*.scss", style);
  watch("src/assets/scripts/*.js", script);
  watch("src/*.html", page);
  // 这几个静态资源, 开发过程中没必要构建
  // watch('src/assets/images/**', image)
  // watch('src/assets/fonts/**', font)
  // watch('public/**', public)
  watch(
    ["src/assets/images/**", "src/assets/fonts/**", "public/**"],
    bs.reload
  );

  bs.init({
    notify: false, // browser-sync 连接提示
    port: 2080,
    open: true, // 自动打开浏览器窗口
    // files: "dist/**", // 监听dist文件变化
    server: {
      baseDir: ["dist", "src", "public"],
      routes: {
        "/node_modules": "node_modules",
      },
    },
  });
};

//public 原样输出到 dist
const public = () => {
  return src("public/**", { base: "public" }).pipe(dest("dist"));
};

// 并行执行 样式-脚本-页面 编译
const compile = parallel(style, script, page);
// 先清空文件夹, 再编译+复制public文件夹  正式打开再处理 静态资源文件
const build = series(clean, parallel(compile, public, image, font));

const develop = series(compile, serve);

module.exports = {
  clean,
  build,
  serve,
  develop,
  compile,
};

文件压缩
useref

const { src, dest, parallel, series, watch } = require("gulp");
const del = require("del");
const loadPlugins = require("gulp-load-plugins");
const bs = require("browser-sync");
const plugins = loadPlugins();

// const sass = require("gulp-sass");
// const babel = require("gulp-babel");
// const swig = require("gulp-swig");
// const imagemin = require("gulp-imagemin");

const 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(),
};

// 清除文件
const clean = () => {
  // del 返回的是个 promise
  return del(["dist"]);
};

// scss 转 css
const style = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/styles/*.scss", { base: "src" })
      //  scss 处理 并保留花括号换行
      .pipe(plugins.sass({ outputStyle: "expanded" }))
      .pipe(dest("dist"))
      .pipe(bs.reload({ stream: true }))
  );
};

// 编译脚本文件
const script = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/scripts/*.js", { base: "src" })
      //  ES6+ 处理 注意这里要提供 babel 预设, 不然就不转换
      .pipe(plugins.babel({ presets: ["@babel/preset-env"] }))
      .pipe(dest("dist"))
      .pipe(bs.reload({ stream: true }))
  );
};

// 编译模板文件
const page = () => {
  // src/**/*.html 匹配任意子目录
  return src("src/*.html", { base: "src" })
    .pipe(plugins.swig({ data, defaults: { cache: false } })) // 防止模板缓存导致页面不能及时更新
    .pipe(dest("dist"))
    .pipe(bs.reload({ stream: true }));
};

// 转换图片文件
const image = () => {
  // 匹配文件下的所有文件
  return src("src/assets/images/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

// 转换字体文件, 一般的字体文件不需要压缩等处理, 但是有些svg格式的文件,还是可以稍微处理一下
const font = () => {
  // 匹配文件下的所有文件
  return src("src/assets/fonts/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

const serve = () => {
  watch("src/assets/styles/*.scss", style);
  watch("src/assets/scripts/*.js", script);
  watch("src/*.html", page);
  // 这几个静态资源, 开发过程中没必要构建
  // watch('src/assets/images/**', image)
  // watch('src/assets/fonts/**', font)
  // watch('public/**', public)
  watch(
    ["src/assets/images/**", "src/assets/fonts/**", "public/**"],
    bs.reload
  );

  bs.init({
    notify: false, // browser-sync 连接提示
    port: 2080,
    open: true, // 自动打开浏览器窗口
    // files: "dist/**", // 监听dist文件变化
    server: {
      baseDir: ["dist", "src", "public"],
      routes: {
        "/node_modules": "node_modules",
      },
    },
  });
};

//public 原样输出到 dist
const public = () => {
  return src("public/**", { base: "public" }).pipe(dest("dist"));
};

const useref = () => {
  return src("dist/*.html", { base: "dist" })
  .pipe(plugins.useref({ searchPath: ['dist', '.'] }))
  .pipe(plugins.if(/\.js$/, plugins.uglify()))
  .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
  .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
  .pipe(plugins.if(/\.html$/, plugins.htmlmin({
    collapseWhitespace: true,
    minifyCss: true,
    minifyJs: true
  })))
  .pipe(dest("release"));
};

// 并行执行 样式-脚本-页面 编译
const compile = parallel(style, script, page);
// 先清空文件夹, 再编译+复制public文件夹  正式打开再处理 静态资源文件
const build = series(clean, parallel(compile, public, image, font));

const develop = series(compile, serve);

module.exports = {
  clean,
  build,
  serve,
  develop,
  compile,
  useref
};

测试
yarn gulp compile
yarn gulp useref

重新规划合理的构建过程
添加临时文件 tmp 避免读写流冲突(不能读写都是dist 文件)

const { src, dest, parallel, series, watch } = require("gulp");
const del = require("del");
const loadPlugins = require("gulp-load-plugins");
const bs = require("browser-sync");
const plugins = loadPlugins();

// const sass = require("gulp-sass");
// const babel = require("gulp-babel");
// const swig = require("gulp-swig");
// const imagemin = require("gulp-imagemin");

const 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(),
};

// 清除文件
const clean = () => {
  // del 返回的是个 promise
  return del(["tmp"]);
};

// scss 转 css
const style = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/styles/*.scss", { base: "src" })
      //  scss 处理 并保留花括号换行
      .pipe(plugins.sass({ outputStyle: "expanded" }))
      .pipe(dest("tmp"))
      .pipe(bs.reload({ stream: true }))
  );
};

// 编译脚本文件
const script = () => {
  // 指定从 src 下保留路径
  return (
    src("src/assets/scripts/*.js", { base: "src" })
      //  ES6+ 处理 注意这里要提供 babel 预设, 不然就不转换
      .pipe(plugins.babel({ presets: ["@babel/preset-env"] }))
      .pipe(dest("tmp"))
      .pipe(bs.reload({ stream: true }))
  );
};

// 编译模板文件
const page = () => {
  // src/**/*.html 匹配任意子目录
  return src("src/*.html", { base: "src" })
    .pipe(plugins.swig({ data, defaults: { cache: false } })) // 防止模板缓存导致页面不能及时更新
    .pipe(dest("tmp"))
    .pipe(bs.reload({ stream: true }));
};

// 转换图片文件
const image = () => {
  // 匹配文件下的所有文件
  return src("src/assets/images/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

// 转换字体文件, 一般的字体文件不需要压缩等处理, 但是有些svg格式的文件,还是可以稍微处理一下
const font = () => {
  // 匹配文件下的所有文件
  return src("src/assets/fonts/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

const serve = () => {
  watch("src/assets/styles/*.scss", style);
  watch("src/assets/scripts/*.js", script);
  watch("src/*.html", page);
  // 这几个静态资源, 开发过程中没必要构建
  // watch('src/assets/images/**', image)
  // watch('src/assets/fonts/**', font)
  // watch('public/**', public)
  watch(
    ["src/assets/images/**", "src/assets/fonts/**", "public/**"],
    bs.reload
  );

  bs.init({
    notify: false, // browser-sync 连接提示
    port: 2080,
    open: true, // 自动打开浏览器窗口
    // files: "dist/**", // 监听dist文件变化
    server: {
      baseDir: ["tmp", "src", "public"],
      routes: {
        "/node_modules": "node_modules",
      },
    },
  });
};

//public 原样输出到 dist
const public = () => {
  return src("public/**", { base: "public" }).pipe(dest("dist"));
};

const useref = () => {
  return src("tmp/*.html", { base: "tmp" })
  .pipe(plugins.useref({ searchPath: ['tmp', '.'] }))
  .pipe(plugins.if(/\.js$/, plugins.uglify()))
  .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
  .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
  .pipe(plugins.if(/\.html$/, plugins.htmlmin({
    collapseWhitespace: true,
    minifyCss: true,
    minifyJs: true
  })))
  .pipe(dest("dist"));
};

// 并行执行 样式-脚本-页面 编译
const compile = parallel(style, script, page);
// 先清空文件夹, 再编译+复制public文件夹  正式打开再处理 静态资源文件
const build = series(clean, parallel(series(compile, useref), public, image, font));

const develop = series(compile, serve);

module.exports = {
  build,  // 正式打包
  develop // 开发环境
};

配置一下 npm scripts 脚本

自动化构建的学习应用—Gulp

本文地址:https://blog.csdn.net/qinshengnan520/article/details/111133256

相关标签: 笔记 javascript