性能优化之webpack层面优化

本文介绍如何通过合理配置Webpack来优化前端项目,包括解决第三方包重复引用、利用tree-shaking减少打包体积、开启gzip压缩、实现路由及组件懒加载、优化图片资源等方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、第三方包重复引用解决方案

主项目依赖了lodash

// package.json
{
  "name": "project-name",
  "version": "1.0.0",
  "dependencies": {
    "lodash": "^4.17.21",
    "test": "^1.0.2"
  }
}

主项目依赖了test,test又依赖lodash

// node_modules/test/package.json
{
  "name": "test",
  "version": "1.0.2",
  "dependencies": {
    "lodash": "4.17.19"
  }
}
├── node_modules
│   ├──lodash@4.17.21
│   ├──test
│   │   ├── node_modules
|   |   │   ├──lodash@4.17.19

在编译构建期间,两个版本的 lodash 依赖都会打包到产物中,导致第三方包重复引用。

查看两者是否兼容

1.在 webpack 配置中设置 resolve.alias
// webpack.config.js
alias: {
  lodash: path.resolve(__dirname, './node_modules/lodash'),
}
2.yarn resolutions 统一版本

(注意, 该 resolution 字段只能在项目的根目录下设置)
然后 yarn install 即可

// package.json
{
  "name": "project-name",
  "version": "1.0.0",
  "dependencies": {
    "lodash": "^4.17.21",
    "test": "^1.0.2"
  }
  "resolutions": {
     "lodash": "4.17.21",
  }
}

3、 cdn外部引入

externals加载外部资源

操作对象
 configureWebpack: {
    externals: {
      vue: 'Vue',
      'vue-router': 'VueRouter',
      vuex: 'Vuex',
      'element-ui': 'ELEMENT',
      echarts: 'echarts'
    },

2、删除不必要的第三方包

在这个例子中,
在第三方包的 package.json 中正确配置了 sideEffects 的情况下,
代码最后打包的时候被删掉了,
没有正确配置就没有删掉

3、 tree-sharking

应为lodash antd 体积过大,检查按需引入,treeshaking有没有生效

使用webpack插件 例如 tree-sharking进行剔除无关的依赖加载
使用terser进行代码压缩,给执行时间长的loader加 cache-loader,
可以使得下次打包就会使用 node_modules/.cache 里的
依赖于ES6的模块特性,ES6模块依赖关系是确定的,和运行时的状态无关,
可以进行可靠的静态分析,这就是 tree-shaking 的基础
export default 导出的是一个对象,无法通过静态分析判断出一个对象的哪些变量未被使用,
所以 tree-shaking 只对使用 export 导出的变量生效
这也是函数式编程越来越火的原因,因为可以很好利用 tree-shaking 精简项目的体积,
也是 vue3 全面拥抱了函数式编程的原因之一

tree-shaking需要正确配置sideEffects
  "sideEffects": [
    "*.css",
    "*.scss"
  ]
.css和.scss文件都列为没有副作用,因为它们只是导出了样式,
没有对其他模块产生影响,因此可以被tree-shaking移除。

cache-loader

提高Webpack构建性能的loader,提高构建速度

4、Cache invalidation

具体优化:
https://vdavid-gilbertson.medium.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758

// contenthash 的结果是根据最终生成的文件内容生成 hash,
可以确保在资源内容没有变更的情况下,保持文件名的一致,避免缓存失效。
module.exports = {
    output: {
        filename: '[name].[contenthash:8].js,
    }
}
contenthash可以与协商缓存和强缓存配合使用,以实现更好的缓存效果

5、开启gzip

npm i -D compression-webpack-plugin

"use strict";
const path = require("path");
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = ["js", "css"];
 
function resolve(dir) {
  return path.join(__dirname, dir);
}
 
const name = "品牌联盟";
 
module.exports = {
  lintOnSave: process.env.NODE_ENV === "development",
  configureWebpack: {
    name: name,
    resolve: {
      alias: {
        "@": resolve("src"),
        "@i": resolve("src/api"),
        "@c": resolve("src/components"),
        "@v": resolve("src/pages"),
        "@s": resolve("src/static"),
        "@u": resolve("src/utils")
      }
    },
    plugins: [
      new CompressionWebpackPlugin({
        filename: "[path].gz[query]",
        algorithm: "gzip",
        test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"), //匹配文件名
        threshold: 10240, //对10K以上的数据进行压缩
        minRatio: 0.8,
        deleteOriginalAssets: false //是否删除源文件
      })
    ]
  }
};

6、路由懒加载

路由改成按需加载
webpackchunkname
Vue中运用import的懒加载语句以及webpack的魔法注释,
在项目进行webpack打包的时候,
对不同模块进行代码分割,在首屏加载时,
用到哪个模块再加载哪个模块,实现懒加载进行页面的优化。

// 通过webpackChunkName设置分割后代码块的名字
const Home = () => import(/* webpackChunkName: "home" */ "@/views/home/index.vue");

7、组件懒加载

web.dev官方文档
https://web.dev/code-splitting-suspense/?utm_source=lighthouse&utm_medium=devtools

8、UI组件库按需加载

import dialogInfo from '@/components/dialogInfo';
export default {
  name: 'homeView',
  components: {
    dialogInfo
  }
}


const dialogInfo = () => import(/* webpackChunkName: "dialogInfo" */ '@/components/dialogInfo');
export default {
  name: 'homeView',
  components: {
    dialogInfo
  }
}


9、splitChunks 分割代码

splitChunks插件用于将代码库拆分成更小的块,
以便更好地利用浏览器的缓存机制,
从而提高页面加载速度和性能
cacheGroups是一些缓存组的配置项,

  1. chunks选项指定代码块的类型,all表示打包所有类型的代码块。
  2. priority用于指定缓存组的优先级,
  3. enforce用于强制将模块打包到指定的代码块中,
  4. reuseExistingChunk用于控制是否重用已经存在的代码块
  5. minChunks: 用于指定在多少个模块中出现的模块才能被打包到代码块中。
    默认值为1。例如,如果设置为2,则表示只有在两个或两个以上的模块中出现的模块才会被打包到代码块中
  6. maxAsyncRequests: 用于指定按需加载的代码块最多可以并行加载的次数。默认值为Infinity。
  7. maxInitialRequests: 用于指定初始页面加载时,最多可以并行加载的代码块数量。默认值为3。
  8. automaticNameDelimiter: 用于指定自动生成的代码块名称中的分隔符。默认值为~。
  9. automaticNameMaxLength: 用于指定自动生成的代码块名称的最大长度。默认值为64。
  10. test: 可以使用正则表达式、字符串或函数来匹配模块名称,只有匹配到的模块才会被打包到对应的代码块中。
    optimization.splitChunks

使用 Webpack 拆分块的 100% 正确方法
https://david-gilbertson.medium.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758

10、DLL动态链接库

11、terser-webpack-plugin

多线程压缩JS
可以通过删除无用代码、混淆代码和压缩代码等方式来减小JavaScript文件的大小


const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  //...
  optimization: {
    minimize: process.env.NODE_ENV === 'production',
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true,
          },
          output: {
            comments: false,
          },
        },
      }),
    ],
  },
};
compress选项用于删除console语句,output选项用于移除注释
minimize选项需要设置为true,以启用代码压缩。
terser-webpack-plugin会消耗一定的计算资源,
因此在开发环境中,可以暂时关闭代码压缩功能,以提高构建速度
minimize: process.env.NODE_ENV === 'production',

12、降低图片资源体积

webp

https://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/

图片压缩和svg压缩
imagemin-webpack-plugin插件等。

13、不同的环境不同的配置

五个关键字eval,source-map,cheap,module,inline的任意组合

eval: 使用eval包裹模块代码

source-map: 产生.map文件

cheap: 不包含列信息(关于列信息的解释下面会有详细介绍)也不包含loader的sourcemap

module: 包含loader的sourcemap(比如jsx to js ,babel的sourcemap)

inline: 将.map作为DataURI嵌入,不单独生成.map文件(这个配置项比较少见)

在开发环境中我们使用:cheap-module-eval-source-map

在生产环境中我们使用:cheap-module-source-map。

eval-source-map组合使用是指将.map以DataURL的形式引入到打包好的模块中,

 //1)源码映射 会单独生成一个sourcemap文件 出错了会标识当前的列和行 大和全
	devtool:"source-map", //增加映射文件 可以帮我们调试源代码
// 2)不会产生单独的文件 但是可以显示行和列
	devtool:'eval-source-map',
//3) 不会产生列 但是是一个单独的映射文件
	devtool:'cheap-module-source-map', //产生后你可以保留起来
//4)不会产生文件 集成在打包后的文件中 不会产生列
	devtool:"cheap-module-eval-source-map",
//map文件,文件映射,方便浏览器控制台调式
productionSourceMap:process.env.NODE_ENV==='production'?false:true

14、webpack-bundle-analyzer

webpack-bundle-analyzer分析打包后的资源包

查看vuecli的配置文件

#根据mode,分别生成开发环境、生产环境的配置
vue inspect --mode production > output.js
#输入命令后,在根目录会生产一个output.js文件

项目上线

第一种

npm i serve -g
服务器容器
serve dist

第二种

node创建web服务,vue打包生成的dist文件夹
托管为静态文件

pm2托管

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值