基于 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支持:解决跨域问题
  • 热更新通信:实时推送代码变更

结语

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

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学3 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端