Gulp4实战—从0到1打包构建活动页

前言

本文重点 ☞ 在于手把手教你流程化打包构建一个活动页,通过实战的方式了解、学习、并使用 Gulp4 的一些 API 在实际工作中的应用。

正文

如果你对 gulp 相关的概念不是很熟悉,请通过其它方式进行了解。 本文对应 Demo GitHub 仓库地址: https://github.com/15826954460/gulp-practice

环境&依赖

项目搭建

  1. 项目初始化

    bash 复制代码
     1. mkdir gulp-practile-demo
     2. cd gulp-practile-demo
     3. pnpm init
     4. mkdir src
     5. touch readme.md
     6. cd src
     7. mkdir assets
     8. cd assets
     9. mkdir images
     10 mkdir styles

    项目目录如下:

    go 复制代码
     ├── gulp-practile-demo
     │   └── src
     │       └── assets // 静态资源目录
     │           └── images
     │           └── styles 
     │   └── index.html
     │   └── package.json
     |   └── readme.md
  2. 活动页面开发

    活动页的 Code 在这里就不具体介绍了,可以自行写一个,或者直接从 Github Demo 里 Clone

Gulp 构建部署

打包 html 文件

  1. 安装依赖

    bash 复制代码
     pnpm add gulp gulp-htmlmin -D
  2. src/srcipts/utils 文件下新建 paths.js

    path.js 主要用来针对基本路径的维护,如果你对 Vue、React 相关框架比较熟,就类似于 alias 别名对路径的维护

    js 复制代码
     const path = require('path');
     const rootPath = path.resolve(__dirname, '../../../'); // 项目根目录
    
     module.exports = {
       rootPath,
     };
  3. src/srcipts/build 新建 index.js

    build/index.js 为 gulp 打包构建的入口目录

    js 复制代码
     const { series, src, dest } = require('gulp');
     const htmlmin = require('gulp-htmlmin') // 引入 html 压缩模块
    
     const { rootPath } = require('../utils/paths');
    
     const buildHtml = () => {
       const inputDir = `${rootPath}/src/index.html`; // html 入口文件
       const outputDir = `${rootPath}/dist`; // 构建输出 目录
       return src(inputDir) // 打开读取文件
           .pipe(htmlmin({
             removeComments: true, // 清除HTML注释
             collapseWhitespace: true, // 压缩HTML
             collapseBooleanAttributes: true, // 省略布尔属性的值 <input checked="true"/> ==> <input checked />
             removeEmptyAttributes: true, // 删除所有空格作属性值 <input id="" /> ==> <input />
             removeScriptTypeAttributes: false, // 删除<script>的type="text/javascript"
             removeStyleLinkTypeAttributes: true, // 删除<style>和<link>的type="text/css"
             minifyJS: true, // 压缩页面JS
             minifyCSS: true // 压缩页面CSS
           })) // 管道流操作,压缩文件
           .pipe(dest(outputDir)) // 指定压缩文件放置的目录
     };
    
     exports.default = series(buildHtml); // series 串联执行打包脚本
  4. 修改 package.json 打包命令

    gulp -f 用来修改指定执行 gulp 脚本的文件

    json 复制代码
     {
       "scripts": {
         + "build": "gulp -f ./src/scripts/build/index.js"
       }
     }

以上配置可以将 html 文件打包到 dist/index.html, 但是 css 的引用路径有问题,会导致 index.html 无法正常访问。接下来我们解决 css 的打包和路径引用问题

打包 css

css 打包之前,先将 css 复制到 dist/assets/styles 文件然后再进行打包

复制 css 到 dist/assets/styles 目录下, 主要是为了保证目录结构相同,避免打包后还需要修改 html 中引入 css 文件路径

index.html 样式引入是通过 link 外链的 如图

  • 1. 复制文件 Js 脚本

    src/scripts/utils 文件下新建 copyfile.js

    js 复制代码
       const fs = require('fs');  
       const path = require('path');
       
       const copyFolder = (source, destination) => {
       // 如果目标文件夹不存在,则创建
       if (!fs.existsSync(destination)) {
          fs.mkdirSync(destination, { recursive: true });
       }
       // 读取目录中的所有文件/目录
       const files = fs.readdirSync(source);
    
       console.log('files', files);
       
       files.forEach((file) => {
          const sourcePath = path.join(source, file);
          const destinationPath = path.join(destination, file);
       
          // 如果是文件夹则递归调用自身
          if (fs.lstatSync(sourcePath).isDirectory()) {
             copyFolder(sourcePath, destinationPath);
          } else {  
             fs.copyFileSync(sourcePath, destinationPath);
          }
       });
       };
    
       module.exports = { copyFolder };
  • 2. css 文件复制

    src/scripts/build/index.js 修改打包代码

    js 复制代码
       + const { copyFolder } = require('../utils/copyfile');
    
       // 复制图片到 dist 目录
       + const copyFolderToDist = () => {
       +   const source = `${rootPath}/src/assets/images`;
       +   const destination = `${rootPath}/dist/assets/images`;
       +   copyFolder(source, destination);
       + };
  • 3. css 打包压缩

    • scr/scripts/build/index.js 修改打包代码
    js 复制代码
        + const minifyCSS = require('gulp-minify-css');
    
        // 样式打包压缩
        + const buildStyle = () => {
        +   const inputDir = `${rootPath}/src/assets/styles/*.css`;
        +   const outputDir = `${rootPath}/dist/assets/styles/`;
        +   return src(inputDir)
        +     .pipe(minifyCSS()) // 压缩
        +     .pipe(dest(outputDir)); // 输出到 dist 目录
        + };
    
        - exports.default = series(buildHtml);
    
        + exports.default = series(
        +   parallel(
        +      async () => buildHtml(),
        +      async () => copyFolderToDist(),
        +      async () => buildStyle()
        +   )
        + );
  • 4. 执行打包

    bash 复制代码
       npm run build

    打包之后的 html 文件如下

打包 js

实际工作中,所有前端页面都不可能仅仅只是单纯的静态页面,接下来我们对 js 文件进行压缩打包

  1. src/scripts 新建 index.js

    js 复制代码
       // 测试代码如下
       document.body.addEventListener('click', (e) => {
          console.log(e.target);
          console.log('Hello World!');
       });
  2. src/index.html 引入

    html 复制代码
       + <script scr="./scripts/index.js"></script>
  3. 安转依赖

    bash 复制代码
       pnpm add gulp-uglify -D
  4. src/scripts/build/index.js 新增 Js 文件打包压缩脚本

    js 复制代码
       + const uglify = require('gulp-uglify'); // 引入 gulp-uglify 模块
       + const buildJs = () => {
       +   const inputDir = `${rootPath}/src/scripts/index.js`;
       +   const outputDir = `${rootPath}/dist/scripts/`;
       +
       +   return src(inputDir) // 指定要转换的JS文件路径  
       +    .pipe(babel({ presets: ['@babel/preset-env'] })) // 使用Babel进行转换
       +    .pipe(uglify()) // 压缩代码(可选)  
       +    .pipe(dest(outputDir)); // 指定转换后的文件输出路径
       + };
    
        exports.default = series(
          parallel(
             async () => buildHtml(),
             async () => buildStyle(),
       +     async () => buildJs(),
             async () => copyFolderToDist(),
          )
        );

规范打包流程

项目的部署上线终究不是一锤子买卖,从 研发 =》 测试 =》 部署 =》 上线 =》迭代 我们每次打包都需要重新跟新代码,接下来我们补充一下删除 dist 文件夹的逻辑

  1. src/scripts/utils 新增 defile.js

    js 复制代码
       const fs = require('fs');
       const { resolve } = require('path');
       const { rootPath } = require('./paths');
    
       // 需要保留的文件
       const stayFile = ['package.json', 'README.md'];
    
       // 定义删除文件的方法
       const delPath = async (path) => {
          let files = [];
          if (fs.existsSync(path)) {
             files = fs.readdirSync(path);
             files.forEach(async (file) => {
                let curPath = resolve(path, file);
                if (fs.statSync(curPath).isDirectory()) {
                   // recurse
                   if (file != 'node_modules') await delPath(curPath);
                } else {
                   // delete file
                   if (!stayFile.includes(file)) {
                      // delete file
                      fs.unlinkSync(curPath);
                   }
                }
             });
             // 删除给定路径下的目录
             if (path != `${rootPath}`) fs.rmdirSync(path);
          }
       };
       module.exports = { delPath };
    1. src/scripts/build/index.js 新增 Js 删除文件夹脚本
    js 复制代码
       + const { delPath } = require('../utils/delfile');
    
       + // 删除根目录下 dist 文件
       + const removeDist = () => {
       +   return delPath(`${rootPath}/dist`);
       + };
    
       exports.default = series(
       +  // 删除 dist 文件夹
       +  async () => removeDist(),
          // 并行打包 style、 html、 js 文件复制
          parallel(
             async () => buildStyle(),
             async () => buildHtml(),
             async () => buildJs(),
             async () => copyFolderToDist(),
          ),
       );

写在最后

以上就是关于 Gulp 构建打包活动页的整个流程,整个学习过程中的完整 Demo 可参考 github 仓库地址 demo 仓库地址: https://github.com/15826954460/gulp-practice

多页面使用 Gulp 进行流程化打包构建整主要解决各种文件之间的依赖,一些公用的部分也需要单独处理,但整体的思路同单个活动页打包保持一致,根据实际业务进行对应的调整和处理。

本期分享就到此为止,如果有问题 欢迎评论区进行交流讨论,我会根据大家的意见相关博文输出

下一篇: rollup实战------从0到1开发一个敏感字段检索 npm 包

敬请期待!!!

如果该文章对你有所帮助,欢迎点赞、收藏、评论、转发,你的支持是我最大的动力。

相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom12 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试