前端实现首屏优化

本文已参与[新人创作礼]活动,一起开启掘金创作之路

近期正值春招和暑期实习招聘,楼主大大小小也面了10多场大厂面试,关于前端优化方面问的也挺多,其中比较常问的就是首屏优化了,所以,在此总结一下,前端实现首屏优化有哪些方式

首先,谈谈为什么要做性能优化,做性能优化的好处在哪?

性能优化的好处

前端,是一个产品直接展示在用户眼前的战场,而前端性能直接影响了用户体验。可以说,性能优化是初、中级工程师向高级工程师进阶的必学知识点,以及核心技能。

性能优化的商业价值

  • 对于mbify而言,主页加载的速度每提高100ms,转化率就会增加1.11%,平均年收入就会增加380000美元;
  • Pinterest重建了他们的页面以实现性能,使感知等待时间减少了40%,从而将搜索引擎流量和注册量提高了15%;
  • 通过将平均页面加载时间减少850毫秒,COOK发现他们能够将转化率提高7%,将跳出率降低7%,并将每个页面的页面数量增加10%;

可见前端性能优化对我们的影响和收入直接挂钩,高性能的网站比表现不佳的网站更好地吸引和留住用户。

“50%的用户会放弃访问加载超过3秒的网站”

如果高性能是一种资产,那么表现不佳就是一种负担。 性能优化是一个项目发展到一定时期之后绕不开的话题,也是每个工程师心中永远在撩拨的刺,产品的好坏决定着客户的体验,那么一款产品的好坏有很多因素,其中性能是决定因素。

  • 当用户能够在 2 秒以内得到响应时,会感觉系统的响应很快;
  • 当用户在 2-5 秒之间得到响应时,会感觉系统的响应速度还可以;
  • 当用户在 5-8 秒以内得到响应时,会感觉系统的响应速度很慢,但是还可以接受;
  • 而当用户在超过 8 秒后仍然无法得到响应时,会感觉系统糟透了,或者认为系统已经失去响应,而选择离开这个 Web 站点,或者发起第二次请求。

一个网站的性能好坏是留住用户和实现变现的基础,也是我们前端工程师每天都要关注的问题。

image.png

前端性能优化划分

其实,前端性能优化大体分为两个方向,一个是加载时优化,一个是运行时优化

  • 加载时优化:预加载、缓存、网络层、页面解析、静态资源、
  • 运行时优化:避免强制同步布局、长列表优化、避免js执行时间过长、并行计算-service worker、Composite分层绘制、滚动事件性能优化、Passive event listeners、动画

image.png

其中,首屏优化就属于加载时优化

首屏优化

首先,应该区分两个概念,一个是首屏时间,一个是白屏时间

  • 白屏时间是指浏览器从响应用户输入网址地址,到浏览器开始显示内容的时间。
  • 首屏时间是指浏览器从响应用户输入网络地址,到首屏内容渲染完成的时间。

image.png

  • 影响白屏时间的因素:网络,服务端性能,前端页面结构设计。
  • 影响首屏时间的因素:白屏时间,资源下载执行时间。

首屏性能指标

FPS:最能反映页面性能的指标FPS(frame per second),一般系统设置屏幕的刷新率为60fps。小于24就会出现明显的卡顿

DOMContentLoaded:DOM加载并解析完成会触发DOMContentLoaded事件,如果源码输出的内容太多,客户端解析DOM的时间也会变长,例如增加2000个嵌套层叠可能会相应增加50-200ms,尽量保证首屏输出即可,后续的内容只保留钩子,利用js渲染。

流畅度:FPS 值越高,视觉呈现越流畅,在等待的过程中可以加入一些视觉缓冲。

首屏加载时间:通过DOMContentLoad或者performance来计算出首屏时间

// 方案一:
document.addEventListener('DOMContentLoaded', (event) => {
    console.log('first contentful painting');
});
// 方案二:
performance.getEntriesByName("first-contentful-paint")[0].startTime
​
// performance.getEntriesByName("first-contentful-paint")[0]
// 会返回一个 PerformancePaintTiming的实例,结构如下:
{
  name: "first-contentful-paint",
  entryType: "paint",
  startTime: 507.80000002123415,
  duration: 0,
};
复制代码

image.png

image.png

1. DNS解析耗时: domainLookupEnd - domainLookupStart
2. TCP连接耗时: connectEnd - connectStart
3. SSL安全连接耗时: connectEnd - secureConnectionStart
4. 网络请求耗时(TTFB): responseStart - requestStart
5. 数据传输耗时: responseEnd - responseStart
6. DOM解析耗时: domInteractive - responseEnd
7. 资源加载耗时: loadEventStart - domContentLoadedEventEnd
8. 首包时间: responseStart - domainLookupStart
9. 首次渲染时间 / 白屏时间: responseEnd - fetchStart
10. 首次可交互时间: domInteractive - fetchStart
11. DOM Ready时间: domContentLoadEventEnd - fetchStart
12. 页面完全加载时间: loadEventStart - fetchStart
复制代码

加载慢的原因

在页面渲染的过程,导致加载速度慢的因素可能如下:

  • 网络延时问题
  • 资源文件体积是否过大
  • 资源是否重复发送请求去加载了
  • 加载脚本的时候,渲染内容堵塞了

优化方法

我们可以从这个过程来挖掘优化点:交给DNS域名解析 -> 找到对应的IP地址 -> 然后进行TCP连接 -> 浏览器发送HTTP请求 -> 服务器接收请求 -> 服务器处理请求并返回HTTP报文 -> 以及浏览器接收并解析渲染页面通过缩短请求时间,从而去加快网站的访问速度,提升性能。

常见的几种SPA首屏优化方式

  • 减小入口文件体积
  • 静态资源本地缓存
  • UI框架按需加载
  • 图片资源的压缩
  • 组件重复打包
  • 开启GZip压缩
  • 使用SSR

减小入口文件体积

常用方法:

  • 路由懒加载: Vue:箭头函数+import React:React.Lazy
  • 静态资源引入CDN

静态资源本地缓存

后端返回资源问题:

  • 采用HTTP缓存,设置Cache-ControlLast-ModifiedEtag等响应头
  • 采用Service Worker离线缓存

前端合理利用localStorage


UI框架按需加载

常见诸如Element-UI、Antd 快速使用中都有按需使用的文档


图片资源的压缩

图片资源虽然不在编码过程中,但它却是对页面性能影响最大的因素

对于所有的图片资源,我们可以进行适当的压缩

对页面上使用到的icon,可以使用在线字体图标,或者雪碧图,将众多小图标合并到同一张图上,用以减轻http请求压力。


组件重复打包

假设A.js文件是一个常用的库,现在有多个路由使用了A.js文件,这就造成了重复下载

解决方案:在webpackconfig文件中,修改CommonsChunkPlugin的配置

minChunks: 3
复制代码

minChunks为3表示会把使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件


开启GZip压缩

拆完包之后,我们再用gzip做一下压缩 安装compression-webpack-plugin

cnmp i compression-webpack-plugin -D
复制代码

vue.congig.js中引入并修改webpack配置

const CompressionPlugin = require('compression-webpack-plugin')
​
configureWebpack: (config) => {
        if (process.env.NODE_ENV === 'production') {
            // 为生产环境修改配置...
            config.mode = 'production'
            return {
                plugins: [new CompressionPlugin({
                    test: /.js$|.html$|.css/, //匹配文件名
                    threshold: 10240, //对超过10k的数据进行压缩
                    deleteOriginalAssets: false //是否删除原文件
                })]
            }
        }
复制代码

在服务器我们也要做相应的配置 如果发送请求的浏览器支持gzip,就发送给它gzip格式的文件 我的服务器是用express框架搭建的 只要安装一下compression就能使用

const compression = require('compression')
app.use(compression())  // 在其他中间件使用之前调用
复制代码

使用SSR

SSR(Server side ),也就是服务端渲染,组件或页面通过服务器生成html字符串,再发送到浏览器

从头搭建一个服务端渲染是很复杂的,vue应用建议使用Nuxt.js实现服务端渲染,React建议Next.js

运行时优化

运行时性能是指页面运行时的性能表现,而不是页面加载时的性能。可以通过chrome开发者工具中的 Performance 面板来分析页面的运行时性能。

比如:

  • 减少重绘与重排
  • 避免页面卡顿
  • 长列表优化
  • 滚动事件性能优化
  • 使用 Web Workers
  • 写代码时的优化点

image.png

参考链接

前端首屏优化

猜你喜欢

转载自juejin.im/post/7085375180167446535