基于 webpack5 前端工程化

70 阅读3分钟

前言:内容来源于抖音【哲玄前端】大佬的《大前端全栈实践》课程

前端工程化是指围绕代码处理的一系列工具链,它们并不运行代码,而是对代码作处理,包括编译打包、CICD、代码托管、静态分析、格式化等。从而提高开发效率、保证代码质量、确保多环境一致性和可靠性。

解析引擎的工作流程

elpis-image.png

搭建 webpack5 设置

多页面构建

elpis 工程项目结构是多页面系统,前端工程化需要支持多入口配置,适配实际业务当中多页面系统,动态地构造入口页面配置

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const glob = require("glob");
const { sep } = path;

// 动态构造 pageEntries 和 htmlWebpackPluginList
const pageEntries = {};
const htmlWebpackPluginList = [];

// 获取 app/pages 目录下所有入口文件(entry.xx.js)
const entryPath = path.resolve(
  process.cwd(),
  `.${sep}app${sep}pages${sep}**${sep}entry.**.js`
);

glob.sync(entryPath).forEach((file) => {
  const entryName = path.basename(file, ".js");
  pageEntries[entryName] = file;
  htmlWebpackPluginList.push(
    // html-webpack-plugin配置:辅助注入打包后的 bundle 文件到 tpl 模板文件中
    new HtmlWebpackPlugin({
      filename: path.resolve(
        process.cwd(),
        `.${sep}app${sep}public${sep}dist${sep}`,
        `${entryName}.tpl`
      ),
      // 制定要使用的模板文件
      template: path.resolve(process.cwd(), "./app/view/entry.tpl"),
      // 要注入的代码块
      chunks: [entryName],
    })
  );
});

代码分包

对公共部分代码、第三方包代码作处理,这样能有效利用浏览器缓存,且降低打包文件大小。

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CSSMinimizerPlugin = require("css-minimizer-webpack-plugin");
 // 配置打包输出优化(代码分割、模块合并、缓存、treeShaking、压缩等优化策略)
{
  // 入口配置
  entry: pageEntries,
  optimization: {
    /**
     * 把 js 文件打包成 3 种类型
     * 1. vendor: 第三方 lib 库,基本不动,除非依赖版本升级
     * 2. common: 业务组件代码的公共部分抽离出来,改动较少
     * 3. entry.{page}: 不用页面 entry 里的业务组件代码的差异部分,会经常改动
     * 把改动和引用频率不一样的 js 代码区分出来,达到更好利用浏览器缓存的效果
     */
    splitChunks: {
      chunks: "all", // 对同步和异步模块进行都分割
      maxAsyncRequests: 10, // 每次异步加载的最大并发请求数
      maxInitialRequests: 10, // 入口的最大并行请求数
      cacheGroups: {
        vendor: {
          // 第三方依赖包
          test: /[\\/]node_modules[\\/]/,
          name: "vendor", // 模块名称
          priority: 10, // 优先级,数字越大,优先级越高
          enforce: true, // 强制执行
          reuseExistingChunk: true, // 复用已有的公共 chunk
        },
        common: {
          // 公共模块
          name: "common", // 模块名称
          minChunks: 2, // 被两处引用即归为公共模块
          minSize: 1, // 最小分割文件大小(1 byte)
          priority: 1, // 优先级,数字越大,优先级越高
          reuseExistingChunk: true, // 复用已有的公共 chunk
        },
      },
    },
    // 将 webpack 运行时生成的代码打包到 runtime.js
    runtimeChunk: true,
  },
  plugins: [
     // 构造最终渲染的页面模板
    ...htmlWebpackPluginList,
    // 提取 css 的公共部分,有效利用缓存,(非公共部分使用 inline)
    new MiniCssExtractPlugin({
      chunkFilename: "css/[name]_[contenthash:8].bundle.css",
    }),
    // 优化并压缩 css
    new CSSMinimizerPlugin()
  ],
}

开发环境

  1. 热更新:监控能力 (webpack-dev-middleware) 和通知能力 (webpack-hot-middleware)
  2. 把 tpl 文件落地,实时构建产物存在运行时内存