前端性能优化系列 | 加载优化(下)

简介: 1. 资源加载优先级在浏览器发起网络请求时,并非每个字节都具有相同的优先级,所以,浏览器通常会对所要加载的内容进行推测,将相对重要的信息先呈现给用户。比如浏览器一般会先加载CSS,再去加载JavaScript脚本和图像文件。当然,浏览器的判断并不一定都是准确的,下面就来看看如何影响浏览器对资源加载的优先级。

(3)Intersection Observer实现

Intersection Observer是HTML5新增的API,可以用来实现图片懒加载。MDN中对Intersection Observer的解释:


IntersectionObserver接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。祖先元素与视窗(viewport)被称为根(root)。

当一个IntersectionObserver对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦IntersectionObserver被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。


上面使用节流来解决了scroll频繁触发的问题,这也说明传统的图片懒加载方案是存在一定问题的;而Intersection Observer不需要监听scroll事件,可以做到只要图片元素出现在可视区域内,就能进行回调,具体如下:


document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });
    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } 
});
复制代码

上面就是使用Intersection Observer完成图片懒加载的方法,该方法唯一的缺点就是兼容性还不是很好,如果需要兼容版本较低的浏览器,则要根据浏览器的版本封装更通用的方法。


(4)第三方库实现

除了上面介绍的一些延迟加载方法之外,还可以借助一些已经封装好的第三方库,下面是一些成熟的第三方库:

  • lozad.js 是超轻量级且只使用 Intersection Observer 的库, 因此它的性能极佳,但如果要在旧版本浏览器上使用,则需要配置polyfill。
  • lazysizes 是功能全面的延迟加载库,其使用的模式与本文所示的代码示例非常相似,会自动与 <img> 元素上的lazyload 类绑定,然后在data-src 和/或 data-srcset 属性中指定图像网址,该库还可以通过许多插件进行扩展,执行延迟各种资源等操作。
  • 如果使用React框架,可以使用 react-lazyload来进行图片懒加载操作,这个库是React图片懒加载的主流解决方案。
  • 如果使用Vue框架,可以使用 vue-lazyload 来进行图片懒加载操作,这个库是Vue图片懒加载的主流解决方案。


3. 首屏加载优化


随着Vue、React等框架的盛行,SPA单页面应用越来越多,多数的SPA应用的结构都很类似。由于SPA页面打包之后的JavaScript文件很大,等这个巨大的JavaScript文件加载完之后,首屏才能渲染,这就导致出现了白屏的问题。在移动端,一些需要快速迭代的开发项目都是使用HTML5开发的,同样首屏加载白屏问题非常的严重。下面就来看一下针对首屏渲染白屏的解决方案。


(1)骨架屏

骨架屏就是指在未加载完时,先简单的用图形勾勒出页面的大概布局,给用户一个视觉上更好一点的体验,等页面加载完成之后,再将骨架屏替换掉即可,如下图所示:

网络异常,图片无法展示
|


实现骨架屏的方式有很多种,下面来看下常见的几种:

  • 绘制静态骨架屏

最直接的实现方案就是直接绘制出一张骨架屏的图片,在资源加载完毕之后,页面内容直接替换这张图片即可。我们知道,base64格式的图片可以直接插入到HTML中,并且可以节约一次HTTP请求,所以,可以把骨架屏的静态图片直接转化为base64格式并插入到HTML文件中。只要监听onLoad事件,当完成之后,将图片替换掉即可。

  • 代码绘制骨架屏

通过代码绘制骨架屏会比绘制静态图片更加灵活,可定制化程度高。可以根据自己的需要,绘制需要的样式。只需要根据首屏的大致轮廓绘制一个对应HTML结果,再用CSS填充上合适的背景色即可。除此之外,还可以通过改动CSS,为这个骨架图添加一些动态的效果(加载动画),这样用户体验会更好。

  • 自动化解决方案

如果需要给多个页面添加骨架图,那么就需要绘制多个骨架图,这样就比较麻烦。不过,现在已经有以下比较成熟的解决方案,目前使用比较广泛的是 page-skeleton-webpack-plugin插件,该插件是一个webpack插件,可以根据具体的页面生成对应的骨架屏,使用起来非常方便。除此之外,Ant Design也提供了骨架屏的方案:Skeleton骨架屏


(2)资源预加载

上面提到了预加载,MDN中对资源预加载的解释:

页面资源预加载(Link prefetch)是浏览器提供的一个技巧,目的是让浏览器在空闲时间下载或预读取一些文档资源,用户在将来将会访问这些资源。一个 Web 页面可以对浏览器设置一系列的预加载指示,当浏览器加载完当前页面后,它会在后台静悄悄的加载指定的文档,并把它们存储在缓存里。当用户访问到这些预加载的文档后,浏览器能快速的从缓存里提取给用户。


简单来说就是当页面加载完成后或者其他空闲的时间,可以加载之后页面中用到的资源。


1)rel="preload"

可以使用rel属性,<link> 元素的 rel 属性的属性值preload能够让我们在HTML页面中 <head>元素内部书写一些声明式的资源获取请求,可以指明哪些资源是在页面加载完成后即刻需要的。


<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">
复制代码

这样,我们预加载了css和js文件,在随后的页面渲染的时候,如果需要使用这两个文件,直接使用即可,因为已经缓存好了。不仅是这些文件可以预加载,字体,图片,音视频文件都可以进行预加载。


2)rel="subresource"

除此之外,我们还可以使用 subresource 属性。subresource 和 preload 属性相比,它的优先级是最高的,使用方法和 preload 基本相同,如下:


<link rel="subresource" href="styles.css">
复制代码

因此,如果资源需要马上用到或者是当前页面急需的资源,就可以使用subresource。当然在实际的开发当中 preload 属性用的较多一些


3) rel="prerender"

prerender 可以指定加载一个页面的所有资源,使用方法如下:

<link rel="prerender"  href="/result.html" />
复制代码

prerender 的效果就和默认打开了一个隐藏的 tab 一样,会下载所有的资源、创建 DOM、渲染页面、执行 JS 等。如果用户进入指定的链接,隐藏的这个页面就会进入马上进入用户的视线。这个属性虽然强大,但是却不能乱用,一定要确定这个页面用户的确会进行点击,才可以进行设置。否则用户不点,就浪费了大量的宽带资源去下载了一个无用的页面,这样反而得不偿失。


4. 视频加载优化


(1)延迟加载视频

图片和视频这类静态资源资源占比都比较大。与图片一样,视频同样可以延迟加载,来达到优化性能的目的。正常情况下加载视频,使用的是<video>标签,那么对于一些需要由用户自己播放的视频,最好指定<video>标签的preload属性为none,这样浏览器就不会预加载任何视频数据。为了占用空间,可以使用poster属性为<video>占位。实现如下:


<video controls preload="none" poster="replace.jpg">
  <source src="main.webm" type="video/webm">
  <source src="main.mp4" type="video/mp4">
</video>
复制代码


(2)视频代替GIF动画

在业务开发中,我们应尽量使用视频代替尺寸过大的GIF动画,虽然GIF动画应用范围很广, 但是其在输出文件大小、图像色彩质量等方面均不如视频。GIF动画相对于视频具有三个附加的特性:没有音轨、连续循环播放、加载完自动播放,替换成视频后类似于:


<video controls autoplay loop muted playsinline>  
  <source src="main.webm" type="video/webm">
  <source src="main.mp4" type="video/mp4">
</video>
复制代码


其中video标签中附加的属性的含义分别为:autoplay自动播放、muted静音播放、loop循环播放、playsinline用于在ios系统中自动播放。这样,视频就基本实现了一个GIF动画的效果。


实际上,很多浏览器并不能像Chrome浏览器一样,能自动进行延迟加载。下面就来通过一些配置,使得该场景的视频也能延迟加载。首先需要修改HTML标签:

<video controls autoplay loop muted playsinline height:"500" width: "800" poster="replace.jpg">  
  <source data-src="main.webm" type="video/webm">
  <source data-src="main.mp4" type="video/mp4">
</video>
复制代码


这里为video标签添加了poster属性,用来指定图片为视频延迟加载出现前的占位,还使用了类似于图像懒加载的方式,将视频的真实地址放在了data-src中。下面就基于 Intersection Observer,用JavaScript实现对延迟加载的控制:


Document.addEventListener("DOMContentLoaded", () => {
    const lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));
    if("IntersectionObserver" in window) {
      const lazyVideoObserver = new IntersectionObserver((entries, observer) => {
          entries.forEach((video) => {
              if(video.isIntersecting) {
                for(const source in video.target.children) {
                    const videoSrc = video.target.children[source];
                    if (typeof videoSrc.tagName === "string" && videoSrc.tagName === " source") {
                        videoSrc.src = videoSrc.dataset.src;
                    }
                }
                video.target.load();
                video.target.classList.remove("lazy");
                lazyVideoObserver.unobserve(video.target);
              }
          })
      }) 
      lazyVideos.forEach((lazyVideo) => {
          lazyVideoObserver.observe(lazyVideo);
      });
    }
})
复制代码


对于视频的延迟加载有点类似于图片的懒加载,需要对所有source子元素进行迭代解析,将data-src的属性值迁移到src上。不同的是,需要额外显示调用元素的load方法来触发加载,然后视频才会根据autoplay属性开始进行自动播放,这样就能使用低于GIF动画的流量消耗,进行资源的延迟加载。

相关文章
|
1月前
|
前端开发 JavaScript UED
优化前端性能的关键技巧
在当今数字化时代,网站和应用程序的性能对用户体验至关重要。本文将介绍一些优化前端性能的关键技巧,包括减少HTTP请求、使用CDN加速、精简代码等方面的实用建议,帮助开发者提升前端性能,提供更流畅的用户体验。
|
1月前
|
缓存 前端开发 JavaScript
揭秘前端性能优化:从代码到用户体验的全面升级
揭秘前端性能优化:从代码到用户体验的全面升级
20 0
|
1月前
|
Web App开发 缓存 前端开发
前端性能优化方案有哪些?
前端性能优化方案有哪些?
73 1
|
1天前
|
前端开发 JavaScript Go
构建高性能Web应用:优化前端资源加载
在构建现代Web应用时,优化前端资源加载是至关重要的一步。本文将介绍一些提升Web应用性能的关键策略,包括减少HTTP请求、压缩和合并资源、使用CDN加速、以及异步加载技术等。通过实施这些优化策略,开发人员可以显著提升网站的加载速度和用户体验。
|
2天前
|
前端开发 JavaScript UED
如何优化前端网页加载速度
在当今互联网时代,网页加载速度成为了用户体验的重要指标之一。本文将介绍一些优化前端网页加载速度的方法,包括压缩资源、使用CDN加速、延迟加载等技术手段,帮助开发者提升网页性能,提高用户满意度。
|
9天前
|
缓存 前端开发 UED
优化前端性能的六大技巧
在当今互联网高速发展的时代,优化前端性能是每个开发者都必须重视的任务。本文将介绍六大实用的技巧,帮助开发者提升前端应用的性能,提升用户体验。
|
10天前
|
存储 缓存 前端开发
前端如何利用indexDB进行数据优化
使用IndexedDB作为浏览器内置的客户端数据库,用于存储大量数据和实现离线支持。它能缓存常用数据,减少服务器请求,提高用户体验。IndexedDB支持数据索引、复杂查询及版本管理,允许离线操作并同步到服务器。但需熟悉其异步API,可借助Dexie.js、localForage等库简化使用。
|
13天前
|
机器学习/深度学习 前端开发 算法
使用机器学习优化前端用户体验
在当今高度竞争的互联网市场中,用户体验是至关重要的。本文将探讨如何利用机器学习技术来优化前端用户体验,从而提高用户满意度和留存率。我们将介绍如何利用机器学习算法分析用户行为数据,优化网站性能和内容推荐,以及如何实时调整界面设计和交互方式,从而实现个性化、智能化的用户体验。
|
14天前
|
前端开发 算法 JavaScript
如何优化前端性能:探索图片压缩与延迟加载技术
本文深入探讨了前端性能优化中的关键问题:图片压缩与延迟加载技术。通过介绍图片压缩的原理和方法,并结合实例说明了如何有效减少图片大小、提升加载速度;同时,详细解析了延迟加载技术的实现原理及其在提高页面加载性能中的作用,为前端开发者提供了实用的优化方案。
|
16天前
|
缓存 前端开发 JavaScript
如何优化前端网页加载速度:7个实用技巧
在当今互联网时代,网页加载速度对用户体验至关重要。本文将介绍7个实用的技巧,帮助前端开发者优化网页加载速度,提升用户体验。从压缩资源到异步加载,从图片优化到缓存策略,这些技巧将帮助你在前端开发中取得更好的效果。