您现在的位置是:首页 >其他 >前端项目性能优化合集网站首页其他
前端项目性能优化合集
本文将从三个角度(页面渲染,打包优化,总体优化)分析前端性能优化的一些方案
页面渲染
1. 减少页面重绘(repaint)和回流(reflow)
减少使用 css 属性简写,如:用border-width, border-style, border-color代替border。因为css简写把所有值初始化为initial,尽量不使用属性简写可以最小化重绘(repaint)和回流(reflow),(实际工作中,由于css简写带来的性能影响微乎其微,再加上css全都展开写还会增加code size,另外css简写还能解决一些样式覆盖的问题)
- 通过修改className批量修改元素样式;
- 复杂的动画元素定位要设置为 fixed 或 absoult,避免引起回流;
- 不使用table布局(table元素一旦触发回流就会导致table里所有的其它元素回流);
- DOM 元素上下移动用用translate替代top修改
- 需要创建多个DOM节点时,使用DocumentFragment一次性创建。
- css3硬件加速(GPU加速),它可以让transform、opacity、filters这些动画不会引起回流重绘。对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能(但是不能滥用,会导致性能问题)。
- 元素适当地定义高度或最小高度,否则元素的动态内容载入时,会出现页面元素的晃动或位置,造成回流(比如图片要定义宽高,避免页面塌陷,同时减少回流);
- 减少使用层级较深的选择器,或其他一些复杂的选择器,以提高CSS渲染效率;
- 在大量修改元素样式时,可以先用display: none将其隐藏,修改完再设置为display: block,这样只会造成两次回流;
2. 图片压缩,图片分割,精灵图
图片压缩:开发中比较重要的一个环节,现在很多图床工具都自带压缩功能的。如果需要自己压缩的话,可以在tinyPng 网站压缩一下;
- 图片分割:如果页面需要加载一张效果图,比如真机渲染图,UI设计师不允许压缩的时候,我们就可以将图片分割,然后再用css布局将图片拼接到一起。
- 精灵图:与图片分割相反,精灵图是将很多小图片合并到一张大图里,这样加载页面的时候,只需要加载一张图片,就可以加载出来所有的页面元素。这样在一定程度上提高了页面加载速度。而我们使用精灵图的方式,也是通过定位,即通过background-position来移动背景图,从而显示出我们想要显示出来的部分。
但是精灵兔有个很大的不足,那就是牵一发而动全身,因为我们使用精灵图需要准确测量每个元素的位置,一旦要调整页面,将会是一项很麻烦的工作。
3. 字体包压缩
问题描述: 在做类似活动h5的时候,难免需要使用 @font-face 接口引入一些字体包,以达到丰富的页面效果。但是完整的字体包文件一般都很好几兆,加载页面时,不仅会阻塞页面渲染,还会导致文字开始不会显示,直至字体包加载完才会显示文字。
解决方式: 可以使用font-spider字蛛将要使用到的文字提取出来。
4. 懒加载/预加载资源
懒加载: 简言之就是只有当图片出现在浏览器的可视区域内时,才加载图片让图片显示出来(在此之前可以将所有图片元素的路径全都统一设置成一张1*1px的占位图)。
判断图片出现在浏览器可视区域的方法:图片距离顶部的高度(offsetTop) - 页面被卷去的高度(scrollTop) 〈= 浏览器的可视区域的高度(innerHeight)
预加载: Resource Hints(资源预加载)包括预连接、资源与获取、资源预渲染等。
预加载的思路有如下两个:
当前将要获取资源的列表;
通过当前页面或应用的状态、用户历史行为或 session 预测用户行为及必需的资源.
实现Resource Hints的方法有很多种,可分为基于 link 标签的 DNS-prefetch、subresource、preload、 prefetch、preconnect、prerender,和本地存储 localStorage。
打包优化
1. webpack优化resolve.alias配置(vite同理)
resolve.alias 配置通过别名来将原导入路径映射成一个新的导入路径。
可以起到两个作用:1.起别名;2.减少查找过程
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
2. webpack优化resolve.extensions配置(vite同理)
resolve.extensions 代表后缀尝试列表,它也会影响构建的性能,默认是:
extensions: [‘.js’, ‘.json’]
例如遇到require(‘./data’)这样的导入语句时,Webpack会先去寻找./data.js文件,如果该文件不存在就去寻找./data.json文件,如果还是找不到就报错。
【所以后缀尝试列表要尽可能的小,不要把项目中不可能存在的情况写到后缀尝试列表中,频率出现最高的文件后缀要优先放在最前面,以做到尽快的退出寻找过程。】
在源码中写导入语句时,要尽可能的带上后缀,从而可以避免寻找过程。例如在你确定的情况下把require(‘./data’)写成require(‘./data.json’)。
resolve: {
extensions: ['.js', '.vue', '.json'],
}
3. webpack缩小loader范围
loader是很消耗性能的一个点,我们在配置loader的时候,可以使用include和except来缩小loader执行范围,从而优化性能。
{
test: /.svg$/,
loader: 'svg-sprite-loader',
include: [resolve('src/icons')]
},
4. split chunks代码分包
在没配置任何东西的情况下,webpack 4 就智能的帮你做了代码分包。入口文件依赖的文件都被打包进了main.js,那些大于 30kb 的第三方包,如:echarts、xlsx、dropzone等都被单独打包成了一个个独立 bundle。
其它被我们设置了异步加载的页面或者组件变成了一个个chunk,也就是被打包成独立的bundle。
它内置的代码分割策略是这样的:
新的 chunk 是否被共享或者是来自 node_modules 的模块;
新的 chunk 体积在压缩之前是否大于 30kb;
按需加载 chunk 的并发请求数量小于等于 5 个;
页面初始加载时的并发请求数量小于等于 3 个;
splitChunks({
cacheGroups: {
vendors: {
name: `chunk-vendors`,
test: /[\/]node_modules[\/]/,
priority: -10,
chunks: 'initial',
},
dll: {
name: `chunk-dll`,
test: /[\/]bizcharts|[\/]@antv[\/]data-set/,
priority: 15,
chunks: 'all',
reuseExistingChunk: true
},
common: {
name: `chunk-common`,
minChunks: 2,
priority: -20,
chunks: 'all',
reuseExistingChunk: true
},
}
})
vite配置代码如下:
build: {
rollupOptions: {
output: {
chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
assetFileNames: '[ext]/[name]-[hash].[ext]' // 资源文件像 字体,图片等
}
}
}
5. tree shaking
tree shaking(摇树)。望文生义,它是用来清除我们项目中的一些无用代码,它依赖于ES中的模块语法得以实现。 比如日常使用lodash的时候:
import _ from ‘lodash’
如果如上引用lodash库,在构建包的时候是会把整个lodash包打入到我们的bundle包中的。
import _isEmpty from ‘lodash/isEmpty’;
如果如上引用lodash库,在构建包的时候只会把isEmpty这个方法抽离出来再打入到我们的bundle包中。
tree shaking可以大大减少包体积,是性能优化中的重要一环。
在 vite 和 webpack4.x 中都已经默认开启tree-shaking。
6. vite关闭一些打包配置项()
webpack也有类似的配置,自行查阅
build: {
terserOptions: {
compress: {
//生产环境时移除console
drop_console: true,
drop_debugger: true,
},
},
//关闭文件计算
reportCompressedSize: false,
//关闭生成map文件 可以达到缩小打包体积
sourcemap: false, // 这个生产环境一定要关闭,不然打包的产物会很大
}
总体优化
1. SSR服务端渲染
SSR(Server Side Rendering),即服务端渲染。它指的是渲染过程在服务端完成,最终的渲染结果 HTML 页面通过 HTTP 协议发送给客户端,又叫“同构“。
SSR主要带来的好处就是 SEO 和首屏加载速度大大提高
2. Brotli 算法压缩
Brotli 压缩算法 是 Google 2015年推出的无损压缩算法。
启用 Brotli 压缩算法,对比 Gzip 压缩 CDN 流量再减少 20%。
针对常见的 Web 资源内容,Brotli 的性能相比 Gzip 提高了 17-25%;
当 Brotli 压缩级别为 1 时,压缩率比 Gzip 压缩等级为 9(最高)时还要高;
在处理不同 HTML 文档时,Brotli 依然能够提供非常高的压缩率。
兼容性:目前除了 IE 和 Opera Mini 之外,几乎所有的主流浏览器都已支持 Brotli 算法。
vite项目开启 brotli 压缩:
使用 vite-plugin-compression (opens new window)对平台进行 gzip 或者 brotli 压缩,nginx 对这两种压缩模式都支持,压缩后部署到 nginx 将极大提高网页加载速度。
修改 .env.production 文件,设置 VITE_COMPRESSION 全局变量即可
# 不开启压缩,默认
VITE_COMPRESSION = "none"
//以下配置压缩时不删除原始文件的配置
开启 gzip 压缩,
VITE_COMPRESSION = "gzip"
开启 brotli 压缩
VITE_COMPRESSION = "brotli"
# 同时开启 gzip 与 brotli 压缩
VITE_COMPRESSION = "both"
//以下配置压缩时删除原始文件的配置
开启 gzip 压缩
VITE_COMPRESSION = "gzip-clear"
开启 brotli 压缩
VITE_COMPRESSION = "brotli-clear"
# 同时开启 gzip 与 brotli 压缩
VITE_COMPRESSION = "both-clear"
3. 缓存
缓存的原理就是更快读写的存储介质+减少IO+减少CPU计算=性能优化。而性能优化的第一定律就是:优先考虑使用缓存。
缓存的主要手段有:浏览器缓存、CDN、反向代理、本地缓存、分布式缓存、数据库缓存。
4. Ajax可缓存
Ajax在发送的数据成功后,为了提高页面的响应速度和用户体验,会把请求的URL和返回的响应结果保存在缓存内,当下一次调用Ajax发送相同的请求(URL和参数完全相同)时,它就会直接从缓存中拿数据。
在进行Ajax请求的时候,可以选择尽量使用get方法,这样可以使用客户端的缓存,提高请求速度。
5.组件按需引入
使用第三方组件库时,要按需引入,例如import { Button } from ‘element-plus’;
6.动态加载
使用import()动态引入的语法引入一些第三方库和组件,例如我们在测试环境下开启 vconsole 调试:
if (location.host !== '正式环境域名') {
import('@/utils/vconsole')
}
7.组件异步加载
// 1. import懒加载
() => import('@/pages/xxx.vue')
// 2. 使用require
resolve => require(['@/pages/xxx.vue'], resolve),
8.路由懒加载
{
path: '/index',
name: 'index',
component: () => import('@view/xxx.vue'),
//或者 component: require(['@/view/xxx.vue'], resolve),
meta: { title: '首页' }
}