学习日记 webpack优化

140 阅读5分钟

优化

想要优化的话要看是哪一步出现了问题

分析工具

1. speed-measure-webpack-plugin 分析打包的速度

1.1 安装

pnpm install speed-measure-webpack-plugin -D

1.2 在vue.config.js中修改配置

const { defineConfig } = require("@vue/cli-service");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: smp.wrap({}),
});

1.3 执行命令

npm run build

看到SMP 就成功了

截屏2024-01-26 13.46.16.png

2. webpack-bundle-analyzer 分析打包后的文件体积大小

2.1 安装

pnpm i webpack-bundle-analyzer -D

2.2 在plugins中配置

const { defineConfig } = require("@vue/cli-service");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const smp = new SpeedMeasurePlugin();
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: smp.wrap({
    plugins: [
      new BundleAnalyzerPlugin()
    ]
  }),
});

打包之后就能看到结果

3. 缩小范围

3.1 extension

配置resolve中的extension可以缩小文件的查找范围,在require或者是import的时候不需要写扩展名,会自动进行查找

const { defineConfig } = require("@vue/cli-service");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const smp = new SpeedMeasurePlugin();
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: smp.wrap({
    resolve: {
      extensions: ['.js', '.vue', 'ts', 'json', 'jsx']
    },
    plugins: [
      new BundleAnalyzerPlugin()
    ]
  }),
});

3.2 设置别名可以加快webpack的查找速度

就是直接给一个路径解析,而不是让webpack自己去查找,加快了速度

module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: smp.wrap({
    resolve: {
      extensions: ['.js', '.vue', 'ts', 'json', 'jsx'],
      alias: {
        '@': join(__dirname, 'src'),
        'assets': join(__dirname, 'src/assets')
      }
    },
    plugins: [
      new BundleAnalyzerPlugin()
    ]
  }),
});

3.3 modules

  • 告诉webpack在解析模块的时候搜索哪些目录,可以使用相对路径和绝对路径.

  • 相对路径的扫描方式与Node扫描node_modules的方式类似,都是通过当前目录及其祖先就是(./node_modules. ../node_modules等)进行扫描,

  • 绝对路径的话,只会在指定目录中查找

  • 一般不需要配置,当你的项目中有指定的目录让webpack找的话,就可以配置。默认是找node_modules

const { defineConfig } = require("@vue/cli-service");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { join } = require('path')
const smp = new SpeedMeasurePlugin();
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: smp.wrap({
    resolve: {
      extensions: ['.js', '.vue', 'ts', 'json', 'jsx'],
      alias: {
        '@': join(__dirname, 'src'),
        'assets': join(__dirname, 'src/assets')
      },
                        // 默认就是node_modules 不需要配置。有需求才配置 这里只是知道有这个知识点
      modules: ['node_modules']
    },
    plugins: [
      new BundleAnalyzerPlugin()
    ]
  }),
});

4. compression-webpack-plugin 压缩插件

compression-webpack-plugin

4.1 安装

pnpm add -D compression-webpack-plugin

4.2 属性

名称默认值描述
testundefined匹配哪些后缀的文件
includeundefined符合条件的所有资源
excludeundefined排除负荷条件的资源
algorithmgzip事实上就是zlib
compressionOptions
threshold0文件大小超过多少才压缩
minRatio0.8压缩大小/原始大小 小于等于设置的比例
filename"[path][base].gz”文件名
deleteOriginalAssetsfalse是否删除dist中原始的资源

4.3 配置

const { defineConfig } = require("@vue/cli-service");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const CompressionPlugin = require("compression-webpack-plugin");
const { join } = require("path");
const smp = new SpeedMeasurePlugin();
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: smp.wrap({
    resolve: {
      extensions: [".js", ".vue", "ts", "json", "jsx"],
      alias: {
        "@": join(__dirname, "src"),
        assets: join(__dirname, "src/assets"),
      },
      modules: ["node_modules"],
    },
    plugins: [
      new BundleAnalyzerPlugin(),
      new CompressionPlugin({
        test: /\.(vue|js|ts|json|css)$/, // 什么文件需要压缩
        exclude: "node_modules", // 排除什么
        algorithm: "gzip", // 默认是gzip 其实是node那个模块zlib
        threshold: 90, // 文件大小超过多少会被压缩
        minRatio: 0.8, // 压缩大小/当前大小-> 小于0.8才会被处理 默认0.8
        filename(pathData) {
          if (/\.(png|svg|jpg)$/.test(pathData.filename)) {
            return "assets/svg/[path][base].gz";
          }
          return "[path][base].gz";
        }
      }),
    ],
  }),
});

可以看到压缩的效果还是可以的

截屏2024-01-26 15.21.16.png

虽然压缩了但是在服务器上怎么访问呢 打包后的文件都是.gz结尾的,怎么处理呢?于是我把文件放在了nginx的html目录下

截屏2024-01-26 16.23.48.png

修改了代理配置

vi /etc/nginx/nginx.conf

加了这个属性 就能直接访问了

截屏2024-01-26 16.25.39.png

就正常返回了

截屏2024-01-26 16.26.39.png

5. terser-webpack-plugin 多进程打包

  • 并发次数 os.cpus().length - 1

5.1 安装

pnpm add -D terser-webpack-plugin

5.2 选项

名称默认值描述
testundefined匹配哪些后缀的文件
includeundefined符合条件的所有资源
excludeundefined排除负荷条件的资源
algorithmgzip事实上就是zlib
compressionOptions{}
threshold0文件大小超过多少才压缩
minRatio0.8压缩大小/原始大小 小于等于设置的比例
filename"[path][base].gz”文件名
deleteOriginalAssetsfalse是否删除dist中原始的资源

5.3 配置

const { defineConfig } = require("@vue/cli-service");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const CompressionPlugin = require("compression-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { join } = require("path");
const smp = new SpeedMeasurePlugin();
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: smp.wrap({
    ...
    optimization: {
      minimizer: [
        new TerserPlugin({
          parallel: true,
          terserOptions: {},
        }),
      ],
    },
  }),
});

6.sourcemap

  • 一般情况下,我们不希望任何人都可以在浏览器中直接能看到我们未编译的源码,所以我们不希望提供sourceMap, 但是我们需要sorceMap来定义我们的错误信息
  • 设置hidden-source-map
  • 一方面webpack会生成sourcemap文件以提供给错误收集工具比如sentry,另一方面又不会为 bundle 添加引用注释,以避免浏览器使用

7. 将通用的三方库打包成vendor

  • 他们的体积是不会变化的
  • 所以可以利用缓存 只是开发环境
  • 生产环境不用这个缓存
const smp = new SpeedMeasurePlugin();
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: smp.wrap({
    ...
    entry: {
      vendor: ['element-plus']
    },
    ...
  }),
});

8. image-webpack-loader 压缩图片

  • 关于图片的处理,要让UI给出压缩后的图片.
  • 相同的图片质量,webp格式的图片比较小.
  • 压缩图片jpg,webp这种像首页的背景图这种通过image-webpack-loader压缩.
  • 项目中的svg图片很多要考虑做成雪碧图当成组件来引用,并且也是可以压缩的.
const { defineConfig } = require("@vue/cli-service");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const CompressionPlugin = require("compression-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { join } = require("path");
const smp = new SpeedMeasurePlugin();
module.exports = defineConfig({
  transpileDependencies: true,
  publicPath: '.', // 打包出来的index.html中引入的js,css不会出现找不到问题
  configureWebpack: smp.wrap({
    devtool: "hidden-source-map",
    entry: {
      vendor: ["element-plus"],
    },
    output: {
      assetModuleFilename: 'assets/[name][ext]'
    },
    resolve: {
      extensions: [".js", ".vue", ".ts", ".json", ".jsx"],
      alias: {
        "@": join(__dirname, "src"),
        assets: join(__dirname, "src/assets"),
      },
      modules: ["node_modules"],
    },
    module: {
      rules: [
        {
          test: /\.(gif|png|jpe?g|svg)$/i,
          use: [
            "file-loader",
            {
              loader: "image-webpack-loader",
              options: {
                mozjpeg: {
                  progressive: true,
                },
                // optipng.enabled: false will disable optipng
                optipng: {
                  enabled: false,
                },
                pngquant: {
                  quality: [0.65, 0.9],
                  speed: 4,
                },
                gifsicle: {
                  interlaced: false,
                },
                // the webp option will enable WEBP
                webp: {
                  quality: 75,
                },
              },
            },
          ],
        },
      ],
    },
   ...
  }),
});

看了issue,推荐用image-minimizer-webpack-plugin这个loader

截屏2024-01-27 00.41.06.png