目录
- 1. 骨架屏
- 1.1 绘制静态骨架屏
- 1.2 代码绘制骨架屏
- 1.3 自动化解决方案
- 2. 使用动态的Polyfill
- 3. 代码分割
- 4. 使用资源预加载
前言
随着Vue、React等框架的出现,SPA单页面应用越来越多,多数的SPA应用的结构都很类似。由于SPA页面打包之后的JavaScript文件非常大,等这个巨大的JavaScript文件加载完之后,首屏才能渲染,这就导致出现了白屏的问题。还有在移动端,一些需要快速迭代的开发项目都是使用HTML5开发的,同样首屏加载白屏问题非常的严重。
下面就来看一下针对首屏渲染白屏的解决方案。
1. 骨架屏
骨架屏就是指在未加载完时,先简单的用图形勾勒出页面的大概布局,给用户一个视觉上更好一点的体验,等页面加载完成之后,再将骨架屏替换掉即可,如下图所示:
实现骨架屏的方式有很多种,下面来看下常见的几种。
1.1 绘制静态骨架屏
最直接的实现方案就是直接绘制一张骨架屏的图片,在资源加载完毕之后,页面内容直接替换这张图片即可。我们知道base64格式的图片可以直接插入到HTML文档中,并且可以节约一次HTTP请求,所以我们可以把骨架屏的静态图片直接转化为base64格式插入到HTML文件中。
我们可以监听onLoad
事件,只要他完成之后,将图片替换掉即可。如果是Vue项目,我们可以在mounted()
钩子中替换掉这张图篇。
1.2 代码绘制骨架屏
通过代码绘制骨架屏会比绘制静态图片更加灵活,可定制化程度高。我们可以根据自己的需要,绘制需要的样式。只需要根据首屏的大致轮廓绘制一个对应HTML结果,再用CSS填充上合适的背景色即可。
除此之外,我们还可以通过改动CSS,为这个骨架图添加一些动态的效果(加载动画),这样用户体验会更好。
1.3 自动化解决方案
如果我们需要给多个页面添加骨架图,那么就需要绘制多个骨架图,这样就比较麻烦。不过,现在已经有以下比较成熟的解决方案,目前使用比较广泛的是 page-skeleton-webpack-plugin插件,该插件是一个webpack插件,可以根据具体的页面生成对应的骨架屏,使用起来非常方便。
具体使用方法可以在github查看:page-skeleton-webpack-plugin
除此之外,Ant Design也提供了骨架屏的方案:Skeleton骨架屏
2. 使用动态的Polyfill
先来看一下Polyfill是干嘛用的:
全世界有许多不同的浏览器和版本的浏览器在使用,每种浏览器都具有与其他浏览器完全不同的功能集。这会使浏览器开发成为一项艰巨的任务。流行浏览器的最新版本可以完成许多旧浏览器无法完成的任务-但是您可能仍必须支持旧浏览器。通过尝试使用polyfills重新创建缺少的功能,Polyfill.io使其更容易支持不同的浏览器:您可以在支持和不支持的浏览器中利用最新和最强大的功能。
简单来说,就是Polyfill可以为就得浏览器提供和标签API一样的功能,无需引入插件,只要引入一个JS文件即可。
然而我们现在为了所有手机的都能够顺利跑起来项目,引入的 Polyfill 非常多。基于这种情况我们完全可以使用动态Polyfill来代替我们现有的比较笨重的兼容方式。动态Polyfill使用方法也非常简单,我们只需要引入一个<script>
标签即可:
<script src="https://polyfill.io/v3/polyfill.min.js"></script>
这样就保证了 polyfill 在我们需要的时候才会加载。如果对自己需要的 polyfill 比较清楚,也可以自己勾选需要的那部分,这样加载速度会更快。如下:
上图中勾选的三个,对应的script标签如下:
<script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2Ces2016%2Ces2017"></script>
注意:动态 Polyfill 是通过判断浏览器的 UA头,然后根据不同的浏览器选择其对应需要的 Polyfill。
3. 代码分割
最上面说到了由于打包的JavaScript文件很大,导致的首屏加载速度不理想,那么就可以从这方面下手,对代码进行分割,
代码分割:
代码分割指的是将项目代码构建打包之后,根据指定规则分割成多个输出文件,这些文件可以被按需加载或者并行加载,可以用来优化代码加载时的资源大小以及优先级。正确的使用代码分割可以提升资源加载效率。
具体的代码分割方案是在webpack进行配置,这里先不做解释。之后再写webpack优化的时候在介绍吧~
对于分割的代码我们可以进行按需加载,最常用的就是ES6中的import()
方法,在Vue项目中,我们经常用到的就是路由的按需加载。
4. 使用资源预加载
先来看一下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等等。如果用户进入指定的链接,隐藏的这个页面就会进入马上进入用户的视线。
这个属性虽然强大,但是却不能乱用,一定要确定这个页面用户的确会进行点击,才可以进行设置。否则用户不点,我们就浪费了大量的宽带资源去下载了一个无用的页面,这样反而得不偿失。
最后
关于首屏渲染白屏的解决方案还有很多。但是,归根结底,最主要的是对需要加载的资源进行优化,只要资源加载的足够快,首屏问题就解决了。我们可以借鉴《雅虎35条军规》中的原则,例如开启CDN、进行gzip压缩、对图片进行处理、懒加载等,都可以对首屏问题进行一定的优化。