webpack5项目优化

142 阅读2分钟
webpack优化——手把手教你优化webpack

概述

关于webpack常见的性能优化,我们可以从两个方面去着手考虑:
1.传输性能优化;通过优化代码体积等手段提高资源传输速度,达到优化目的;
2.构建过程优化;主要是提高webpack的打包速度;

一、传输性能优化

Tree Shaking

Webpack 已经默认开启了这个功能,无需其他配置

// package.json
  "sideEffects": [
    "**/*.css"
  ]

CDN加载库文件

//html
  <% for (let i in htmlWebpackPlugin.options.cdns) { %>
    <script  src="<%= htmlWebpackPlugin.options.cdns[i] %>"></script>
  <% } %>

//config
plugins:[
    new HtmlWebpackPlugin({
      title:'demo webpack5',
      template:'./src/index.html',
      cdns:['https://cdn.bootcss.com/jquery/3.4.1/jquery.js']
    })
]

//externals
  externals:{
    jquery:'jQuery'
  },

开放gzip压缩

const CompressionWebpackPlugin = require('compression-webpack-plugin');

      new CompressionWebpackPlugin({
        exclude: /.(html|map)$/i
      }),

缓存开放

  cache:{
    type:'filesystem'
  },

懒加载

//路由懒加载
component: () => import("@/views/pages/advertise/AdvertisePage.vue")

文件图片压缩

Babel

  1. 下载包:npm i @babel/plugin-transform-runtime -D
  2. 在babel-loader中添加:
{
  loader: "babel-loader",
  options: {
    plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
  },
},

提取重复代码,对模块都进行分割

optimization: {
  // 代码分割配置
  splitChunks: {
    chunks: "all", // 对所有模块都进行分割
    // 以下是默认值
    // minSize: 20000, // 分割代码最小的大小
    // minRemainingSize: 0, // 类似于minSize,最后确保提取的文件大小不能为0
    // minChunks: 1, // 至少被引用的次数,满足条件才会代码分割
    // maxAsyncRequests: 30, // 按需加载时并行加载的文件的最大数量
    // maxInitialRequests: 30, // 入口js文件最大并行请求数量
    // enforceSizeThreshold: 50000, // 超过50kb一定会单独打包(此时会忽略minRemainingSize、maxAsyncRequests、maxInitialRequests)
    // cacheGroups: { // 组,哪些模块要打包到一个组
    //   defaultVendors: { // 组名
    //     test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
    //     priority: -10, // 权重(越大越高)
    //     reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
    //   },
    //   default: { // 其他没有写的配置会使用上面的默认值
    //     minChunks: 2, // 这里的minChunks权重更大
    //     priority: -20,
    //     reuseExistingChunk: true,
    //   },
    // },
    // 修改配置
    cacheGroups: {
      // 组,哪些模块要打包到一个组
      // defaultVendors: { // 组名
      //   test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
      //   priority: -10, // 权重(越大越高)
      //   reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
      // },
      default: {
        // 其他没有写的配置会使用上面的默认值
        minSize: 0, // 我们定义的文件体积太小了,所以要改打包的最小文件体积
        minChunks: 2,
        priority: -20,
        reuseExistingChunk: true,
      },
    },
  },

按需加载,动态导入。异步加载

console.log("hello main");
document.getElementById("btn").onclick = function () {
  // 动态导入 --> 实现按需加载
  // 即使只被引用了一次,也会代码分割
  import("./math.js").then(({ sum }) => {
    alert(sum(1, 2, 3, 4, 5));
  });
};

二、构建过程优化

打包时间、体积分析

  1. 安装插件
npm i -D speed-measure-webpack-plugin
npm i -D webpack-bundle-analyzer
  1. 配置webpack.config.js
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
//smp.wrap时间分析要包裹配置文件
module.exports = smp.wrap({
  // ...
  plugins:[
    //体积分析
    new BundleAnalyzerPlugin({
      analyzerMode:'disabled',
      generateStatsFile:true,
    })
  ]
});
  1. 运行命令
// package.json scripts下面加,启动体积分析服务
// "analyzer":"webpack-bundle-analyzer --port 8888 ./dist/stats.json"

开发模式

cheap-module-source-map:打包编译速度快,只包含行映射。source-map:包含行/列映射

module.exports = {
  // 其他省略
  mode: "development",
  devtool: "cheap-module-source-map",
};

热模块替换

hot: true, // 开启HMR功能(只能用于开发环境,生产环境不需要了)

OneOf

用{oneOf: [ ]}把所有test包住,生产模式也是如此配置。

rules: [
  {
    oneOf: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      ……
    ]
  }
]

Include/Exclude 缩小搜索范围,提高性能

{
  test: /\.js$/,
  // exclude: /node_modules/, // 排除node_modules代码不编译
  include: path.resolve(__dirname, "../src"), // 也可以用包含
  loader: "babel-loader",
},

new ESLintWebpackPlugin({
  // 指定检查文件的根目录
  context: path.resolve(__dirname, "../src"),
  exclude: "node_modules", // 默认值
}),

Cache开起缓存,提高二次构建速度

{
  test: /\.js$/,
  // exclude: /node_modules/, // 排除node_modules代码不编译
  include: path.resolve(__dirname, "../src"), // 也可以用包含
  loader: "babel-loader",
  options: {
    cacheDirectory: true, // 开启babel编译缓存
    cacheCompression: false, // 缓存文件不要压缩
  },
}
……
new ESLintWebpackPlugin({
  // 指定检查文件的根目录
  context: path.resolve(__dirname, "../src"),
  exclude: "node_modules", // 默认值
  cache: true, // 开启缓存
  // 缓存目录
  cacheLocation: path.resolve(
    __dirname,
    "../node_modules/.cache/.eslintcache"
  ),
}),

Thread开启多进程同时处理 js 文件

  1. 下载包:npm i thread-loader -D
  2. 引入:const ThreadLoader = require("thread-loader");
  3. 配置:
// nodejs核心模块,直接使用
const os = require("os");
// cpu核数
const threads = os.cpus().length;
const TerserPlugin = require("terser-webpack-plugin");// 压缩js
……
{
  test: /\.js$/,
  // exclude: /node_modules/, // 排除node_modules代码不编译
  include: path.resolve(__dirname, "../src"), // 也可以用包含
  use: [
    {
      loader: "thread-loader", // 开启多进程
      options: {
        workers: threads, // 数量
      },
    },
    {
      loader: "babel-loader",
      options: {
        cacheDirectory: true, // 开启babel编译缓存
      },
    },
  ],
},
……
plugins: [
  new ESLintWebpackPlugin({
    // 指定检查文件的根目录
    context: path.resolve(__dirname, "../src"),
    exclude: "node_modules", // 默认值
    cache: true, // 开启缓存
    // 缓存目录
    cacheLocation: path.resolve(
      __dirname,
      "../node_modules/.cache/.eslintcache"
    ),
    threads, // 开启多进程
  }),
  // css压缩和放到optimization一样
  // new CssMinimizerPlugin(),
],
optimization: {
  minimize: true,
  minimizer: [
    // css压缩也可以写到optimization.minimizer里面,效果一样的
    new CssMinimizerPlugin(),
    // 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了
    new TerserPlugin({
      parallel: threads // 开启多进程
    })
  ],
},