如何在项目中合理配置Webpack

项目中配置 webpack 有三个目的,打包速度,打包体积,运行流畅度,速度指的是run build的时间,体积是指dist 的大小,流畅指的是打开页面是否不卡顿

打包速度

提升打包速度有以下方式,范围优化,多进程打包,利用缓存

测试打包速度利用speed-measure-webpack-plugin如:

js 复制代码
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
 plugins: [
    new VueLoaderPlugin(),
    new SpeedMeasurePlugin(),
    new HtmlWebpackPlugin({ template: "./public/index.html" }), //JS或者CSS文件可以自动引入到html中
  ],

范围优化

alias 配置路径别名,优化文件查找速度

javascript 复制代码
function pathResolve(dir) {
  return path.join(__dirname,dir)
}

resolve: {
  alias: {
    "@": pathResolve("src"),
    "page":pathResolve("src/page")
  },
},

extensions 文件扩展名配置,频率高的放在前面

javascript 复制代码
resolve: {
    extensions: [".js", ".css", ".vue"], //第一种配置后缀名
    extensions: [".vue", ".js", ".json", ".css"], //第二种配置后缀名
  },

modules 解析模块时应该搜索的目录

javascript 复制代码
 resolve: {
    // modules: ["node_modules", pathResolve("src")],
  },
javascript 复制代码
resolve: {
  modules: ["node_modules", pathResolve("src")],
},

externals 配置

配合 cdn 降低一些依赖打包构建

  • 不配置externals

安装 jquery

shell 复制代码
npm install jquery
javascript 复制代码
<template>
  <router-view></router-view>
</template>

<script>
import $ from 'jquery'
import {  cloneDeep } from "lodash";
export default {
  name: "App",
  mounted() {
    const aa = {
      ddd: () => {
        console.log(1111);
      },
    };
    console.log(cloneDeep(aa));

    console.log($('.app'))
  },
};
</script>

<style scoped></style>
  • 配置 externals
javascript 复制代码
externals: {
    jquery: 'jQuery',
  },
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script
      src="https://code.jquery.com/jquery-3.1.0.js"
      integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

noParse

防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中 不应该含有 <font style="color:rgb(43, 58, 66);">import</font>, <font style="color:rgb(43, 58, 66);">require</font>, <font style="color:rgb(43, 58, 66);">define</font> 的调用,或任何其他导入机制。忽略大型的 library 可以提高构建性能。

javascript 复制代码
module.exports = {
  //...
  module: {
    noParse: /jquery|lodash/,
  },
};

include/exclude

控制范围提高构建速度

  • **<font style="color:rgb(251, 112, 53);background-color:rgb(238, 238, 238);">include</font>**:符合条件的模块进行解析
  • **<font style="color:rgb(251, 112, 53);background-color:rgb(238, 238, 238);">exclude</font>**:排除符合条件的模块,不解析,优先级更高
javascript 复制代码
{ test: /\.js$/, exclude: /node_modules/,include: pathResolve('src'), loader: "babel-loader" },

IgnorePlugin

阻止为与正则表达式或过滤器函数匹配的 <font style="color:rgb(43, 58, 66);">import</font> 或 <font style="color:rgb(43, 58, 66);">require</font> 调用生成模块;

可以用于 momentjs 处理时区

多进程打包

thread-loader 使用时,需将此 loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。

每个 worker 都是一个独立的 node.js 进程,其开销大约为 600ms 左右。同时会限制跨进程的数据交换。

请仅在耗时的操作中使用此 loader!

缓存

js 缓存

javascript 复制代码
{
  test: /\.js$/,
    exclude: /node_modules/,
    include: pathResolve("src"),
    use: [
    {
      loader: "babel-loader", // 开启多进程打包
      options: {
        cacheDirectory: true,
      },
    },
  ],
},

样式缓存

添加 cache-loader

javascript 复制代码
{
  test: /\.less$/,
    use: [
    "style-loader",
    "cache-loader",
    "css-loader",
    "less-loader",
  ],
    },

持久化缓存

webpack5 开启 cache 缓存模块

javascript 复制代码
module.exports = {
  //...
  cache: {
    type: 'memory',
  },
};

打包体积

测试打包体积利用<font style="color:#DF2A3F;">webpack-bundle-analyzer</font>,打包时会开启本地构建每个包的大小

javascript 复制代码
const BundleAnalyzerPlugin =
  require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
module.exports = {
    plugins: [
    new VueLoaderPlugin(),
    // new SpeedMeasurePlugin(),
    new BundleAnalyzerPlugin(),
    new HtmlWebpackPlugin({ template: "./public/index.html" }), //JS或者CSS文件可以自动引入到html中
  ],
}

CSS 压缩

powershell 复制代码
npm install css-minimizer-webpack-plugin --save-dev
javascript 复制代码
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
  optimization: {
    minimize: true, // 开启后会在开发环境生效
    minimizer: [
      // 添加 css 压缩配置
      new CssMinimizerPlugin(),
    ],
  },Ï
}

JS 压缩

webpack5 内置了terser-webpack-plugin插件,所以我们不需重复安装,直接引用就可以了,具体配置如下

powershell 复制代码
module.exports = {
  
  optimization: {
    minimize: true, // 开发环境开启才生效
    minimizer: [
      new TerserPlugin({})
    ]
  },
}

TREE SHAKING 摇树

打包时不将项目中引入未使用的代码打包进去,在 package.json 中开启 sideEffects

powershell 复制代码
{
  sideEffects:false/true/[]
}
  • true 所有文件都有副作用,全都不可 <font style="background-color:rgb(238, 238, 238);">tree-shaking</font>
  • false 有这些文件有副作用,所有其他文件都可以 <font style="background-color:rgb(238, 238, 238);">tree-shaking</font>,但会保留这些文件
  • \[\] 选中的单位进行 <font style="color:rgb(85, 85, 85);">tree shaking</font>

GZIP 压缩

在构建过程中生成Gzip文件,从而减少传输到客户端的数据大小,提高加载速度。

powershell 复制代码
npm install compression-webpack-plugin --save-dev
javascript 复制代码
const CompressionWebpackPlugin = require('compression-webpack-plugin')

module.exports = {
  // 其他配置...
  plugins: [
    new CompressionWebpackPlugin({
      filename: '[path][base].gz', // 输出的Gzip文件名格式
      algorithm: 'gzip', // 使用gzip算法
      test: /\.js$|\.css$|\.html$/, // 哪些文件需要进行压缩
      threshold: 10240, // 只有文件大小大于该值时才会被压缩,默认是10KB
      minRatio: 0.8, // 压缩率小于这个值的资源将不会被压缩
      deleteOriginalAssets: false // 是否删除原文件,默认为false
    })
  ],
  
};

运行流畅度

运行流畅度优化的目的就是提升首屏的加载速度,方式有降低首屏加载文件体积,首屏不需要的文件进行预加载或者按需加载

splitChunks 分包

首屏分包利用浏览器的并发请求来提高首屏包的加载速度,<font style="color:rgb(44, 44, 54);">splitChunks</font> 允许我们将公共模块、第三方库等拆分到单独的 chunk 文件中,从而实现更细粒度的代码分割和缓存策略。

javascript 复制代码
module.exports = {
  // 其他配置...
  optimization: {
    splitChunks: {
      chunks: 'all', // 对所有类型的chunk进行处理(包括异步和非异步)
      minSize: 20000, // 形成一个新chunk最小的文件大小(单位:字节)
      maxSize: 0, // 最大尺寸目标,超过该值会尝试再分割,默认为0表示不启用
      minChunks: 1, // 模块至少应被共享的次数(即最少引用了多少次)
      maxAsyncRequests: 30, // 按需加载的最大并行请求数
      maxInitialRequests: 30, // 入口点处的最大并行请求数
      automaticNameDelimiter: '~', // 文件名连接符
      name(module, chunks, cacheGroupKey) {
        return cacheGroupKey + '_' + chunks.map(chunk => chunk.name).join('~');
      }, // 自定义chunk名称生成规则
      cacheGroups: { // 缓存组配置
        vendors: {
          test: /[\\/]node_modules[\\/]/, // 匹配node_modules下的模块
          priority: -10, // 优先级,数值越大优先级越高
          filename: 'vendors.js', // 输出文件名
          enforce: true, // 强制分割,即使未达到minSize条件也进行分割
        },
        default: {
          minChunks: 2, // 模块至少被引用两次才会被提取
          priority: -20,
          reuseExistingChunk: true, // 如果当前chunk包含已从主bundle中拆分出的模块,则重用而不是创建新的chunk
        },
      },
    },
  },
};

图片懒加载

利用 prefetch 和 preload 来优化大图片加载过慢问题

  • prefetch (预获取):浏览器空闲的时候进行资源的拉取
  • preload (预加载):提前加载后面会用到的关键资源
javascript 复制代码
import( /* webpackPrefetch: true */ './img')
import(/* webpackPreload: true */ './img');

总结

webpack 优化的三个目的速度,体积,流畅度在很多大项目中都是十分必要的,不管后续如何优化都万变不离其宗

相关推荐
DsirNg15 小时前
断点不该认识设备:组件布局的容器状态治理
css·前端工程化·组件化·响应式布局·css grid·设计系统·container queries
liangshanbo12151 天前
Webpack vs Vite 底层原理高频追问的问题
前端·webpack·node.js
liangshanbo12151 天前
面试题:AI 对话上下文超限怎么办?
面试·webpack·devops
liangshanbo12152 天前
Webpack 文件指纹面试题整理
前端·webpack·node.js
liangshanbo12152 天前
Webpack 常见 Plugin 面试题
前端·webpack·node.js
liangshanbo12152 天前
Webpack Tree Shaking 面试题整理
前端·webpack·node.js
陪我一起学编程2 天前
vue3笔记
前端·webpack·vue3·vite·脚手架·vue3笔记·组件式
liangshanbo12152 天前
Webpack的分包策略面试题
前端·webpack·node.js
liangshanbo12154 天前
面试题:如何优化 Webpack 的打包速度?
前端·webpack·node.js
DsirNg5 天前
让故障自己找到主人:前端错误的归并、反解与分派系统
可观测性·前端工程化·微前端·灰度发布·监控平台·错误治理·source map