概述

一个包含完整配置的 webpack 从开发到生产的全方位配置指南,展示从开发环境到生产环境的完整配置方案。该项目包含了现代前端开发中常用的各种配置,如样式处理、资源管理、代码优化等

核心配置文件分析

开发环境配置 (webpack.dev.js)

开发环境配置主要关注开发体验和调试便捷性,以下是关键配置点:

1. 基础配置

module.exports = {
  entry: "./src/main.js",
  output: {
    path: undefined, // 开发环境下输出到内存
    filename: "static/js/main.js",
  },
  mode: "development",
  devtool: "cheap-module-source-map",
};

要点

  • path: undefined:开发环境下,webpack-dev-server 将文件输出到内存中,提高构建速度

  • cheap-module-source-map:生成较快的 source map,只包含行映射,适合开发调试

2. 开发服务器配置

devServer: {
  host: "localhost",
  port: "3000",
  open: true, // 自动打开浏览器
  hot: true, // 开启热模块替换
},

要点

  • hot: true:启用热模块替换(HMR),修改文件时无需刷新整个页面

  • open: true:构建完成后自动打开浏览器,提升开发效率

3. Loader 配置


module: {
  rules: [
    {
      oneOf: [
        // CSS 处理
        { test: /\.css$/, use: ["style-loader", "css-loader"] },
        // Less 处理
        { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"] },
        // Sass/SCSS 处理
        { test: /\.s[ac]ss$/, use: ["style-loader", "css-loader", "sass-loader"] },
        // Stylus 处理
        { test: /\.styl$/, use: ["style-loader", "css-loader", "stylus-loader"] },
        // 图片处理
        {
          test: /\.(png|jpe?g|gif|webp)$/,
          type: "asset",
          parser: {
            dataUrlCondition: { maxSize: 1000 * 1024 }, // 1000kb 以下图片 base64 处理
          },
          generator: { filename: "static/images/[hash:16][ext][query]" },
        },
        // 字体处理
        {
          test: /\.(ttf|woff2?)$/,
          type: "asset/resource",
          generator: { filename: "static/media/[hash:10][ext][query]" },
        },
        // JavaScript 处理
        {
          test: /\.js$/,
          include: path.resolve(__dirname, "../src"),
          use: [
            {
              loader: "thread-loader", // 多线程构建
              options: { workers: threads },
            },
            {
              loader: "babel-loader",
              options: {
                cacheDirectory: true, // 缓存转译结果
                cacheCompression: false, // 不压缩缓存文件
                plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
              },
            },
          ],
        },
      ],
    },
  ],
},

要点

  • oneOf:优化 loader 匹配,避免不必要的 loader 执行

  • asset 模块:webpack 5 内置的资源处理,替代了 file-loader、url-loader 等

  • thread-loader:多线程构建,提升构建速度

  • babel-loader:使用 Babel 转译 JavaScript,支持 ES6+ 语法

4. 插件配置

plugins: [
  new ESLintWebpackPlugin({
    context: path.resolve(__dirname, "../src"),
    exclude: "node_modules",
    fix: true, // 自动修复 ESLint 错误
    cache: true, // 缓存检查结果
    cacheLocation: path.resolve(__dirname, "../node_modules/.cache/.eslintcache"),
    threads, // 多线程检查
  }),
  new HtmlWebpackPlugin({
    template: path.resolve(__dirname, "../public/index.html"),
  }),
],

要点

  • ESLintWebpackPlugin:集成 ESLint 代码质量检查

  • HtmlWebpackPlugin:生成 HTML 文件,自动注入打包后的资源

生产环境配置 (webpack.prod.js)

生产环境配置主要关注构建优化和性能,以下是关键配置点:

1. 输出配置

output: {
  path: path.resolve(__dirname, "../dist"),
  filename: "static/js/[name].[contenthash:8].js",
  chunkFilename: "static/js/[name].[contenthash:8].chunk.js",
  assetModuleFilename: "static/media/[name].[hash][ext]",
  clean: true, // 清理输出目录
},

要点

  • contenthash:根据文件内容生成哈希值,实现长期缓存

  • clean: true:构建前清理输出目录,避免文件残留

2. 样式处理

function getStyleLoaders(preloader) {
  return [
    MiniCssExtractPlugin.loader, // 提取 CSS 到单独文件
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: ["postcss-preset-env"], // 自动添加浏览器前缀
        },
      },
    },
    preloader,
  ].filter(Boolean);
}

要点

  • MiniCssExtractPlugin:将 CSS 提取到单独文件,减少 JavaScript 文件体积

  • postcss-loader:处理 CSS 兼容性,自动添加浏览器前缀

3. 性能优化插件

plugins: [
  // ...
  new PreloadWebpackPlugin({
    rel: "preload", // 预加载关键资源
    as: "script",
  }),
  new WorkboxPlugin.GenerateSW({
    clientsClaim: true,
    skipWaiting: true, // 快速启用 Service Worker
  }),
],

要点

  • PreloadWebpackPlugin:预加载关键资源,提升首屏加载速度

  • WorkboxPlugin:生成 Service Worker,支持离线访问

4. 代码优化配置

optimization: {
  minimize: true,
  minimizer: [
    new CssMinimizerPlugin(), // 压缩 CSS
    new TerserPlugin({ parallel: true }), // 压缩 JavaScript
    new ImageMinimizerPlugin({
      minimizer: {
        implementation: ImageMinimizerPlugin.squooshMinify,
        options: {
          encodeOptions: {
            mozjpeg: { quality: 80 },
            webp: { lossless: true },
            avif: { cqLevel: 33 },
          },
        },
      },
    }),
  ],
  splitChunks: {
    chunks: "all", // 分割所有类型的 chunks
  },
  runtimeChunk: {
    name: (entrypoint) => `${entrypoint.name}-runtime`, // 分离运行时代码
  },
},

要点

  • 代码压缩:使用 TerserPlugin、CssMinimizerPlugin 压缩代码

  • 图片压缩:使用 ImageMinimizerPlugin 压缩图片

  • 代码分割:使用 splitChunks 分割代码,减少初始加载体积

  • 运行时代码分离:避免业务代码变化导致 runtime hash 变化

ESLint 配置 (.eslintrc.json)

{
  "extends": ["eslint:recommended"],
  "parser": "@babel/eslint-parser",
  "env": {
    "node": true,
    "es6": true,
    "browser": true
  },
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module",
    "requireConfigFile": false
  },
  "rules": {
    "no-var": 2
  },
  "plugins": ["import"]
}

要点

  • extends: "eslint:recommended":使用 ESLint 推荐规则

  • parser: "@babel/eslint-parser":使用 Babel 解析器,支持 ES6+ 语法

  • no-var: 2:禁止使用 var 声明变量

Babel 配置 (babel.config.js)

module.exports = {
  presets: [
    ["@babel/preset-env", {
      useBuiltIns: "usage", // 按需加载 polyfill
      corejs: { version: "3", proposals: true } // 使用 core-js 3
    }]
  ],
};

要点

  • useBuiltIns: "usage":根据代码中实际使用的特性按需加载 polyfill

  • corejs: { version: "3", proposals: true }:使用 core-js 3 版本,支持提案阶段的特性

项目配置 (package.json)

{
  "scripts": {
    "dev": "npx webpack serve --config ./config/webpack.dev.js",
    "build": "npx webpack --config ./config/webpack.prod.js"
  },
  "browserslist": [
    "last 2 versions",
    "> 1%",
    "not dead",
    "ie 11"
  ],
  "dependencies": {
    "core-js": "^3.49.0"
  }
}

要点

  • scripts:定义开发和构建命令

  • browserslist:指定目标浏览器,影响 Babel 转译和 PostCSS 前缀添加

  • core-js:提供 polyfill 支持

第三方包说明

包名

用途

webpack

核心打包工具

webpack-cli

命令行工具

webpack-dev-server

开发服务器,支持热更新

babel-loader

使用 Babel 转译 JavaScript

@babel/preset-env

Babel 预设,转换 ES6+ 语法

@babel/plugin-transform-runtime

减少重复代码,优化 Babel 输出

core-js

提供 polyfill 支持

eslint-webpack-plugin

集成 ESLint 代码质量检查

html-webpack-plugin

生成 HTML 文件,自动注入资源

mini-css-extract-plugin

提取 CSS 到单独文件

css-loader

解析 CSS 文件

style-loader

将 CSS 注入到 DOM

less-loader

解析 Less 文件

sass-loader

解析 Sass/SCSS 文件

stylus-loader

解析 Stylus 文件

postcss-loader

处理 CSS 兼容性

postcss-preset-env

自动添加浏览器前缀

thread-loader

多线程构建,提升速度

terser-webpack-plugin

压缩 JavaScript

css-minimizer-webpack-plugin

压缩 CSS

image-minimizer-webpack-plugin

压缩图片

@vue/preload-webpack-plugin

预加载关键资源

workbox-webpack-plugin

生成 Service Worker

优化策略总结

1. 开发体验优化

  • 热模块替换:修改文件时无需刷新页面

  • 自动打开浏览器:构建完成后自动打开浏览器

  • source map:方便调试,快速定位错误

  • ESLint 集成:实时检查代码质量,自动修复错误

2. 构建速度优化

  • 多线程构建:使用 thread-loader 并行处理

  • 缓存机制:缓存 babel 转译结果和 ESLint 检查结果

  • oneOf 优化:避免不必要的 loader 执行

  • 内存输出:开发环境输出到内存,提升构建速度

3. 代码体积优化

  • 代码分割:使用 splitChunks 分割代码

  • Tree Shaking:移除未使用的代码

  • 代码压缩:压缩 JavaScript 和 CSS

  • 图片压缩:优化图片大小

  • 动态导入:按需加载代码,减少初始加载体积

4. 运行性能优化

  • 资源预加载:使用 preload 预加载关键资源

  • Service Worker:支持离线访问,提升重复访问速度

  • CSS 提取:CSS 单独文件,并行加载

  • 长期缓存:使用 contenthash 实现文件缓存

  • 运行时代码分离:避免业务代码变化影响缓存

5. 兼容性处理

  • Babel 转译:将 ES6+ 语法转换为 ES5

  • Polyfill 按需加载:根据实际使用的特性加载 polyfill

  • PostCSS 前缀:自动添加浏览器前缀

  • browserslist 配置:明确目标浏览器范围