【学习笔记】Webpack基础(二)

108 阅读3分钟

Webpack 基础(二)

第二篇笔记是关于webpack优化的部分内容的学习。

一、优化构建速度

resolve

resolve配置主要用于控制模块解析的行为。它决定了 Webpack 在importrequire模块时如何寻找文件路径。

常用配置项如下:

选项作用常见配置示例
extensions如果用户引入模块时不带扩展名,就会按照此数组从左到右去尝试解析模块extensions:['.js', '.ts', '.tsx', '.json']
alias配置模块路径别名,简化路径书写alias: { '@': path.resolve(__dirname, 'src')}

externals

指定某些模块不打包,而是直接通过全局变量或外部加载。 例如:假设我们想将ReactReactDOM从打包中排除,并通过 CDN 加载它们:

  1. webpack.config.js:
externals: {
  react: 'React',
  'react-dom': 'ReactDOM',
}

当代码中使用import React from 'react'时,Webpack 不会将 React 打包,而是假定项目运行时已经通过<script>标签加载了 React 并定义了全局变量React

  1. index.html
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>

最终 React 和 ReactDOM 不会被打包进输出的文件,在运行时,通过<script>标签加载的全局变量提供它们。引用的时候照常引用。

缩小处理范围

1. includeexclude

这两个选项主要用于 Loader 的配置中,用来指定哪些文件应该被某个 Loader 处理或者排除。

  • 作用: 提高构建效率,避免不必要的文件处理。
include
  • 表示只处理指定目录或文件。
  • 接收的值通常是一个路径或者正则表达式。
  • 例子:
    module.exports = {
      module: {
        rules: [
          {
            test: /\.js$/,
            use: "babel-loader",
            include: /src/, // 只处理 src 目录下的文件
          },
        ],
      },
    };
    
exclude
  • 表示排除指定目录或文件,不进行处理。
  • 适合排除 node_modules 这样的外部依赖库。
  • 例子:
    module.exports = {
      module: {
        rules: [
          {
            test: /\.js$/,
            use: "babel-loader",
            exclude: /node_modules/, // 排除 node_modules 目录
          },
        ],
      },
    };
    
同时使用 includeexclude

可以更精准地控制范围,但需确保逻辑不冲突。
例如:

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: "babel-loader",
        include: /src/,
        exclude: /node_modules/,
      },
    ],
  },
};

2. noParse

noParse 是 Webpack 中用来优化模块解析的配置,作用是告知 Webpack 不解析某些模块的依赖关系。

  • 作用: 提高构建速度,适用于不需要解析依赖的库(如预编译的库)。
  • 注意事项:被标记为 noParse 的模块仍然会被打包,但 Webpack 不会分析它们的依赖树。
  • 常见使用场景:指定不包含依赖关系的库,比如 jQuery、lodash 的独立文件。
例子:
module.exports = {
  module: {
    noParse: /jquery|lodash/, // 不解析 jquery 和 lodash 的依赖关系
  },
};
注意:
  • noParse 的模块不能包含 importrequire 等动态导入语法,否则会报错。
  • 适用于独立、完整的库,通常和 CDN 配合使用。

利用缓存

babel-loader开启缓存

const config = {
  module: {
    noParse: /jquery|lodash/,
    rules: [
      {
        test: /\.js$/i,
        include: resolve("src"),
        exclude: /node_modules/,
        use: [
          // ...
          {
            loader: "babel-loader",
            options: {
              cacheDirectory: true, // 启用缓存
            },
          },
        ],
      },
      // ...
    ],
  },
};

其他的 loader 可以安装使用cache-loader来将结果缓存。

二、优化构建结果

压缩 CSS

最常用的插件是css-minimizer-webpack-plugin,用于优化和压缩 CSS 文件。

配置示例:

const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  mode: "production",
  optimization: {
    minimizer: [
      "...", // 其他
      new CssMinimizerPlugin(),
    ],
  },
};

压缩 JS

在生成环境下打包默认会开启 js 压缩,但是当我们手动配置 optimization 选项之后,就不再默认对 js 进行压缩,需要我们手动去配置。

webpack5 内置了terser-webpack-plugin,直接引用就可以。

配置示例:

const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  mode: "production",
  optimization: {
    minimize: true, // 是否进行压缩
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true, //传true就是干掉所有的console.*这些函数的调用.
            drop_debugger: true, //干掉那些debugger;
          },
        },
      }),
    ], 
  },
};

三、优化运行时体验

运行时,是指用户在浏览器中加载、解析和执行前端代码的阶段。

运行时优化的核心就是提升首屏加载速度。

代码懒加载

针对首屏加载不太需要的一些资源,我们可以通过懒加载的方式去实现。 示例:

// 按需加载
img.addEventListener('click', () => {
  import('./desc').then(({ default: element }) => {
    document.body.appendChild(element)
  })
})

使用上述方法异步加载文件时,如果文件比较大,在点击时去加载影响体验。可以考虑使用prefetch来进行预拉取,它会在浏览器空间的时候进行拉取。

示例如下:

img.addEventListener('click', () => {
  import( /* webpackPrefetch: true */ './desc').then(({ default: element }) => {
    console.log(element)
    document.body.appendChild(element)
  })
})