【包真】我的第一次webpack优化,首屏渲染从9s到1s

news2024/11/19 2:34:32

目录

前言        

1.生产环境关闭productionSourceMap、css sourceMap

2.分析大文件,找出内鬼

3. 逐个包优化

TreeShaking

使用cdn加载第三方js

懒加载有间接依赖的包

moment.js的优化

还有进步空间?

最后


 

前言        

        本文基于vue2(虽然vue3已出,但是本文也很实用)

        谈到webpack优化大部分人可能都看腻了,无非就那几招嘛,我之前也是看过许多类似的文章,但都没有自己真正上手过,下面是我用公司的项目真实操练下来的,首屏加载速度提升很大(刷刷的),希望能帮到你。

        废话不多说,先看看对比成果!

类型优化前优化后
js文件大小24MB3MB
主页首屏显示9s1s

        这简直太夸张了,提升了8倍?可以想象以前是多慢,要等半天啊。蛮王这个真男人都开大2次了~

        可以看到,优化前后首屏加载速度有质的提升,之前一直想优化我们项目的首屏加载时间,有缓存还好,没有缓存屏幕白屏都要等待7、8s。特别是有的客户第一次打开这个系统,那7、8秒犹如过了一个世纪,非常尴尬。那么我做了哪些常规操作呢?

1.生产环境关闭productionSourceMapcss sourceMap

        众所周知,SourceMap就是当页面出现某些错误,能够定位到具体的某一行代码,SourceMap就是帮你建立这个映射关系的,方便代码调试。在生产环境中我们完全没必要开启这个功能(谁在生产环境调试代码?不会是你吧
  如下配置:

const isProduction = process.env.NODE_ENV === 'production' 
// 判断是否是生产环境 
module.exports = {     
  productionSourceMap: !isProduction, //关闭生产环境下的SourceMap映射文件 
  css: {         
    sourceMap: !isProduction, // css sourceMap 配置 
    loaderOptions: {             
    ...其它代码         
   }     
  },     
  ...其它代码 
}

        此时再npm run build 打包,就会发现速度快了很多,体积瞬间只有几兆了!

2.分析大文件,找出内鬼

        安装 npm install webpack-bundle-analyzer -D 插件,打包后会生产一个本地服务,清楚的展示打包文件的包含关系和大小。

  vue.config.js 配置:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin  
module.exports = {     
   ...其它     
   configureWebpack: [         
   plugins: [             
      new BundleAnalyzerPlugin() // 分析打包大小使用默认配置         
   ]    
  },  
 ...其它 
}

  自动弹出一个服务,清晰的展示打包后js的文件大小:

  通过图中可以发现:

  1. element-ui和ant-design占了近1/4的大小:1.53MB

  2. exceljs也是个大东西有:1.3MB

  3. echarts.js文件也接近1MB

  4. moment.js也有700KB

        打包后js文件一共就5MB,这五个哥们就占了4M左右。不分析好还,一分析吓得够呛~
不要虚!找到刺了,一个一个来拔掉就好了。相信我拔掉的过程是很爽的。

3. 逐个包优化


        分析发现,elementui、echarts是必须使用的,打包又耗时且页面加载也较慢得很。可以通过cdn直接引入,方便且速度快。
    element-ui是我们项目用的主要框架,所以这个肯定是少不了,但是项目里面ant-design为什么会存在呢,原来是发现有个页面使用了antd的进度条组件,因为elementui的进度条不太好看。但是没想到这样把整个antd都导进来了。


TreeShaking

        舍弃antd组件,自己去找一个类似的vue插件或者干脆自己实现一个。(这个方法短时间无法完成,且不想去动以前代码,暂不考虑)

        使用antd部分加载。只加载想要的进度条组件,可以减少文件体积(这个方法简单粗暴,就是牺牲一些文件大小)。

        我们使用方案2,根据antd官方的文档配置部分组件的引入。

安装 npm install babel-plugin-import -D

1. main.js导入需要的组件 Step

import { Steps } from 'ant-design-vue'; 
Vue.component(Steps.name, Steps); 
Vue.component(Steps.Step.name, Steps.Step);

2. babel.config.js 加上配置:

module.exports = {  
    presets: [  '@vue/cli-plugin-babel/preset'   ],   
    //以下是按需加载的配置++++ 
    plugins: [     
     [       
      "import",       
      {         
          libraryName: "ant-design-vue",        
          libraryDirectory: "es",         
          style: true       
      }     
     ]   
    ] 
}

        此时再分析,antd已经小了很多。

使用cdn加载第三方js

        我们项目里面第三方js很多,有些打包下来会很大,而且加载速度较慢。我们把这些js分离出来,通过cdn的方式在html中的script标签中直接使用,一方面减少打包体积,一方面提高了加载速度。

        这里推荐一个免费的cdnBootCDN。也可以使用自己购买的付费cdn服务,我们到网站搜索自己项目需要的js。例如:vue

        注意,一定要选择自己项目对应的版本,否则会出现各种奇怪的问题

        我的项目使用的是 "vue": "^2.6.12", (package.json)

第一步:配置vue.config.js,让webpack不打包这些js,而是通过script标签加入。

 const isProduction = process.env.NODE_ENV === 'production' // 判断是否是生产环境
//正式环境不打包公共js
let externals = {}
//储存cdn的文件
let cdn = {
    css: [
        'https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.0/theme-chalk/index.min.css' // element-ui css 样式表
    ],
    js: []
}
//正式环境才需要
if (isProduction) {
    externals = { //排除打包的js
        vue: 'Vue',
        'element-ui': 'ELEMENT',
        echarts: 'echarts',
    }
    cdn.js = [
        'https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js', // vuejs
        'https://cdn.bootcdn.net/ajax/libs/element-ui/2.6.0/index.js', // element-ui js
        'https://cdn.bootcdn.net/ajax/libs/element-ui/2.6.0/locale/zh-CN.min.js',
        'https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.min.js',
    ]
}
module.exports = {
//...其它配置
configureWebpack: {
        //常用的公共js 排除掉,不打包 而是在index添加cdn,
        externals, 
        //...其它配置
    },
chainWebpack: config => {
        //...其它配置  
        // 注入cdn变量 (打包时会执行)
        config.plugin('html').tap(args => {
            args[0].cdn = cdn // 配置cdn给插件
            return args
        })
    }
//...其它配置     
}

第二步:html模板中加入定义好的cdn变量使用的代码

<!DOCTYPE html>
<html lang="">

<head>
<meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>web</title>
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <!-- 引入样式 -->
    <% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
       <link rel="stylesheet" href="<%=css%>" >
    <% } %>

    <!-- 引入JS -->
    <% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
       <script src="<%=js%>"></script>
    <% } %>
</head>
<body style="font-size:14px">
    <section id="app"></section>
</body>
</html>

        可以发现cdn.js中,我把vue、echarts、element-ui这三个大头加入了。在externals对象中左侧是npm包的名称,右侧是在代码中暴露的全局变量。注意element-ui对应的是 ELEMENT

        没有ant-design-vue是因为我们上面使用了部分加载的方式,如果使用cdn这种方式是加载全部的代码,有点浪费。

        没有使用exclejs,是因为exceljs在我的业务代码中不是直接引用的,而是一个叫table2excel间接依赖的。所以就算我通过上面的方法排除掉它,在打包的时候还是会通过table2excel的依赖找到它并打包。

懒加载有间接依赖的包


    那这种不可避免的情况,该如何优化,让加载速度不受影响呢?答案是通过懒加载的方式:

  • 1.script标签中注释掉 import Table2Excel from "table2excel.js";

  • 2.下载的方法中:download(){}

1.script标签中注释掉 import Table2Excel from "table2excel.js";

2.下载的方法中:
download(){
    //使用import().then()方式
    import("table2excel.js").then((Table2Excel) => {
        new Table2Excel.default("#table").export('filename') //多了一层default 
    })
}

        这样在进入系统时,不会加载Table2Excel 和exceljs,当需要时才会去加载,第一次会慢一点,后面就不需要加载了,会变快。

moment.js的优化

        我们发现monentjs在项目中有使用来对时间格式化,但是使用频率并不高,完全可以自己实现一个format方法,或者使用只有6kbday.js.

        但这里我们暂不替换,把moment变得瘦小一些即可,删除掉除中文以外的语言包
第一步:**vue.config.js**

...其它配置
 chainWebpack: config => {
     config.plugin('ignore')
        //忽略/moment/locale下的所有文件
     .use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/))
 }
...其它配置
 

第二步:main.js

import moment from 'moment' //手动引入所需要的语言包 
import 'moment/locale/zh-cn'; // 指定使用的语言 
moment.locale('zh-cn');

这次我们看看moment打包后多大:

        只有174kb了。不过,有一说一还是day.js香~。做完上面这些动作我们的js文件总大小:3.04MB ,其中包含 1.3MB的懒加载js,剩下的1.7MB左右的js基本上不会对页面造成很大的卡顿。

还有进步空间?


        1. 通过 compression-webpack-plugin 插件把代码压缩为gzip。但是!需要服务器支持
webpack端 vue.config.js配置如下:

//打包压缩静态文件插件
const CompressionPlugin = require("compression-webpack-plugin")

//...其它配置
module.exports = {
    //...其它配置
    chainWebpack: config => {
        //生产环境开启js\css压缩
        if (isProduction) {
            config.plugin('compressionPlugin').use(new CompressionPlugin({
                test: /\.(js)$/, // 匹配文件名
                threshold: 10240, // 对超过10k的数据压缩
                minRatio: 0.8,
                deleteOriginalAssets: true // 删除源文件
            }))
        }
    }
    //...其它配置
}

        打包大小由3MB860KB,感觉起飞了~

        2. 服务器端配置这里就不详细说明了可以谷百:nginx开启静态压缩 找到答案。


最后

贴上优化前后的无缓存下的首屏加载时间对比(chrome浏览器),绝对包真:
优化前项目网站首屏加载数据:9.17s

优化后项目网站首屏加载数据:1.24s

        这些都是在工作之余,自己抽时间去查阅各位大佬的帖子,虽然都是些耍烂了的技术,但是真的要在自己项目中实施还是需要一些时间和精力,大多数都是为了完成功能快速迭代而忽略掉了做程序原本的目的,就是要让用户有一个良好的使用体验。

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

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

相关文章

我的小实验项目:实现人体红外采集控制LED灯亮灭

从传感器电路图中找到红外感应&#xff0c;找到接口D2&#xff0c;可以看出&#xff0c;采集的信息从D2进入 从核心板电路图找到D2接口&#xff0c;发现引脚为PB8 并用相似的方法&#xff0c;找到用于代表有人无人的LED灯 在STM32CubeMx里设置 在Keil里设置代码 main.c&#x…

智慧物业如何整合生态资源,小程序技术或成为突破口

数字物业和智慧社区成为了当前数字化转型的热点领域。这些新兴技术的应用&#xff0c;不仅为业主提供了更加便捷、高效的服务&#xff0c;也为物业公司和城市管理带来了全新的运营模式和管理方式。 根据数据显示&#xff0c;截至2021年底&#xff0c;中国物业服务企业智慧化改造…

基于Java+SpringBoot+Vue前后端分离网上银行系统设计与实现(视频讲解)

博主介绍&#xff1a;✌全网粉丝3W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

Element-ui中el-table展开行

类似这样的需求还记录不记录呢&#xff0c;其实我觉得是没必要的&#xff0c;但是想来还是记录一下吧&#xff0c;因为element-ui里面组件本身也很多&#xff0c;其中el-table的配置样式需求更是很多很多&#xff0c;所以这还是决定来记录一下&#xff0c;以后再有类似的需求也…

linux内核篇-输入输出系统(块设备,字符设备)

计算机系统的输入和输出系统都有哪些呢&#xff1f;有键盘、鼠标、显示器、网卡、硬盘、打印机、CD/DVD 等等&#xff0c;多种多样。但是对于操作系统来讲&#xff0c;却是一件复杂的事情&#xff0c;因为这么多设备&#xff0c;形状、用法、功能都不一样&#xff0c;怎么才能统…

SpringBoot中整合Swagger2接口文档

目录 1、maven依赖 2、swagger2 注解整体说明 2.1、请求类的描述 2.2、方法和方法参数的描述 2.3、方法的响应状态的描述 2.4、对象的描述 3、请求类的描述 3.1、Api&#xff1a;请求类的说明 3.2、示例&#xff1a; 4、方法和方法参数的描述 4.1、ApiOperation&#xff1a…

Linux 中的文件类型

目录 Linux文件类型说明 软链接 软链接特点 软链接工作过程 正常原文件a工作流程 文件a的软链接工作流程 硬链接 硬链接的特点 文件a的硬链接工作流程 软链接与硬链接的比较 测试软链接以及硬链接 1.进入根目录 2.创建test目录 3.进入test目录中&#xff0c;并创建a…

基于Redis的分布式锁,Redisson的简单使用和常用配置

介绍 Redisson是一个在Redis基础上实现的Java驻内存数据网格。Redisson提供了使用Redis的最简单最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离&#xff0c;从而让使用者能够将精力更集中的放在处理业务逻辑上。 Redisson官方文档地址&#xff1a;https://githu…

蛋糕烘焙店小程序开发 让生活多点甜

蛋糕甜品因为较高的颜值、香甜的口感深受大众喜欢&#xff0c;当我们路过一家蛋糕烘焙店的时候&#xff0c;飘香的味道让我们流连忘返。但是互联网时代&#xff0c;各个行业都在转型&#xff0c;蛋糕烘焙店也需要由传统线下店面向线上线下结合的方式转变&#xff0c;以求摆脱区…

数据对象属性分类

数据集由数据对象组成&#xff0c;一个数据对象代表一个实体。数据对象又称样本、实例、数据点或对象。属性&#xff08;attribute&#xff09;是一个数据字段&#xff0c;表示数据对象的一个特征。属性向量&#xff08;或特征向量&#xff09;是用来描述一个给定对象的一组属性…

MySQL之单表访问方法

前言 本文章收录在MySQL性能优化原理实战专栏&#xff0c;点击此处查看更多优质内容。 本文摘录自 ▪ 小孩子4919《MySQL是怎样运行的&#xff1a;从根儿上理解MySQL》 对于我们这些MySQL的使用者来说&#xff0c;MySQL其实就是一个软件&#xff0c;平时用的最多的就是查询功…

快码住!!! 二叉树概念、重要性质、存储结构 技巧大总结!

文章目录 树树的概念树的表示树在实际中的应用 二叉树二叉树的概念特殊的二叉树 二叉树的性质二叉树性质应用的练习题 二叉树的存储结构顺序结构链式结构 树 树的概念 树是一种非线性的数据结构&#xff0c;它是由n(n>0)个有限结点组成的一个具有层次关系的集合。把它叫做…

语言模型及Word2vec与Bert简析

语言模型可以对一段文本的合理性概率进行估计&#xff0c;对信息检索&#xff0c;机器翻译&#xff0c;语音识别等任务有着重要的作用。就以前的学习笔记&#xff0c;本文简单总结了NLP语言模型word2vec和bert分享给大家&#xff0c;疏漏之处&#xff0c;望请指出&#xff0c; …

Go语言的简介和环境搭建

Go语言的简介和环境搭建 带你了解什么是Go语言 如何安装和配置Go的开发环境 静态强类型&#xff0c;编译型语言&#xff01;&#xff01;&#xff01; 1.简介 1.1介绍 Go 也称为 Golang&#xff0c;两个是一个东西。谷歌弄得。创造者都是大佬&#xff0c;所以说这个编程语言很…

PSP - AlphaFold2 Multimer 的 Heteromer (异聚体) MSA 逻辑

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/130733737 同源多聚体 (Homomer) 是由相同的蛋白质亚基组成的,而异源多聚体 (Heteromer) 是由不同的蛋白质亚基组成的。同源多聚体的亚基之间通常有对称的相…

BFT 最前线 | OpenAI开放网络浏览和插件;“360AI商店”上线;Bing市场份额不升反降;亚马逊机器人配送中心投产

原创 | BFT机器人 AI视界 TECHNOLOGY NEWS 01 OpenAI将向所有ChatGPT Plus用户推出网络浏览和插件 OpenAI将向所有ChatGPT Plus用户推出网络浏览和插件近日&#xff0c;OpenAI发文称&#xff0c;将在本周&#xff08;5.15-5.21日&#xff09;内向所有ChatGPT Plus用户推出网络…

【Python scikit-learn】零基础也能轻松掌握的学习路线与参考资料

Python是一种广泛使用的编程语言&#xff0c;随着数据科学领域的不断发展&#xff0c;Python成为了数据科学的主要工具之一。scikit-learn是Python中一款非常流行的机器学习库&#xff0c;它为广大科学家和工程师提供了一种简单而有效的方法来解决机器学习问题。 本文将从以下…

客服软件强攻略——改善客户自助服务

客户自助服务相对容易采用并集成到您现有的客户服务产品中。也就是说&#xff0c;任何自助服务计划都应该经过充分研究&#xff0c;跟踪明确的目标和成功指标&#xff0c;以确保其成功。 有效的自助服务通常可以通过软件工具形成&#xff0c;比如SaleSmartly&#xff08;ss客服…

微服务保护(线程隔离、降级、熔断)

线程隔离 线程隔离有两种方式实现: 线程池隔离信号量隔离 线程池隔离 假设服务A依赖于服务B和服务C&#xff0c;那么服务A就会分别对服务B和服务C创建线程池&#xff0c;当有请求进来时不会使用服务A本身的线程&#xff0c;而是到对应的线程池中取一个线程来调用feign的客户…

ViLT论文精读笔记

ViLT论文精读笔记 0.摘要1.引言2.背景知识&#xff08;小综述&#xff09;2.1对VLP模型分类2.2模态的融合2.3融合前特征的抽取 3.模型方法3.1预训练目标函数&#xff1a;3.1.1 Image Text Matching&#xff1a;3.1.2 Masked Language Modeling3.1.3 Masked Image Modeling 3.2W…