关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

Webpack4 性能优化实践 #108

发布时间:2023-06-27 18:00:44

为什么需要性能优化


在使用 时,如果不注意性能优化,可能会产生性能问题,会导致在开发体验上不是非常丝滑,性能问题主要是编译速度慢,打包体积过大,因此性能优化也主要从这些方面来分析。本文主要是自己平时的工作积累和参考别人的文章,而进行总结,基于 版本。WebpackWebpack4


构建分析


编译速度分析

对 构建速度进行优化的首要任务就是去知道哪些地方值得我们注意。

插件能够测量 Webpack 构建速度Webpackspeed-measure-webpack-plugin

SMP ⏱ General output time took 38.3 secs  SMP ⏱ Plugins HtmlWebpackPlugin took 1.31 secs CopyPlugin took 0.016 secs OptimizeCssAssetsWebpackPlugin took 0.002 secs ContextReplacementPlugin took 0.001 secs MiniCssExtractPlugin took 0 secs DefinePlugin took 0 secs  SMP ⏱ Loaders _babel-loader@8.1.0@babel-loader took 29.98 secs  module count = 1503 _babel-loader@8.1.0@babel-loader, and _eslint-loader@3.0.4@eslint-loader took 18.74 secs  module count = 86 _css-loader@3.6.0@css-loader, and _less-loader@5.0.0@less-loader took 16.45 secs  module count = 64 modules with no loaders took 2.24 secs  module count = 7 _file-loader@5.1.0@file-loader took 1.03 secs  module count = 17 _style-loader@1.3.0@style-loader, and _css-loader@3.6.0@css-loader, and _less-loader@5.0.0@less-loader took 0.102 secs  module count = 64 _html-webpack-plugin@3.2.0@html-webpack-plugin took 0.021 secs  module count = 1

   

居然达到了惊人的 38.3 秒,虽然有点不是很准确,但是非常慢。发现 占据了大头。babel-loader、eslint-loader、css-loader、less-loader

const webpackBase = require('./webpack.base.conf'); const path = require('path'); const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin'); const smp = new SpeedMeasureWebpackPlugin(); module.exports = smp.wrap({  // 配置源码显示方式  devtool: 'eval-source-map',  mode: 'development',  entry: {  app: ['./src/index.jsx']  },  output: {  path: path.resolve(__dirname, 'dist'),  filename: 'index.js'  },  resolve: webpackBase.resolve,  module: webpackBase.module,  stats: webpackBase.stats,  optimization: webpackBase.optimization,  plugins: [  webpackBase.plugins.html,  webpackBase.plugins.miniCssExtract,  webpackBase.plugins.optimizeCssAssets,  // webpackBase.plugins.progressBarPlugin,  webpackBase.plugins.ContextReplacementPlugin,  webpackBase.plugins.DefinePlugin,  // webpackBase.plugins.AntdDayjsWebpackPlugin,  webpackBase.plugins.CopyPlugin  // webpackBase.plugins.HotModuleReplacementPlugin  ],  devServer: webpackBase.devServer,  watchOptions: webpackBase.watchOptions,  externals: webpackBase.externals });

   


打包体积分析

通过 插件能够在 构建结束后生成构建产物体积报告,配合可视化的页面,能够直观知道产物中的具体占用体积。webpack-bundle-analyzerWebpack

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = {  plugins: bundleAnalyzer: new BundleAnalyzerPlugin({ analyzerPort: 8081 })], };

   

效果图如下:

可以看出一个很明显的问题就是 这些库,没有排除。Ant Design、TRTC、Mobx

打包体积如下:


如何优化


缩小构建目标

  • 优化 配置(减少模块搜索层级和不必要的编译工作)resolve.modules
  • 优化 配置resolve.extensions
  • 增加缓存
const path = require('path'); module.exports = {  resolve: {  // 自动解析确定的扩展  extensions: ['.js', '.jsx', '.css', '.less', '.json'],  alias: {  // 创建 import 或 require 的别名,来确保模块引入变得更简单  'react': path.resolve( __dirname ,'./node_modules/react/dist/react.min.js')  },  // 当从 npm 包导入模块时,此选项将决定在 `package.json` 中使用哪个字段导入模块  // 默认值为 browser -> module -> main  mainFields: ['main']  },  module: {  rules: [  {  // 排除node_modules模块  test: /\.(js|jsx)$/,  exclude: /node_modules/,  // 开启缓存  loader: 'babel-loader?cacheDirectory=true'  }  ]  } };

   


使用 thread-loader,开启多进程

thread-loader 会将你的 放置在一个 池里面运行,每个 都是一个单独的有 600ms 限制的 进程。同时跨进程的数据交换也会被限制。请在高开销的 中使用,否则效果不佳。loaderworkerworkernode.jsloader

module.exports = {  module: {  rules: [  {  test: /\.js$/,  include: path.resolve('src'),  use: [  'thread-loader',  // your expensive loader (e.g babel-loader)  ],  },  ],  }, };

   


使用 hard-source-webpack-plugin

在 是 的更好替代者。Webpack4中,hard-source-webpack-pluginDLL

hard-source-webpack-plugin 是 的插件,为模块提供中间缓存步骤。为了查看结果,您需要使用此插件运行 两次:第一次构建将花费正常的时间。第二次构建将显着加快(大概提升 90% 的构建速度)。不过该插件很久没更新了,不太建议使用。WebpackWebpack


去掉 eslint-loader

由于我项目中使用了 如果配置了 ,其实可以去掉的。eslint-loaderprecommit


通过 externals 把相关的包,排除

Webpack

module.exports = {  // externals 排除对应的包,注:排除掉的包必须要用script标签引入下  externals: {  react: 'React',  'react-dom': 'ReactDOM',  'trtc-js-sdk': 'TRTC',  bizcharts: 'BizCharts',  antd: 'antd',  mobx: 'mobx',  'mobx-react': 'mobxReact'  } };

   

index.html

    <meta  name="viewport"  content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"  />   <link  rel="stylesheet"  href="https://xxx/antd.min3.26.20.css"  />  webpack <script  type="text/javascript"  src="https://xxx/17.0.0react.production.min.js"  > <script  type="text/javascript"  src="https://xxx/17.0.0react-dom.production.min.js"  > <script  type="text/javascript"  src="https://xxx/BizCharts3.5.8.js"  > <script  type="text/javascript"  src="https://xxx/trtc4.6.7.js"  > <script  type="text/javascript"  src="https://xxx/moment2.29.1.min.js"  > <script  type="text/javascript"  src="https://xxx/moment2.29.1zh-cn.js"  > <script  type="text/javascript"  src="https://xxx/polyfill.min7.8.0.js"  > <script  type="text/javascript"  src="https://xxx/antd.min3.26.20.js"  > <script  type="text/javascript"  src="https://xxx/mobx.umd.min5.13.1.js"  > <script  type="text/javascript"  src="https://xxx/mobx-react.index.min5.4.4.js"  >

   


JS 压缩

从 开始,默认情况下使用 是一款兼容 的 压缩器。与 (许多项目的早期标准)相比,它是面向未来的选择。有一个 的分支—— ,但由于它不再维护,于是就从这个分支诞生出了一个独立分支,它就是 。Webpack4terser压缩生产环境下的输出结果。TerserES2015 +JavaScriptUglifyJSUglifyJSuglify-esterser

const TerserPlugin = require('terser-webpack-plugin'); module.exports = {  optimization: {  minimizer: [  // 压缩js  new TerserPlugin({  test: /\.(jsx|js)$/,  extractComments: true,  parallel: true,  cache: true  })  ]  }, };

   


CSS 压缩

Webpack 4.0 以后,官方推荐使用 插件来打包 文件。mini-css-extract-pluginCSS

const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = {  module: {  rules: [  {  test: /\.(css|less)$/,  use: [MiniCssExtractPlugin.loader]  }  ]  }, };

   


FAQ


Ant Design 无法加载

请确保加载顺序, 放在 前面加载Moment、PolyfillAnt Design


MobX 无法加载

MobX 引入 需要引入mobx.umd.min.js库,mobx-react


package.json


{  "name": "webpack",  "version": "1.0.0",  "private": true,  "main": "index.js",  "dependencies": {  "antd": "^3.26.20",  "babel-eslint": "^10.0.3",  "babel-loader": "^8.0.0",  "babel-plugin-import": "^1.13.0",  "babel-plugin-react-css-modules": "^5.2.6",  "bizcharts": "^3.5.8",  "china-division": "^2.3.1",  "compression-webpack-plugin": "^3.0.1",  "copy-webpack-plugin": "^5.1.1",  "css-loader": "^3.2.0",  "eslint": "^6.8.0",  "eslint-config-prettier": "^6.11.0",  "eslint-config-standard": "^14.1.0",  "eslint-loader": "^3.0.4",  "eslint-plugin-import": "^2.20.0",  "eslint-plugin-promise": "^4.2.1",  "eslint-plugin-react": "^7.17.0",  "eslint-plugin-standard": "^4.0.1",  "html-webpack-plugin": "^3.2.0",  "less": "^3.8.1",  "less-loader": "^5.0.0",  "lint-staged": "^10.0.8",  "mini-css-extract-plugin": "^0.8.0",  "mobx": "^5.13.1",  "mobx-react": "^5.4.4",  "optimize-css-assets-webpack-plugin": "^5.0.1",  "pre-commit": "^1.2.2",  "progress-bar-webpack-plugin": "^1.12.1",  "react": "^17.0.0",  "react-dom": "^17.0.0",  "speed-measure-webpack-plugin": "^1.3.1",  "style-loader": "^1.2.1",  "terser-webpack-plugin": "^2.2.1",  "trtc-js-sdk": "^4.6.7",  "viewerjs": "^1.5.0",  "webpack": "^4.41.2",  "webpack-bundle-analyzer": "^3.6.0",  "webpack-cli": "^3.3.10",  "webpack-dev-server": "^3.10.1"  } }

   


最终效果


打包体积:

打包体积由原先 2.1M 变成了 882KB,可以说效果非常巨大。

包依赖:

Ant Design、TRTC、Mobx 这些库也没了

编译速度:

SMP ⏱ General output time took 10.67 secs  SMP ⏱ Plugins HtmlWebpackPlugin took 1.69 secs BundleAnalyzerPlugin took 0.091 secs CopyPlugin took 0.011 secs MiniCssExtractPlugin took 0.003 secs OptimizeCssAssetsWebpackPlugin took 0.002 secs DefinePlugin took 0.001 secs ContextReplacementPlugin took 0 secs  SMP ⏱ Loaders _babel-loader@8.1.0@babel-loader took 8.26 secs  module count = 277 _babel-loader@8.1.0@babel-loader, and _eslint-loader@3.0.4@eslint-loader took 7.18 secs  module count = 86 _css-loader@3.6.0@css-loader, and _less-loader@5.0.0@less-loader took 1.94 secs  module count = 28 modules with no loaders took 0.728 secs  module count = 12 _file-loader@5.1.0@file-loader took 0.392 secs  module count = 17 _style-loader@1.3.0@style-loader, and _css-loader@3.6.0@css-loader, and _less-loader@5.0.0@less-loader took 0.052 secs  module count = 28 _html-webpack-plugin@3.2.0@html-webpack-plugin took 0.026 secs  module count = 1

   

编译速度由原先 38.3 秒(实际编译速度大概 15 秒左右),减少到 10.67 秒(实际编译速度 10 秒左右)。


国内外公共 CDN 地址


  • 引导CDN
  • 中新社

参考资料


  • 网络包指南
  • Webpack 核心知识有哪些?

/template/Home/leiyu/PC/Static