对开发更友好的前端骨架屏自动生成方案

本文介绍了马蜂窝电商前端团队实现的一种自动化生成骨架屏的方法,旨在提升用户体验,减少白屏时间。通过Puppeteer操控Chrome生成骨架屏,解决手写骨架屏的维护难题。文章对比了现有的几种骨架屏方案,提出了一种读取配置文件,通过Puppeteer获取DOM结构并生成骨架屏的方案,该方案已应用于多页面项目中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击上方“马蜂窝技术”,关注订阅更多优质内容

一份来自 Akamai 的研究报告显示,在对 1048 名网购户进行采访后发现:

  • 约 47% 的用户期望他们的页面在两秒之内加载完成。

  • 如果页面加载时间超过 3s,约 40% 的用户会选择离开或关闭页面。


一直以来,为了提升用户在页面加载时的体验,无论是 Web 还是 iOS、Android 的应用中,前端开发工程师都做了许多工作。除了解决如何让网页展现速度更快的问题,还有很重要的一点就是提升用户对加载等待时间的感知。「菊花图」以及由其衍生出的各种加载动画就是一类常见的解决方案,相信无论是开发者还是用户对下面这个图标都不会陌生:

本文将要介绍的「骨架屏」则被视为菊花图升级版的方案。受现有骨架屏方案的启发,马蜂窝电商前端研发团队实现了一种自动化生成骨架屏的方法,并在马蜂窝商城的多个页面中实现应用,取得了不错的效果。

一、

什么是骨架屏

骨架屏可以理解为在页面数据尚未返回或页面未完成完全渲染前,先给用户呈现一个由灰白块组成的当前页面大致结构,让用户产生页面正在逐渐渲染的感受,从而使加载过程从视觉上变得流畅。生成后的骨架屏页面如下图所示:

骨架屏的主要优势为:

1.用户避免看到长时间的白页
2.可以获知页面的大体结构,减小用户认为页面出错而离开的机率
3.与菊花图相比视觉更加流畅

二、

常见的前端骨架屏方案

在选择骨架屏之前,我们也考虑了一些其他的方法,比如能否通过服务端渲染(SSR)的方式来避开前端白屏时间的问题。但发现需要涉及项目过多,还会涉及服务的构建与部署;或是通过 prerender-spa-plugin 提供简单的预呈现,它对 SPA 支持友好,但需要额外的 webpack 配置,且因为包源的问题,下载时间过长,有时还会莫名失败,等等,都因为种种原因最终放弃。

经过一系列调研后,我们对业界常见的几种骨架屏解决方案,以及它们的优势、不足进行了一个简单的梳理。

1. UI 骨架屏图

即通过 UI 提供符合页面首页样式的图来充当骨架屏,将骨架屏 base64 图片插入 root 根节点,在 webpack 打包时嵌入项目中。

这是一种简单粗暴的方法,实现起来比较容易。但缺点也很明显,就是需要 UI 设计师支持和开发介入,不能自动生成。

2.  手写骨架屏

即通过手写 HTML、CSS 的方式为目标页定制骨架屏。这种方式可以做到对页面真实样式的复刻。不过一旦由于各种原因导致页面样式发生改变,就需要再改一遍骨架屏的样式和布局,极大增加了维护的成本。

3. 自动生成静态骨架屏 

目前比较受关注的是饿了么开源的插件 page-skeleton-webpack-plugin,其具体实现原理为:

  • 生成骨架屏

通过 Puppeteer 操控 handless Chrome 打开需要生成的骨架屏页面,在等待页面加载完成之后,保留页面布局样式的前提下,通过对页面中元素进行增删,对已有元素通过层叠样式进行覆盖,使其展示为灰白块。然后将修改后的 HTML 和 CSS 提取出来,将页面分为不同的块区域,例如文本块、图片块、按钮块、SVG、伪类元素块等,分别对每个块进行处理,使其尽量与原页面保持一致。这里用到了 Puppeteer  page 实例的 addScriptTag 方法来将处理块的脚本插入到 headless Chrome 打开的页面当中。

实际生成的骨架屏页面与原页面可能还会存在差距,插件通过 memory-fs 将骨架屏写入内存中,可以通过预览页面对生成的骨架屏进行二次编辑和效果预览,修改完成后点击生成按钮就能生成一份新的骨架屏写入到项目中。

借一张图来说明:

  • 插入骨架屏

骨架屏的 DOM 结构和 CSS 通过离线生成后,在构建时注入模板 (EJS) 中的节点下面,插入到 HTML 是在 after-emit 钩子函数中进行。

page-skeleton-webpack-plguin 生成骨架屏的方案可以根据项目中不同的路由页面生成相应的骨架屏页面,并将骨架屏页面通过 webpack 打包到对应的静态路由页面中。

它的不足之处在于:

  • 实际使用过程中无法监听接口返回导致生成骨架屏的时机是否准确

  • 生成的页面与业务人员写的结构质量有直接关系,经常出现需要手工二次调整的情况

在这样的背景下,马蜂窝电商研发前端团队希望找一种在提升用户体验的同时,对开发更友好的骨架屏生成方式,能针对不同的业务场景自动生成出相似的骨架屏,并且实现自动注入。对于开发而言,只需要执行一条命令,或者简单配置,就可以生成骨架屏,不需要再考虑后续的维护工作。

在方案调研过程中,draw-page-structure 为我们的设计提供了灵感。

4. draw-page-structure

  • 生成骨架屏:


// dps.config.js
{
  url: 'https://baidu.com',
  output: {
    filepath: '/Users/famanoder/DrawPageStructure/example/index.html',
    injectSelector: '#app'
  },
  background: '#eee',
  animation: 'opacity 1s linear infinite;',
  // ...
}

根据 URL 指定的线上地址,配合 Puppeteer 获取当前页面的 DOM 结构,并对其中元素节点生成骨架屏文件到 filepath 指定的文件里面,就可以生成骨架屏页面,结果如下图所示:

  • 插入骨架屏

将上述生成的骨架屏文件插入到页面根节点下面一般为 id="app" 的节点,然后在通用工具里提供主动销毁骨架屏的方法,就可以帮助开发主动控制或销毁骨架屏,显示页面真实内容。

draw-page-structure 的设计思想很大程度上可以满足我们的需求,不足的是只能对线上已经存在的 URL 生成骨架屏,不支持开发环境。另外由于是自动生成,当页面存在重定向(如果未登录重定向到登录页面)的情况时,生成的骨架屏可能与预期不一致。而且它的内部实现并不完善,可能导致某些结构复杂的页面下生成的骨架屏需要二次优化调整。

于是,我们开始了进一步的探索。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值