基于 webpack5 完成工程化建设

抖音 - 哲玄《大前端全栈实践》

前言

通过最近学习,对工程化有了进一步的认识,前端工程化 不是一个具体的工具,而是一个思想和体系,可以通过:

  • 模块化/组件化来解耦复杂应用。
  • 规范化来约束开发过程。
  • 自动化来提升效率和质量。
  • 性能优化来保障用户体验。

掌握工程化思想,要比学习怎么使用构建工具来的更重要。

1.解析引擎工作流程

2. 项目Webpack架构设计

2.1 配置文件结构

bash 复制代码
app/webpack/
├── config/
│   ├── webpack.base.js    # 基础配置(公共配置)
│   ├── webpack.dev.js     # 开发环境配置
│   └── webpack.prod.js    # 生产环境配置
├── dev.js                 # 开发服务器启动脚本
└── prod.js               # 生产环境构建脚本

2.2 配置继承关系

scss 复制代码
webpack.base.js (基础配置)
    ├── webpack.dev.js (开发环境继承)
    └── webpack.prod.js (生产环境继承)

3. 核心配置详解

3.1 基础配置 (webpack.base.js)

3.1.1 多页面入口配置

javascript 复制代码
// 动态构造入口文件和HTML模板文件
const pageEntries = {};
const htmlWebpackPluginList = [];
const entryList = path.resolve(process.cwd(), "./app/pages/**/entry.*.js");

glob.sync(entryList).forEach((file) => {
  const entryName = path.basename(file, ".js");
  pageEntries[entryName] = file;
  htmlWebpackPluginList.push(
    new HtmlWebpackPlugin({
      filename: path.resolve(process.cwd(), "./app/public/dist/", `${entryName}.tpl`),
      template: path.resolve(process.cwd(), "./app/view/entry.tpl"),
      chunks: [entryName],
    })
  );
});

3.1.2 模块解析规则

javascript 复制代码
module: {
  rules: [
    {
      test: /\.vue$/,
      use: { loader: "vue-loader" }
    },
    {
      test: /\.js$/,
      include: [path.resolve(process.cwd(), "./app/pages")],
      use: { loader: "babel-loader" }
    },
    {
      test: /\.(png|jep?g|gif)(\?.+)?$/,
      use: {
        loader: "url-loader",
        options: { limit: 300, esModule: false }
      }
    }
  ]
}

3.1.3 代码分割策略

javascript 复制代码
optimization: {
  splitChunks: {
    chunks: "all",
    cacheGroups: {
      vendor: {
        test: /[\/]node_modules[\/]/,
        name: "vendor",
        priority: 20,
        enforce: true,
        reuseExistingChunk: true,
      },
      common: {
        name: "common",
        minChunks: 2,
        minSize: 1,
        priority: 10,
        reuseExistingChunk: true,
      },
    },
  },
  runtimeChunk: true,
}

分割策略:

  1. vendor:第三方库代码(node_modules)
  2. common:业务公共代码(被2个以上页面引用)
  3. runtime:webpack运行时代码
  4. entry.{page}:页面特定代码

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

3.2.1 热更新配置

javascript 复制代码
// 为每个入口添加HMR客户端
Object.keys(baseConfig.entry).forEach((v) => {
  if (v !== "vendor") {
    baseConfig.entry[v] = [
      baseConfig.entry[v],
      `webpack-hot-middleware/client?path=http://${HOST}:${PORT}/${HMR_PATH}?timeout=${TIMEOUT}&reload=true`,
    ];
  }
});

plugins: [
  new webpack.HotModuleReplacementPlugin({ multiStep: false })
]

3.2.2 Source Map配置

javascript 复制代码
devtool: "eval-cheap-module-source-map"

选择原因:

  • eval:快速重新构建
  • cheap:只包含行信息,构建更快
  • module:包含loader的source map

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

3.3.1 CSS提取和压缩

javascript 复制代码
plugins: [
  new MiniCssExtractPlugin({
    chunkFilename: "css/[name]_[contenthash:8].bundle.css",
  }),
  new CssMinimizerPlugin(),
]

3.3.2 JavaScript压缩优化

javascript 复制代码
optimization: {
  minimize: true,
  minimizer: [
    new TerserPlugin({
      parallel: true,
      cache: true,
      terserOptions: {
        compress: {
          drop_console: true, // 移除console.log
        },
      },
    }),
  ],
}

3.3.3 多线程构建加速

javascript 复制代码
new HappyPack({
  id: "js",
  threadPool: HappyPack.ThreadPool({ size: os.cpus().length }),
  loaders: [
    `babel-loader?${JSON.stringify({
      presets: ["@babel/preset-env"],
      plugins: ["@babel/plugin-transform-runtime"],
    })}`,
  ],
})

4. 开发服务器配置

4.1 Express + Webpack中间件

javascript 复制代码
const devMiddleware = webpackDevMiddleware(compiler, {
  writeToDisk: (files) => files.endsWith(".tpl"),
  publicPath: webpackConfig.output.publicPath,
  headers: {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
    "Access-Control-Allow-Headers": "X-Requested-With, Content-Type, Authorization",
  },
});

const hotMiddleware = webpackHotMiddleware(compiler, {
  path: `/${HMR_PATH}`,
  log: false,
});

关键特性:

  • 内存编译:文件保存在内存中,提高访问速度
  • 选择性写盘:只有.tpl文件写入磁盘(后端需要)
  • CORS支持:解决跨域问题
  • 热更新通信:实时推送代码变更

结语

学习前端工程化有助于提升开发效率与项目质量,但不应盲目套用现有方案,而应深入理解其本质。我们应掌握其整体思路与工作流程,思考性能优化方向,并能够结合具体业务需求进行工程化配置。

相关推荐
zengyuhan5033 小时前
Windows BLE 开发指南(Rust windows-rs)
前端·rust
醉方休3 小时前
Webpack loader 的执行机制
前端·webpack·rust
前端老宋Running3 小时前
一次从“卡顿地狱”到“丝般顺滑”的 React 搜索优化实战
前端·react.js·掘金日报
隔壁的大叔3 小时前
如何自己构建一个Markdown增量渲染器
前端·javascript
用户4445543654263 小时前
Android的自定义View
前端
WILLF3 小时前
HTML iframe 标签
前端·javascript
枫,为落叶3 小时前
Axios使用教程(一)
前端
小章鱼学前端3 小时前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
ohyeah3 小时前
JavaScript 词法作用域、作用域链与闭包:从代码看机制
前端·javascript
流星稍逝3 小时前
手搓一个简简单单进度条
前端