CcbeanBlog CcbeanBlog
首页
  • 前端文章

    • JavaScript
    • HTML+CSS
    • Vue
    • React
  • 系列笔记

    • React使用学习
    • Vue2源码探究
  • Node文章

    • 基础
    • 问题
    • 框架
  • 系列笔记

    • 数据结构与算法
  • 构建工具文章

    • webpack
  • 系列笔记

    • Webpack5使用学习
  • MySQL
  • Linux
  • 网络
  • 小技巧
  • 杂记
  • 系列笔记

    • Protobuf Buffers
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Ccbean

靡不有初,鲜克有终
首页
  • 前端文章

    • JavaScript
    • HTML+CSS
    • Vue
    • React
  • 系列笔记

    • React使用学习
    • Vue2源码探究
  • Node文章

    • 基础
    • 问题
    • 框架
  • 系列笔记

    • 数据结构与算法
  • 构建工具文章

    • webpack
  • 系列笔记

    • Webpack5使用学习
  • MySQL
  • Linux
  • 网络
  • 小技巧
  • 杂记
  • 系列笔记

    • Protobuf Buffers
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 邂逅Webpack
  • Webpack的配置和处理CSS资源
  • Webpack加载和处理其它资源
  • Webpak模块化原理
  • Webpack中的source-map
  • Webpack中的babel
  • Webpack中的DevServer和HMR
  • Webpack环境分离和代码分离
  • Webpack中的DLL、Terser和ScopeHoisting
  • Webpack中的TreeShaking以及其它优化
  • Webpack打包分析
    • 打包时间分析
    • 打包文件分析
  • Webpack自定义Loader
  • Webpack自定义Plugin
  • 分析React和Vue脚手架
  • Gulp的使用
  • Rollup的使用
  • Vite的使用
  • Webpack5使用学习
ccbean
2022-06-21
目录

Webpack打包分析

# Webpack打包分析

# 打包时间分析

如果我们希望看到每一个loader、每一个Plugin消耗的打包时间,可以借助于插件speed-measure-webpack-plugin (opens new window)

注意:该插件在最新的webpack版本中存在一些兼容性的问题(和部分Plugin不兼容),暂时的做法是把不兼容的插件先删除掉,也就是不兼容的插件不显示它的打包时间,以便测试。

安装插件:

npm install speed-measure-webpack-plugin -D

这里注释掉不兼容插件mini-css-extract-plugin:
























 








 
 
 
 






























































const path = require('path');
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const PurgeCSSPlugin = require('purgecss-webpack-plugin');
const glob = require('glob');
const CompressionPlugin = require('compression-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasurePlugin();

const config = merge(baseConfig, {
  mode: "production",
  module: {
    rules: [
      {
        test: /\.css/i,
        use: [
          // MiniCssExtractPlugin.loader,
          'style-loader',
          'css-loader'
        ],
        sideEffects: true
      }
    ]
  },
  plugins: [
    // new MiniCssExtractPlugin({
    //   filename: 'css/[name].[contenthash:6].css',
    //   chunkFilename: 'css/[name].[contenthash:6].css'
    // }),
    new PurgeCSSPlugin({
      // src下所有目录下的所有文件
      paths: glob.sync(path.resolve(__dirname, '../src/**/*'), {nodir: true}),
      safelist: function() {
        // 不移除html和body的样式
        return {
          standard: ['html', 'body']
        }
      }
    }),
    new CompressionPlugin({
      test: /\.(css|js)$/, // 匹配压缩的文件
      threshold: 500, // 设置文件从多大开始压缩
      minRatio: 0.8, // 至少的压缩比例 达不到就不会压缩 优先于threshold
      algorithm: 'gzip', // 压缩算法
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      inject: 'body',
      cache: true, // 文件未改变时,不重新生成文件
      minify: {
        removeComments: true, // 是否要移除注释
        removeRedundantAttributes: false, // 是否移除多余的属性 input的type=text默认会被移除
        removeEmptyAttributes: true, // 是否移除一些空属性 如 <div id=""></div> id属性会被移除
        collapseWhitespace: false, // 折叠(移除)空格
        removeStyleLinkTypeAttributes: true, // 比如link中的type="text/css"
        keepClosingSlash: true, // 是否保持单元素的尾部
        minifyCSS: true, // 是否压缩内部style标签中的CSS
        minifyJS: { // 是否压缩script标签中的JS代码 利用的是Terser插件
          mangle: {
            toplevel: true
          }
        }
      }
    }),
    new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.+\.js$/])
  ],
  optimization: {
    usedExports: true,
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: false,
        terserOptions: {
          compress: {
            arguments: true
          },
          mangle: true,
          toplevel: true,
          keep_classnames: true,
          keep_fnames: true
        }
      }),
      new CssMinimizerPlugin()
    ],
    runtimeChunk: {
      name: 'runtime'
    }
  }
})

module.exports = smp.wrap(config);

执行打包后可在控制台看到如下结果,统计了总输出时间,各个插件和Loader运行时间,开发中可以做分析,确定哪一步影响了打包速度:

 SMP  ⏱  
General output time took 1.92 secs

 SMP  ⏱  Plugins
BundleAnalyzerPlugin took 0.437 secs
TerserPlugin took 0.23 secs
HtmlWebpackPlugin took 0.177 secs
CompressionPlugin took 0.004 secs
ProvidePlugin took 0.001 secs
(unable to deduce plugin name) took 0 secs
InlineChunkHtmlPlugin took 0 secs
CssMinimizerPlugin took 0 secs

 SMP  ⏱  Loaders
babel-loader took 0.741 secs
  module count = 5
css-loader took 0.075 secs
  module count = 1
style-loader, and
css-loader took 0.034 secs
  module count = 1
modules with no loaders took 0.031 secs
  module count = 7
html-webpack-plugin took 0.015 secs
  module count = 1

# 打包文件分析

Webpack文档bundle 分析 (opens new window)中介绍了多个分析工具,这里介绍两种方案。

第一种方案是使用 官方分析工具 (opens new window),首先需要生成待分析的JSON文件:

"scripts": {
  "stats": "webpack --config ./config/webpack.prod.js --profile --json stat.json'",
},

--profile、--json以JSON文件格式输出stat.json,然后将文件上传到官方分析工具即可查看分析结果。

第二种方案是使用插件webpack-bundle-analyzer (opens new window),安装插件:

npm install webpack-bundle-analyzer -D

该插件支持很多配置,可在文档中查看具体配置

webpack配置中使用插件:

const path = require('path');
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const PurgeCSSPlugin = require('purgecss-webpack-plugin');
const glob = require('glob');
const CompressionPlugin = require('compression-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = merge(baseConfig, {
  mode: "production",
  module: {
    rules: [
      {
        test: /\.css/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'
        ],
        sideEffects: true
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:6].css',
      chunkFilename: 'css/[name].[contenthash:6].css'
    }),
    new PurgeCSSPlugin({
      // src下所有目录下的所有文件
      paths: glob.sync(path.resolve(__dirname, '../src/**/*'), {nodir: true}),
      safelist: function() {
        // 不移除html和body的样式
        return {
          standard: ['html', 'body']
        }
      }
    }),
    new CompressionPlugin({
      test: /\.(css|js)$/, // 匹配压缩的文件
      threshold: 500, // 设置文件从多大开始压缩
      minRatio: 0.8, // 至少的压缩比例 达不到就不会压缩 优先于threshold
      algorithm: 'gzip', // 压缩算法
      // include:
      // exclude:
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      inject: 'body',
      cache: true, // 文件未改变时,不重新生成文件
      // minify: false // 开发环境下,默认值
      minify: {
        removeComments: true, // 是否要移除注释
        removeRedundantAttributes: false, // 是否移除多余的属性 input的type=text默认会被移除
        removeEmptyAttributes: true, // 是否移除一些空属性 如 <div id=""></div> id属性会被移除
        collapseWhitespace: false, // 折叠(移除)空格
        removeStyleLinkTypeAttributes: true, // 比如link中的type="text/css"
        keepClosingSlash: true, // 是否保持单元素的尾部
        minifyCSS: true, // 是否压缩内部style标签中的CSS
        minifyJS: { // 是否压缩script标签中的JS代码 利用的是Terser插件
          mangle: {
            toplevel: true
          }
        }
      }
    }),
    new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.+\.js$/]),
    new BundleAnalyzerPlugin()
  ],
  optimization: {
    usedExports: true,
    minimize: true,
    minimizer: [
      new TerserPlugin({
        extractComments: false,
        terserOptions: {
          compress: {
            arguments: true
          },
          mangle: true,
          toplevel: true,
          keep_classnames: true,
          keep_fnames: true
        }
      }),
      new CssMinimizerPlugin()
    ],
    runtimeChunk: {
      name: 'runtime'
    }
  }
});

执行npm run build时,这个工具会在8888端口上建立服务,访问该服务可以直接的看到每个包的大小。

  • 比如有一个包时通过一个Vue组件打包的,但是非常的大,那么我们可以考虑是否可以拆分出多个组件,并且对其进行懒加载;
  • 比如一个图片或者字体文件特别大,是否可以对其进行压缩或者其他的优化处理;
编辑 (opens new window)
上次更新: 2022/06/21, 20:13:11
Webpack中的TreeShaking以及其它优化
Webpack自定义Loader

← Webpack中的TreeShaking以及其它优化 Webpack自定义Loader→

最近更新
01
阅读精通正则表达式总结
09-29
02
项目搭建规范的配置
07-15
03
Vite的使用
07-03
更多文章>
Theme by Vdoing | Copyright © 2018-2023 Ccbeango
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式