webpack指南(优化篇)——webpack项目优化

news2025/7/9 17:27:10

系列文章目录

webpack指南(基础篇)——手把手教你配置webpack


文章目录

  • 系列文章目录
  • 前言
  • 一、概述
  • 二、传输性能优化
    • 1.代码压缩
      • 1.1 css压缩
      • 1.2 js压缩
      • 1.3 进一步压缩js
      • 1.4 压缩html
      • 1.5图片压缩
    • 2.摇树优化(Tree Shaking)
    • 3.作用域提升
    • 4.抽取公共模块(splitChunks)
    • 5.按需加载
    • 6.优化按需加载
    • 7.利用浏览器缓存
    • 8.切换为cdn资源
      • 1.打包分析
      • 2.切换为cdn
    • 三、构建过程优化
      • 1.忽略对第三方包的解析
      • 2.忽略第三方包的指定目录
      • 3.并行打包


前言

面试的时候总是会问用webpack对项目做过哪些优化,今天我们就来详细列举一下常用的优化手段;
前面我们利用webpack构建了一个项目,今天我们在原项目基础上进行优化,还没有观看的小伙伴可以移步看一下。

一、概述

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


二、传输性能优化

1.代码压缩

进行代码压缩,减少资源包体积

1.1 css压缩

CssMinimizerWebpackPlugin这个插件使用 cssnano 优化和压缩 CSS

安装

 yarn add css-minimizer-webpack-plugin -D

使用

// 引入
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
// 配置
  //  webpack内置的优化配置项
  optimization: {
    // 为true时 告知webpack 使用配置的插件压缩 bundle。生产环境默认开启
    minimize: true,
    // 配置优化插件
    minimizer: [
         new CssMinimizerPlugin(),
    ],
  },

效果
配置前:
配置前打包后的css

配置后:配置后

1.2 js压缩

webpack自带的配置默认开启js压缩,我们保留原来配置即可

    minimizer: [
      // 使用 `...` 语法来扩展现有的 minimizer,保留原webpack的优化措施
      //   `...`,
      new CssMinimizerPlugin(),
    ],

开启前:
在这里插入图片描述
开启后:
开启后

1.3 进一步压缩js

有时候默认的配置无法满足我们的需求,我们需要自定义一些压缩规则,这时候就需要使用terser-webpack-plugin自己配置了;

安装

yarn add terser-webpack-plugin -D

使用

const TerserPlugin = require('terser-webpack-plugin');
devtool: 'source-map',
  //  webpack内置的优化配置项
  optimization: {
    // 为true时 告知webpack 使用配置的插件压缩 bundle。生产环境默认开启
    minimize: true,
    // 配置优化插件
    minimizer: [
      // 使用 `...` 语法来扩展现有的 minimizer,保留原webpack的优化措施
      //   `...`,
      new CssMinimizerPlugin(),
      new TerserPlugin({
        // 匹配要压缩的文件
        test: /\.js(\?.*)?$/i,
        // 配置参数
        terserOptions: {
          format: {
            // 删除注释
            comments: false,
          },
          compress: {
            // 移除所有console相关代码;
            drop_console: true,
            // 移除自动断点功能;
            drop_debugger: true,
            // 配置移除指定的指令,如console.log,alert
            pure_funcs: ['console.log', 'console.error'],
          },
        },
        // 是否抽离注释
        extractComments: false,
      }),
    ],
  },

压缩后
在这里插入图片描述

值得注意的是,开启TerserPlugin 优化必须配置devtool为terse-webpack-plugin支持的选项:source-map,inline-source-map!!否则不生效这个配置项的作用我们随后再介绍;

1.4 压缩html

我们通过修改html-webpack-plugin的配置来实现压缩

    new HtmlWebpackPlugin({
      template: './index.html',
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true,
      },
    }),

压缩前:
在这里插入图片描述
压缩后:
在这里插入图片描述

1.5图片压缩

image-webpack-loader基于webpack的图片压缩工具,压缩方案采用 imagemin ,代码实现比较全面,支持 Minify PNG, JPEG, GIF, SVG and WEBP images 等,支持各个版本 webpack,github start 1625

安装

cnpm install --save-dev image-webpack-loader file-loader

使用

      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        // type: 'asset',
        use: [
          'file-loader',
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
              },
              optipng: {
                enabled: false,
              },
              pngquant: {
                quality: [0.5, 0.65],
                speed: 4,
              },
              gifsicle: {
                interlaced: false,
              },
              // the webp option will enable WEBP
              webp: {
                quality: 75,
              },
            },
          },
        ],
      },

效果:5kb压缩至2kb
在这里插入图片描述
在这里插入图片描述
踩坑:
enn…一言难尽
1.安装loader必须用cnpm,别不信邪…
2.不是所有的图片都能压缩成功,目前没有找出规律,所以谨慎使用吧。

ok,关于代码压缩就先介绍到这里;更多参数配置都可以移步npm查看;

2.摇树优化(Tree Shaking)

简单来说就像摇晃一颗树一样,把没有根的叶子晃下来;在代码里就是移除没有被引用的代码;

tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块语法的 静态结构 特性,例如 import 和 export

演示
我们新建个模块文件module.js,导出module1和module2代码如下:

export function module1() {
  console.log('module1');
}
export function module2() {
  console.log('module2');
}

在index.js中只引入module1

import { module1 } from './utils/module';
module1();

打包后可以看到,module2函数也被打包在内
在这里插入图片描述
解决
在optimization中配置usedExports: true;

 // 检查代码是否使用
 usedExports: true,

打包后module2被排除
在这里插入图片描述
但是这样也是有问题的,因为usedExports 依赖于 terser 去自动检测语句中的副作用,他的策略比较保守,有时候我们需要告诉插件我们的这个代码没有副作用,可以全部优化,这个时候我们需要对代码进行标记,让terser 强制优化;

使用sideEffects标记代码
可以通过 package.json 的 sideEffects声明哪些文件可以被优化;fasle表示无副作用,可以优化,true表示谨慎对待,也可以提供一个数组;

演示
在全局对象上挂一个方法,terser 不会优化此方法

window.onload = function () {
  console.log(123);
};

在这里插入图片描述
现在我们声明我们的代码没有副作用,可以优化;

// 所有代码都可以优化
"sideEffects": false

可以看到,确实没有了onload,但是同时也发现项目中的css和静态资源也没有了
在这里插入图片描述
在这里插入图片描述
sideEffects使用数组,告诉插件数组内的是有副作用的,不能优化,其他的无副作用,可以优化;

  "sideEffects": [
    "*.css",
    "*.jpg"
  ]

在这里插入图片描述
sideEffects原理
webpack 能将标记为 side-effects-free 的包由 import {a} from xx 转换为 import {a} from ‘xx/a’,是根据你的引入关系进行判断的,从而自动修剪掉没必要要的 import,如果写一个方法没有被导出的话,是无法被优化的;
如下图,onscroll打包有依旧存在
在这里插入图片描述
在这里插入图片描述

3.作用域提升

将具有引用关系的代码尽可能的合并,减少代码量;

// optimization中插入如下
concatenateModules: true,

4.抽取公共模块(splitChunks)

SplitChunks插件是webpack中用来提取或分离代码的插件,主要作用是提取公共代码,减少代码被重复打包,拆分过大的js文件,合并零散的js文件

webpack 将根据以下条件自动拆分 chunks:

  • 新的 chunk 可以被共享,或者模块来自于 node_modules 文件夹
  • 新的 chunk 体积大于 20kb(在进行 min+gz 之前的体积)
  • 当按需加载 chunks 时,并行请求的最大数量小于或等于 30
  • 当加载初始化页面时,并发请求的最大数量小于或等于 30
    我们可以自己去修改一些配置项,常用配置如下:
    //   分包
    splitChunks: {
      // 选取使用哪些chunks进行优化
      chunks: 'all',
      //   被引用次数超过该阈值的模块才会被拆包处理
      minChunks: 2,
      //   打包后的分包数量
      maxInitialRequests: 10,
      maxAsyncRequests: 10,
      //   生成 chunk 的最小/大体积(kb)
      minSize: 2000,
      maxSize: 200000,
      // 为不同的包配置不同的策略,缓存组可以继承和/或覆盖来自 splitChunks.* 的任何选项
      // 当不配置cacheGroups时,内部会存在vendors和default默认配置,我们也可以通过手动更改默认值。
      cacheGroups: {
        // 自定义的缓存组名称
        common: {
          name: 'common',
          //   始终为此缓存组创建分包
          enforce: true,
        },
      },
    },

5.按需加载

对于一些不需要一打开页面就展示的资源,我们可以使用按需加载的方式,减少起始页面压力;

标准用法的 import 导入的模块是静态的,会使所有被导入的模块,在加载时就被编译(无法做到按需编译,降低首页加载速度)。有些场景中,你可能希望根据条件导入模块或者按需导入模块,这时你可以使用动态导入代替静态导入
import()返回一个promise对象;

import('/modules/my-module.js')
  .then((module) => {
    // Do something with the module.
  });

6.优化按需加载

有时候模块包比较大,用户操作后再进行加载会有一定的延时,影响用户体验,我们可以配合webpack的魔法注释,使用预加载或预拉取进行优化;

使用prefetch或preload标签预加载模块;prefetch标签可以告诉浏览器在后台加载指定的资源,以便在未来某个时刻使用。preload标签则可以告诉浏览器在当前页面加载时立即加载指定的资源。通过使用这两种标签,可以在浏览器闲置时提前加载一些模块,从而提高程序响应速度。

// 预加载
import(/*webpackPrefetch:true*/ '@/assets/01.png');
// 预拉取
import(/*webpackPreload:true*/ '@/assets/01.png');

7.利用浏览器缓存

浏览器回对加载资源默认进行缓存,当加载资源名称没有改变时,会从缓存数据库中读取;我们可以配置打包后没有修改的文件hash值不变,使浏览器从缓存中读取文件;

// 修改output中filename属性,contenthash代表文件内容改变时更新hash
filename: '[name].[contenthash].js',

8.切换为cdn资源

1.打包分析

// 安装webpack-bundle-analyzer
yarn add -D webpack-bundle-analyzer
// 引入
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
// 使用
new BundleAnalyzerPlugin(),

执行命令后发现:jquery占了很大体积,我们尝试把它切换为cdn资源
在这里插入图片描述

2.切换为cdn

// 配置排除打包
  externals: {
    // 排除打包 npm包名:window.对象名
    jquery: 'jQuery',
  },

效果:jquery确实没有了,包小了很多,但同时,用到jquery的功能也失效了,我们需要在页面中将jquery的引入换为cdn
在这里插入图片描述

// index.html中引入
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>

三、构建过程优化

随着项目体积越来越大,打包时耗费时间也越来越多,我们可以通过一些配置去优化这个过程;

1.忽略对第三方包的解析

webpack打包过程会先解析再打包,对于比较成熟的第三方包我们可以忽略解析这个过程l;

// module中配置noParse
 noParse: /jquery/,

2.忽略第三方包的指定目录

对于多语言组件库如moment,我们用不到的语言包就可以排除;使用方法如下:

let Webpack = require('webpack');
plugins:[
	new Webpack.IgnorePlugin(/\.\/locale/,/moment/),//moment这个库中,如果引用了./locale/目录的内容,就忽略掉,不会打包进去
]

这时候locale目录都会被忽略,我们需要手动引入下中文包:

import 'moment/locale/zh-cn';
moment.locale('zh-cn');

3.并行打包

顾名思义,开启多线程打包,使用happypack

// 下载
yarn add happypack -D
// 使用
// 多线程打包
const happypack = require('happypack');
const os = require('os');
// 创建进程池
const happyThreadPool = happypack.ThreadPool({
  // 获取电脑cpu数,作为线程数
  size: os.cpus().length,
});

// 配置plugin,以babel-loader为例
    new HappyPack({
      // 进程名称,每个线程独一无二
      id: 'happypack1',
      //   当前线程要使用的loader
      loaders: [
        {
          loader: 'babel-loader',
          options: {
            // 降级es6
            presets: ['@babel/preset-env'],
            //   修改辅助代码引入
            plugins: ['@babel/plugin-transform-runtime'],
          },
        },
      ],
      threadPool: happyThreadPool,
    }),
 // 改写js babel-loader关联到进程
   {
        test: /\.js$/i,
        // 排除node_modules下的文件
        exclude: /node_modules/,
        // 用url的形式把规则和线程关联起来
        use: 'happypack/loader?id=happypack1',
        // use: {
        //   loader: 'babel-loader',
        //   options: {
        //     // 降级es6
        //     presets: ['@babel/preset-env'],
        //     //   修改辅助代码引入
        //     plugins: ['@babel/plugin-transform-runtime'],
        //   },
        // },
      },
 

happypack目前并不支持所有的loader,有一些兼容性问题,使用需注意

ok,关于webpack打包优化就介绍到这里,码字不易,欢迎三连;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/396342.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python+selenium自动化测试解决不了的alert问题,使用PyKeyboard解决方法

在python自动化测试中&#xff0c;面对浏览器弹出的对话框&#xff0c;python自带的alert可能解决不了关闭弹框&#xff0c;这时候可以引入PyKeyboard来解决下载并安装pyHook-1.5.1-cp36-cp36m-win_amd64.whl&#xff0c;下载地址https://www.lfd.uci.edu/~gohlke/pythonlibs/&…

你需要知道的云计算常识

云计算常识_基础阶段云计算服务器架构的演进云计算能够提供什么价值&#xff1f;谁为云计算提供服务&#xff1f;计算机的组成部分进制转换云计算 服务器架构的演进 Mon 06Mon 13Mon 20裸金属 虚拟机 云主机(云平台) 容器&#xff08;云原生&#xff09; serviceless(无服务) …

基于VC+MSSQL开发的医院PACS系统全套源代码 强大的三维重建功能

医院PACS系统源码 PACS源码 一套医学影像存储与传输系统&#xff0c;PACS部分主要提供医学影像获取、影像信息网络传递、大容量数据存储、影像显示和处理、影像打印等功能。RIS主要提供分诊登记、叫号、检查报告生成和打印等功能。本套影像存储与传输系统将二者进行无缝对接&a…

CHAPTER 4 文件共享 - Samba

文件共享 - Samba1 Samba1.1 Samba的软件架构1.2 搭建Samba服务器1.3 samba用户管理1. 添加用户2. 修改用户密码3. 删除用户和密码4. 查看samba用户列表5. 查看samba服务器状态1.4 samba共享设置&#xff08;配置文件详解&#xff09;1.5 访问共享目录1. windows访问2. linux客…

机智云目前我用过最便捷的物联网快速开发方案

GE211 MINI DTU上手来看&#xff0c;是一款尺寸比较小巧的模块&#xff0c;适合放置在几乎所有白色家电中&#xff0c;通过ph2.0端子&#xff08;注意不要买错&#xff09;引出了5v、gnd、tx、rx。可以说是非常方便了。下面正式开始我们的接入流程&#xff1a;首先注册一个机智…

PPC902AE101 3BHE010751R0101

PPC902AE101 3BHE010751R0101PPC902AE101 3BHE010751R0101PLC脉冲量的控制目的主要是位置控制、运动控制、轨迹控制等。例如&#xff1a;脉冲数在角度控制中的应用。步进电机驱动器的细分是每圈10000&#xff0c;要求步进电机旋转90度。 那么所要动作的脉冲数值10000/(360/90)2…

如果读了我2011年求职前端开发的酸爽经历,希望你可以鼓起勇气继续向前

今年是2023年&#xff0c;如果你觉得今年找工作很难&#xff0c;狗哥回忆了一下2011年求职前端开发工作的酸爽经历&#xff0c;希望你读了以后可以鼓起勇气&#xff0c;不要迷茫&#xff0c;简历投出去石沉大海的&#xff0c;需要改简历的就赶紧改&#xff0c;刷题不到位的就赶…

美国主机的CMS兼容性:如何选择适合您的CMS?

在如今的数字时代&#xff0c;网站是企业宣传和业务发展的重要方式&#xff0c;而一个好的主机对于网站的性能和稳定性至关重要。如果您正在寻找一个适合您的CMS(内容管理系统)的美国主机&#xff0c;您需要考虑一些关键因素&#xff0c;以确保您选择的主机能够满足您的需求。以…

接上篇《旋转矩阵的作用:世界坐标变换;求解局部坐标系下的局部坐标》,理解欧拉角:内旋;外旋;万向节死锁

目录1、什么是欧拉角、静态欧拉角、动态欧拉角2、内旋、外旋及计算方式3、万向节死锁接上篇《旋转矩阵的作用&#xff1a;世界坐标变换&#xff1b;求解局部坐标系下的局部坐标》&#xff0c;理解欧拉角&#xff1a;内旋&#xff1b;外旋&#xff1b;万向节死锁1、什么是欧拉角…

抢跑数字中国建设,青岛市统计系统考察团赴实在智能调研统计数字员工

当前&#xff0c;数据要素价值不断显现&#xff0c;数字经济正引领着政企业加快数字技术的应用&#xff0c;融通创新工作机制&#xff0c;推进高质量转型。近日&#xff0c;中共中央、国务院印发了《数字中国建设整体布局规划》。《规划》指出&#xff0c;到2025年&#xff0c;…

Rust 开发系列PyO3:Rust与Python的联动编程(上)

前言 Rust语言经常被人误认为是R语言&#xff0c;或者Ruby语言……但是做为近十年来tiobe最出人意料的编程语言&#xff0c;从冷门逐渐变成了明星&#xff0c;不过这次我们不讲Rust入门的内容&#xff0c;我们先来看看它一个很实用的功能——与Python的联动编程。 在正式开始之…

易优cms searchform 搜索标签使用方法

searchform 搜索标签 【基础用法】 标签&#xff1a;searchform 描述&#xff1a;文档标题搜索&#xff0c;默认搜索整站 用法&#xff1a; {eyou:searchform typesonself} <form method"get" action"{$field.action}"> <input …

僵尸(Zombie)进程

文章目录1.僵尸进程2.产生僵尸进程的原因3.利用 wait 函数销毁僵尸进程4.使用 waitpid 函数销毁僵尸进程1.僵尸进程 进程完成工作后&#xff08;执行完 main 函数中的程序后&#xff09;应被销毁&#xff0c;但有时这些进程将变成僵尸进程&#xff0c;占用系统中的重要资源。这…

vue 监测数据改变的原理,添加属性

vue 监测数据改变的原理&#xff0c;添加属性 概况就是vue帮我们处理了&#xff0c;data的数据&#xff0c;加了get和set在生成虚拟dom模板之前&#xff0c; 开始做data数据的生成&#xff0c;get&#xff0c;set vue 提供的api : Vue.set(vm._data.student,‘key’,‘val’)…

C++复习笔记16

非类型的模板参数 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之后的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可将该参数当成常量来使用。 注意&#xff1a; 1. 浮点数…

分享一个可以早点下班的开发小技巧

这次来跟大家分享一下让大家早下班的工具。首先要声明一下&#xff0c;分享的工作&#xff0c;是为了大部分人&#xff0c;而不是“某一个人”&#xff0c;不喜勿喷哈&#xff01; 介绍的就是这两年很火的低代码平台&#xff0c;网上两种观点&#xff1a; 第一种人是很不屑&am…

等保2.0与1.0 测评要求的变化

No.1标准内容增加了 标准内容上最大的变化就是将安全要求分为了安全通用要求和扩展要求。首先&#xff0c;安全通用要求部分已对1.0标准的内容进行了优化&#xff0c;删除或修订了过时的要求项&#xff0c;新增了对新型网络攻击行为防护和个人信息保护等方面的新要求。其次&am…

SAP 更改物料基本计量单位

前言部分 在SAP中物料创建后&#xff0c;一旦发生业务&#xff0c;其基本计量单位便很难修改。由于单位无法满足业务要求&#xff0c;往往会要求新建一个物料替代旧物料。这时候除了要将旧物料上所有的未清业务删除外&#xff0c;还需要替换工艺与BOM中的旧物料。特别是当出现旧…

一文带你看懂:亿级大表垂直拆分的工程实践

伴随着不断扩张的业务量&#xff0c;在数据库层面一般会经历数据拆分。解决问题的第一步&#xff0c;就是重新评估DB表结构设计的合理性。我们开发者会对表结构和业务代码进行重构&#xff0c;在之前的文章《业务系统重构》我有提到过。大表问题我实际遇到的是怎么样的情况呢&a…

CAD指令框找不到了怎么调出来?CAD指令框调出方法

CAD制图过程中&#xff0c;为了提高设计师的绘图效率&#xff0c;经常会用到各种CAD命令快捷键&#xff0c;可是CAD指令框突然不见了&#xff0c;这就让人很头疼了。CAD指令框找不到了怎么调出来呢&#xff1f;本节内容小编以浩辰CAD软件为例来给大家分享一下CAD指令框调出方法…