自动化构建、测试、部署(上)

课程目标

  • 掌握前端自动化构建体系搭建思路;

  • 了解常见构建工具生态;

  • 掌握常见构建相关生态;

  • 掌握前端自动化构建实现方案;

  • 掌握自动化构建流程与原理;

知识要点

现代构建工具

Rollup

Rollup 是一个专注于 JavaScript 类库打包 的模块打包器,它尤其擅长处理 ES6 模块,并能通过高效的 Tree-shaking 来优化输出代。

Rollup和 Webpack 的主要区别

Rollup 更专注于 ES Modules 的打包,利用 ESM 的特性可以构建出结构更扁平、性能更出众的类库。它通常能生成更小巧、更高效的 bundle。配置相对简单但因为没有devServer和HMR,所以一般rollup用于类库编写(JS库开发),而非业务开发

Webpack 功能非常全面,致力于前端工程化的完整解决方案。它具备强大的代码分割、静态资源处理、热模块替换 (HMR) 等高级功能,更适合构建复杂的应用程序;

针对一个相同的demo,webpack和rollup打包出的体积相差极大

webpack诞生于ESM标准出来前,CommonJs出来后,当时的浏览器只能通过script标签加载模块; script标签加载代码是没有作用域的,只能在代码内 用iife的方式 实现作用域效果。

Esbuild
Esbuild实践
javascript 复制代码
// esbuild.config.js
import esbuild from 'esbuild'

const config = {
  entryPoints: ['src/index.tsx'], // 支持 TS/TSX/JS/JSX
  bundle: true, // 必须为 true 才能打包依赖
  outdir: 'dist',
  platform: 'browser', // 'node', 'neutral'
  format: 'esm', // 'cjs', 'iife'
  sourcemap: true, // 开发环境用 'linked',生产环境用 true 或 'external'
  minify: true, // 生产环境开启
  target: ['es2020'], // 根据你的目标浏览器设置
}

// 区分开发和生产环境
if (process.env.NODE_ENV === 'production') {
  await esbuild.build(config)
} else {
  const ctx = await esbuild.context(config)
  // await ctx.watch() // 监听文件变化
  await ctx.serve({ servedir: 'dist', port: 3000 }) // 提供服务并热重载(非 HMR)
}

构建的技术选型与方案

  • 初始化项目

  • 依赖盘点与安装(在架构时,分析你们的项目前期需要那些库及依赖,安装它们)

  • 运行你确定的一些工程化脚本

    • start build

    • test、lint、type-check

    • 基于 git 钩子做一些事情 commit pre-commit

  • 打包构建

  • (团队建设 团队提效)规范的确立:ts、eslint、stylelint、spellcheck(拼写检查),git flow 规范

  • git flow 规范

    => 提效 =》减少 bug 提高代码质量

=》 cli 脚手架 统一脚手架 遵循规范

构建优化

输出分析

我们需要对输出结果做分析,以决定下一步的优化方向。

最直接的分析方法就是去阅读 Webpack 输出的代码,但由于 Webpack 输出的代码可读性非常差而且文件非常大,这会让你非常头疼。 为了更简单直观的分析输出结果,社区中出现了许多可视化的分析工具。这些工具以图形的方式把结果更加直观的展示出来,让你快速看到问题所在。

javascript 复制代码
"buildJson": "webpack  --profile  --json > stats.json",
官方的可视化分析工具

打开 Webpack Analyse 链接的网页后,你就会看到一个弹窗提示你上传 JSON 文件,也就是需要上传上面讲到的 stats.json 文件,如图:

webpack-bundle-analyzer

它能方便的让你知道:

  • 打包出的文件中都包含了什么;

  • 每个文件的尺寸在总体中的占比,一眼看出哪些文件尺寸大;

  • 模块之间的包含关系;

  • 每个文件的 Gzip 后的大小;

Esbuild-loader

esbuild-loader 是一个基于 esbuild 的 webpack 加载器,可以显著提升构建速度。

javascript 复制代码
// webpack.config.js
const { ESBuildMinifyPlugin } = require('esbuild-loader');

module.exports = {
  mode: 'development',
  
  module: {
    rules: [
      // JavaScript/TypeScript
      {
        test: /\.(js|jsx|ts|tsx)$/,
        loader: 'esbuild-loader',
        options: {
          loader: 'tsx',
          target: 'es2015',
          jsx: 'automatic' // 或 'preserve', 'transform'
        }
      },
      
      // CSS
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'esbuild-loader',
            options: {
              loader: 'css',
              minify: true
            }
          }
        ]
      }
    ]
  },
  
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx']
  }
};

使用swc-loader优化

SWC虽然名义上是编译器,但它实际上是compiler + bundler,只不过目前的bundler功能还有待完善提高;

SWC 是用 Rust 语言编写的,其性能优势非常明显。它利用了 Rust 语言的高效性和底层优化机制,在对代码进行转换时速度极快。例如,在将 ES6 + 代码转换为 ES5 兼容代码的常见任务中,SWC 通常能够比 Babel 更快地完成转换操作,尤其是在处理大型项目的大量代码时,这种性能差异更加显著。

SWC

SWC 使用 .swcrc 文件进行配置,支持 JSON 格式:

javascript 复制代码
{
  "jsc": {
    "parser": {},
    "transform": {},
    "target": "es5",
    "loose": false,
    "externalHelpers": false
  },
  "env": {
    "targets": {},
    "mode": "usage",
    "coreJs": 3
  },
  "module": {
    "type": "commonjs"
  },
  "minify": false
}
Vs Babel

Vite构建优化

Vite 在开发环境下凭借其基于 ESM 的 No-Bundle 机制已经非常快速,但在生产构建时,我们仍然需要关

核心构建配置优化
javascript 复制代码
// vite.config.js
import { defineConfig } from 'vite'

export default defineConfig({
  build: {
    // 1. 指定输出目录,默认为 'dist'
    outDir: 'dist',

    // 2. 代码分割策略
    rollupOptions: {
      output: {
        // 手动分块,避免过大的 chunk
        manualChunks(id) {
          if (id.includes('node_modules')) {
            // 将 node_modules 中的依赖分块
            if (id.includes('lodash')) {
              return 'lodash';
            }
            if (id.includes('axios')) {
              return 'axios';
            }
            // 将 React 相关库打包在一起
            if (id.includes('react')) {
              return 'react-vendor';
            }
            // 默认将所有其他 npm 包打包到 vendor 块中
            return 'vendor';
          }
        },
        // 用于命名代码拆分时创建的 chunk
        chunkFileNames: 'js/[name]-[hash].js',
        // 用于输出静态资源的命名
        assetFileNames: '[ext]/[name]-[hash].[ext]'
      }
    },

    // 3. 资源大小限制警告(单位:kb)
    chunkSizeWarningLimit: 1000,

    // 4. 生产环境 sourcemap(可选,根据需求选择)
    // 'hidden-source-map' 只生成 sourcemap 但不包含引用,适合错误上报
    sourcemap: process.env.NODE_ENV === 'production' ? 'hidden-source-map' : false,

    // 5. 最小化配置
    minify: 'esbuild', // 或 'terser',esbuild 更快
    terserOptions: { // 当使用 terser 时的配置
      compress: {
        drop_console: true, // 移除 console
        drop_debugger: true // 移除 debugger
      }
    }
  }
})
路由级代码分割

使用动态 import() 实现路由懒加载,这是最有效的优化手段之一。

javascript 复制代码
// router.js
const Home = () => import('./views/Home.vue')
const About = () => import('./views/About.vue')
const HeavyComponent = () => import('./components/HeavyComponent.vue')

对于非首屏需要的重型组件,使用懒加载。

javascript 复制代码
<template>
  <div>
    <button @click="loadHeavyComponent">加载重型组件</button>
    <Suspense>
      <HeavyComponent v-if="showHeavy" />
      <template #fallback>
        <div>加载中...</div>
      </template>
    </Suspense>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const showHeavy = ref(false)
const HeavyComponent = ref(null)

const loadHeavyComponent = async () => {
  HeavyComponent.value = await import('./components/HeavyComponent.vue')
  showHeavy.value = true
}
</script>
相关推荐
loong_XL36 分钟前
elastic kibana可视化数据统计案例
运维·ai·智能体
惜.己44 分钟前
安装windows版本docker(配置镜像源+拉取运行docker)
运维·docker·容器
5G全域通1 小时前
面向5G复杂性的下一代运维技术体系:架构、工具与实践
大数据·运维·人工智能·5g·架构
你好helloworld1 小时前
ubuntu安装protobuf
linux·运维·ubuntu
Atri厨1 小时前
awk入门练习题
linux·运维·服务器
极客小云2 小时前
【2026年Docker国内镜像源最新可用清单与配置指南】
运维·docker·容器
乾元2 小时前
生成对抗样本在网络安全中的工程化解读——AI 误报、误判与对抗的真实边界
运维·网络·人工智能·python·安全·web安全
zeijiershuai2 小时前
Linux、Linux常用命令、Linux软件安装、Linux项目部署
linux·运维·服务器
小宇的天下2 小时前
Calibre nmDRC 高级边缘处理与输出控制(17)
linux·运维·lvs
java_logo2 小时前
Caddy Docker 容器化部署指南
运维·docker·容器·caddy部署·caddy部署文档·caddy部署教程·docker部署caddy