killblanks 预渲染和骨架屏解决白屏问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
yuutan
V2EX    分享创造

killblanks 预渲染和骨架屏解决白屏问题

  •  
  •   yuutan 2021-03-09 15:27:48 +08:00 1364 次点击
    这是一个创建于 1756 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    白屏一直是 CSR 项目诞生来困扰前端的一大问题,如何在低成本的情况下,增加用户的等待时间,减少跳出率,以及提高页面性能,是前端一直在解决的难题,killblanks 作为其中一种的解决方案,将页面节点直接生成骨架屏,通过预渲染让用户能在等待内容加载时显示内容的轮廓,提供了更好的用户体验,并使内容感觉更快。

    白屏是怎么产生的

    这是一个普通 CSR 项目的Chrome performance截图,可以从快照中看到,白屏的时间大约在 330ms 左右,

    在这段时间里页面的执行逻辑 :

    • 请求 HTML -> 等待 HTML 文档 -> 解析 HTML -> 请求 JS 和 CSS 资源 -> 执行 vendors 和 index.js 逻辑

    330ms 后页面出现大体框架,页面的执行逻辑:

    • vue render 各个组件 -> mounted 页面挂载 -> 调用业务的 API 请求数据 -> 渲染返回的数据 -> 完整的页面

    正是因为 CSR 项目在等待文件加载CSSOM 构建JS 解析等过程中耗费了大量时间,导致了用户会长时间处于不可交互的首屏灰白屏状态,即白屏(blanks)

    详细可以看看寒阳的文章构建时预渲染:网页首帧优化实践

    白屏会影响什么

    通过分析 150 多个网站和 1.5 亿次页面访问的页面放弃数据,戈麦斯发现了游客忠诚度的匮乏,页面响应时间从 2 秒增加到 10 秒,页面跳出率增加了 38%

    简单来说每增加 1s 页面的等待时间,对于 app 来说是跳出率和成交率的下降,对于老板来说就是赔钱,对于你来说就是涨不了工资

    目前常用的白屏解决方案

    方案 预渲染 SSR NSR
    优点 不依赖数据 SEO 友好,构建方便,FMP 比预渲染快 SEO 友好,首屏性能高, FMP 最快
    缺点 SEO 不友好,FMP 慢 成本高,前端负载压力大 成本高,客户端压力大

    SSR 和 NSR 都是非常好的解决白屏的方案,但是缺点也很明显,成本太高,SSR 非常依赖服务的稳定性,对于中小公司而言很少有资源能为前端提供一套稳定的服务器环境,一旦 node 出现故障,损失很大,而 CSR 方案则是对于客户端来说成本很高,有很多不确定性。

    预渲染不是银弹

    基于此,预渲染可能是最简单也最实际的一种方案,但预渲染也并非是银弹,来看看我们团队第一个版本实现的预渲染

    当你高高兴兴的把辛苦做好的预渲染交给视觉视检时,可能换来的是只是一个字:(

    没错,或者说是不友好,感觉网速很慢,这些都是看过第一个版本的同事的反应,为什么会这样?

    通过两个截图对比可以发现

      1. 图片未加载导致页面存在大面积的色块
      1. 后端的请求未返回也造成了页面的空缺甚至是框架的变形

    我们发现问题主要在元素占位上,如果能提前对元素进行占位,预渲染就能渲染出很漂亮的页面,那么有没有方便 快捷 好看的占位元素呢?

    当我搜索解决方案的时候发现,早有人提出了一种占位方案

    一种自动化生成骨架屏的方案

    骨架屏

    是的,正是@Jocs,在 18 年分享了一种自动化生成骨架屏的方案,以及后续开源的page-skeleton-webpack-plugin,提供了一种成本较低的解决骨架屏的方案,为骨架屏实现方式提供一种新的思路,具体方案可以看看他的文章

    比较可惜的是page-skeleton-webpack-plugin三年没更新维护了,虽然是一种很可行的方案,但是还有很多能提高的空间,因此我决定在page-skeleton-webpack-plugin的基础上,提供一种更方便的方案,这就是Killblanks的由来

    Killblanks

    2020 年这个项目正式开始,经过半年的调试和开发,终于成功通过abtest测试,落地上线, 并于 2021 年 2 月开源,感谢每一位对此付出的人。

    原理

    利用Purpeteer能模拟浏览器请求页面的功能,加载谷歌插件@killblanks/skeleton-ext生成骨架屏组件的页面,直出 html 文件

    框架

    目前Killblanks依靠lerna构建,由三个核心功能组成

    使用

    Killblanks 使用非常方便,如果你明白其中原理,三分钟即可上手

    1. 安装

     yarn add @killblanks/prerender -D 

    2. 配置

    // webpack.config.js const prerender = require('@killblanks/prerender') export default { ... plugins: [new prerender()] ... } 

    3. 使用@killblanks/skeleton-ext

    4. 将生成的骨架屏组件使用在项目中

    • 比如像DEMO中所做的一样
    // index.vue <template> <div class="container"> <skeleton :show="!!filterProductList.length"> <div class="productionList"> <div v-for="(item, key) in filterProductList" :key="item.goods_id + key" class="production"> xxx </div> </div> </skeleton> </div> </template> <script> import skeleton from './skeleton' export default { components: { skeleton }, data: () => { return { filterProductList: [] } }, mounted() { setTimeout(() => { const res = JSON.parse( `{"goods_id":"5e7d6d331d41c801b95f594f","name":"skeleton-test","photo":"https://o-static.ihago.net/ikxd/e62403ac0d365c57b4dbc1a0ab7e9cf4/128.png","svga_photo":"","tag":"new","type":1,"type":1805,"real_price":199,"price":299,"discount":8000,"update_time":1594695268}` ) this.filterProductList = Array(10).fill(res) }, 3000) } } </script> 
    // skeleton.vue <script> import Vue from 'vue' const skeletOnLoader= { name: 'skeletocnLoader', functional: true, props: { show: { type: Boolean, default: false } }, render(h, context) { const { show } = context.props if (!show || window.__PRERENDER_INJECTED__) { const html = `<div>xxx</div>` const compOnent= Vue.compile(html) return h(component) } else { return context.children[0] } } } export default skeletonLoader </script> 

    5. 在浏览器的console输入PRERENDER_SKELETON

     在 Chrome console 中输入`PRERENDER_SKELETON`启动骨架屏预览 

    最后效果

    性能

    最后看看abtest测试,Killblanks带来的页面性能数据上的改变

    数据来源:

    利用公司在印度尼西亚上线的活动,进行 abtest 得出相关数据

    数据:

    type total fcp lcp
    @killblanks 1532 536ms 661ms
    Normal 1730 990ms 993ms

    First-contentful-paint(fcp)

    • FCP 平均值对比:536 : 990 @killblanks 能提升454ms, 平均提高45%

    Largest-contentful-paint(lcp)

    • LCP 平均值对比:661 : 993 @killblanks 能提升332ms, 平均提高33.4%

    未来

    killblanks 未来还有很多功能需要完善,目前正在做的

    • 单元测试
    • 优化文档
    • 支持 react && angular
    • 完善 demo

    欢迎各位前端朋友可以在issue留下自己的意见,拒绝白嫖,有时间就为killblanks点下吧。

    3 条回复    2021-03-09 17:06:19 +08:00
    amundsen
        1
    amundsen  
       2021-03-09 16:15:42 +08:00
    好东西
    justin2018
        2
    justin2018  
       2021-03-09 16:40:53 +08:00
    好东西
    iikebug
        3
    iikebug  
       2021-03-09 17:06:19 +08:00
    牛逼
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1078 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 23:30 PVG 07:30 LAX 15:30 JFK 18:30
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86