最近在做项目的优化,除了整体的架构更改,我们发现在每次加载的时候,首页白屏的问题十分明显。

为什么会出现白屏

现在的前端框架, React、Vue、Angular 三大巨头已经占据了主导地位,市面上大多数前端应用也都是基于这三个框架或库完成,这三个框架有一个共同的特点,都是 JS 驱动,在 JS 代码解析完成之前,页面不会展示任何内容,也就是所谓的白屏。

用户是极其不喜欢看到白屏的,什么都没有展示,用户很有可能怀疑网络或者应用出了什么问题。 拿 Vue 来说,在应用启动时,Vue 会对组件中的 data 和 computed中状态值通过 Object.defineProperty 方法转化成 set、get 访问属性,以便对数据变化进行监听。

而这一过程都是在启动应用时完成的,这也势必导致页面启动阶段比非 JS 驱动(比如 jQuery 应用)的页面要慢一些。

所以我们首页就是一个典型的案例,在一次我们前端周会上,我们老大问了我们一个问题,如何给用户啊一个更好的体验。

SSR

这时候我第一个反应是,尽量不出现白屏的话,可以用VueSSR,就是服务端直出页面。

首先我们了解到,服务端渲染主要有两个目的,一是 SEO,二是加快内容展现。

在带来这两个好处的同时,我们也需要评估服务端渲染的成本,首先我们需要服务端的支持,因此涉及到了服务构建、部署等,同时 web 项目是一个流量较大的网站,也需要考虑服务器的负载,以及相应的缓存策略,特别像我们行业,由于地理位置的不同,不同用户看到的页面也是不一样的,也就是所谓的千人千面,这也为缓存造成了一定困难。

预渲染

所谓预渲染,就是在项目的构建过程中,通过一些渲染机制,比如 puppeteer或则 jsdom 将页面在构建的过程中就渲染好,然后插入到 html 中,这样在页面启动之前首先看到的就是预渲染的页面了。

但是该方案最终也抛弃了,预渲染渲染的页面数据是在构建过程中就已经打包到了 html 中, 当真实访问页面的时候,真实数据可能已经和预渲染的数据有了很大的出入,而且预渲染的页面也是一个不可交互的页面,在页面没有启动之前,用户无法和预渲染的页面进行任何交互,预渲染页面中的数据反而会影响到用户获取真实的信息,当涉及到一些价格、金额、地理位置的地方甚至会导致用户做出一些错误的决定。

骨架图

骨架页面(Skeleton Page)指的是当你打开一个移动端 web 页面,在页面解析和数据加载之前,首先给用户展示页面的大概样式。在骨架页面中,图片、文字、图标都将通过灰色矩形块或圆形块来展示,在真实页面展示之前,用户能够感知到即将加载页面的基本 CSS 样式和页面布局。

骨架屏初体验

一开始在我脑子里,以为骨架屏是一个页面去手写一个css和Html,或者说是让ui去设计一个骨架图。但是这样是有缺点的,比如产品改需求了呢,不仅要去修改代码,还要去重新修改骨架页面或者骨架图?

后来,看到了饿了么大神的文章和很成熟的产品page-skeleton-webpack-plugin ,瞬间明白了我和大佬的区别

解析-饿了么骨架屏

生成骨架页面的基本方案

通过 puppeteer 在服务端操控 headless Chrome 打开开发中的需要生成骨架页面的页面,在等待页面加载渲染完成之后,在保留页面布局样式的前提下,通过对页面中元素进行删减或增添,对已有元素通过层叠样式进行覆盖,这样达到在不改变页面布局下,隐藏图片、文字和图片的展现,通过样式覆盖,使得其展示为灰色块。然后将修改后的 HTML 和 CSS 样式提取出来,这样就是骨架页面了。

在阐述具体生成骨架页面之前,先了解下 puppeteer, GitHub 上是这样介绍的。

Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。

Puppeteer API 是分层次的,反映了浏览器结构。说实话,这是我第一次接触这个 Node 库,刚上手安装的时候就遇到了不少坑,哈哈哈哈哈哈,尴尬。

骨架屏的开发基本上就是基于这个node库开始的。接下来我们来解析一下基础代码

skeleton.js

const puppeteer = require('puppeteer')

const devices = require('puppeteer/DeviceDescriptors') //puppeteer 提供了一些设备的参数选项

const { sleep , genScriptContent } = require('./util/utils') //公共工具方法

const scriptFns = require('./util/browserUtils')

const skeleton = async function(url, option = {}) {

const defaultOption = {

device: 'iPhone 6'

}

const {

device,

defer = 0, //延迟的时间

remove = [], //页面想要移除的class类名数组

excludes = [], //页面想要不包括的class类名数组

hide= [],//页面想要隐藏的class类名数组

launch: launchOpt

} = Object.assign({}, defaultOption, option)

// 当 Puppeteer 连接到一个 Chromium 实例的时候会通过 puppeteer.launch 或 puppeteer.connect 创建一个 Browser 对象。

// 返回一个新的 [Page] 对象。[Page] 在一个默认的浏览器上下文中被创建。

const browser = await puppeteer.launch(launchOpt)

const page = await browser.newPage() //新建一个页面

/**

* 根据指定的参数和 user agent 生成模拟器。此方法是和下面两个方法效果相同

* @param { options }

* viewport

width 页面的宽度,单位像素.

height 页面的高度,单位像素.

deviceScaleFactor 定义设备缩放, (类似于 dpr). 默认 1。

isMobile 要不要包含meta viewport 标签. 默认 false。

hasTouch 指定终端是否支持触摸。默认 false

isLandscape 指定终端是不是 landscape 模式. 默认 false。

userAgent

*

*/

await page.emulate(devices[device])

await page.goto(url)

// 将一些 utils 插入到打开的页面执行环境中,这里会引入如何判断图片,文字的方法,将他们覆盖成灰色,也是骨架图中必不可缺的代买

await page.addScriptTag({

content: genScriptContent(...scriptFns)

})

/**

还应注意一点,defer 配置,用于告诉 Puppeteer 打开页面后需等待的时间,这是因为,在打开开发中页面后,页面中有些内容还未真正加载完成,如果在这之前进行骨架页面生成,很有可能导致最终生成的骨架页面和真实页面不符。使得生成骨架页面失败。

**/

await sleep(defer)

/**

* page.evaluate(pageFunction, ...args)

* pageFunction 要在页面实例上下文中执行的方法

...args <...> 要传给 pageFunction 的参数

返回: > pageFunction执行的结果

*/

const html = await page.evaluate(async ( remove, excludes, hide ) => {

const $ = document.querySelectorAll.bind(document)

if (remove.length) {

const removeEle = $(remove.join(','))

Array.from(removeEle).forEach(ele => ele.parentNode.removeChild(ele))

}

if (hide.length) {

const hideEle = $(hide.join(','))

Array.from(hideEle).forEach(ele => ele.style.opacity = 0)

}

const excludesEle = excludes.length ? Array.from($(excludes.join(','))) : []

await traverse(document.documentElement, excludesEle)

return document.documentElement.outerHTML

}, remove, excludes,hide)

// browser.close()

return { html }

}

module.exports = skeleton

复制代码下一篇,我们会认真的去分析,饿了么骨架屏中是如何去将页面根据不同元素分成不同的块:文本、图片块,SVG块,伪元素块、按钮块

将元素区分为不同块后,下一步就是对这些块分别进行处理,包括元素的增减和样式的覆盖,目的只有一个,就是将这些块转化为骨架页面的样式。

资源链接 饿了么大佬-Ran Luo 一种自动化生成骨架屏的方案

前端白屏问题_首页白屏的引发的思考(一)相关推荐

  1. 前端白屏问题_首页白屏优化实践

    前言 自从前端三大框架React.Vue.Angular面世以来,前端开发逐渐趋向规范化.统一化,大多数时候新建前端项目,首先想到使用的技术一定是三大框架之一,框架给前端开发带来了极大的便利和规范,但 ...

  2. 苹果手机录屏软件_手机录屏哪个软件好用?

    需要好用.清晰而且免费的手机录屏软件,其实手机自带的就能够满足大家了. 那么,手机自带的录屏功能如何开启呢?以下是详细的操作方法,一起来看下吧. 一.安卓手机录屏功能的开启: 1.首先,解锁软件的锁屏 ...

  3. jquery导航图片全屏滚动、首页全屏轮播图,各式相册

    1.目录结构 源码 project css js image index1 index2 index3 index4 index.html index1到index4分为四个iframe标签引入的可单 ...

  4. 华为手机怎么设置应用不全屏显示_手机投屏智能电视画面比例不合适怎么办?...

    手机投屏到电视的比例不对怎么办 知乎上有网友私下:"苹果手机屏幕镜像投屏到电视上,画面不能全屏,然后在网上查了一下是因为显示比例的问题,请问怎么解决?" 这个问题说简单也简单,说难 ...

  5. led拼接屏报价_液晶拼接屏与led显示屏的区别在哪?

    在目前的大屏显示产品中,液晶拼接屏和led显示屏是两种比较普遍的产品,拼接大屏是通过单个液晶拼接单元拼接而成的显示大屏,而led显示屏则是通过发光二极管组成密集点阵组成图像显示,我们通常听到的P1.P ...

  6. 装了mysql电脑黑屏怎么办_电脑黑屏的原因,教你解决黑屏

    电脑使用过程中突然出现黑屏的现象怎么办呢?电脑出现黑屏的原因有很多种,比如主板.CPU.内存.显卡等等都会造成电脑黑屏的,具体如何排除呢?接下来,小编给你详细解答怎么解决电脑黑屏. 电脑出现黑屏到底是 ...

  7. 日紫白飞星算法_紫白飞星择日法

    紫白飞星是一种重要的择日方法,五黄煞为择日中之大煞,所以一定要懂得剔除年月日时之"五黄",否则不小心犯之,为祸甚重.特别是动土之日课尤忌,没有一定的道行,还是避之为妙.另外,日课中 ...

  8. 安卓手机投屏软件_手机投屏软件哪个好?推荐这五款投屏神器

    现如今投屏在我们的工作生活中越来越常见了,电影投屏.游戏投屏.网课投屏.会议投屏等诸多场景相信大家也看过不少了.今天就来给大家分享五款非常不错的手机投屏软件,它们的功能各有千秋,大家可以任意选用. 一 ...

  9. 手机投屏不是全屏怎么办_手机投屏怎样才能全屏

    手机投屏怎样才能全屏 在统计7月份咨询量的时候,发现就手机用户而言,咨询比较多的不再是怎么投屏,而是怎么全屏. 因为电视机.各种投屏软件.投屏器的流畅,手机投屏到大屏幕已经不是什么"黑&qu ...

最新文章

  1. 浙江将建设超级高速公路,全面支持自动驾驶
  2. Jupyter Notebook快捷键
  3. 朋友,别告诉我你懂分布式事务!
  4. 足不出户完成交付独家交付秘籍(第二回)
  5. Python实现简单的购物车
  6. Angular:why click add button does not work for the second time
  7. asp 退出登录修改cookie能进入后台_深入浅出让你理解跨域与SSO单点登录原理与技术...
  8. android /data/data/数据作用,android 清除data/data/ 下其他应用的数据
  9. Linux下安装Beego:go install: cannot install cross-compiled binaries when GOBIN is set
  10. java应用uploadify 3.2丢失session
  11. 中小企业网络安全建设指引
  12. Cisco(61)——双出口策略路由PBR+NAT
  13. Websphere应用部署发布
  14. 西瓜文案:水果西瓜的文案,水果文案西瓜
  15. 区块链是什么通俗解释_区块链是什么,区块链是什么通俗解释
  16. 中美跨境电商贸易投资云洽会成功举办;TT Shop和TTforBusiness将互通;PhonePe月破20亿...|洞悉跨境
  17. 微信内的浏览器缓存清理方法
  18. sqlserver设计表不允许保存更改,阻止保存要求重新创建表的更改
  19. 解决chrome系浏览器ime-mode问题
  20. 【5万字】文件增量复制【OS库、Tkinter库等】

热门文章

  1. shell全面入门教程--IT隐匿者
  2. 青龙面板库 大全(9.6更新)
  3. vr计算机方面的应用,AR和VR到底有什么区别,分别应用在哪些方面?
  4. oeasy教您玩转linux010203显示logo
  5. excel批量改名字(含识别区分)
  6. distill_basic_teacher
  7. 虚拟机安装centeros7镜像
  8. 第5节 批处理编写及其示例
  9. mysql sniffer 源码_MySQL 抓包工具 - MySQL Sniffer 使用小结 (含带general_log日志)
  10. 人脑是量子计算机科学实验,你的大脑可能是一台量子计算机