前言

前端框架时代,为开发体验、效率与页面性能带来,非常大的革命。大家纷纷拿起一系列打包工具(webpack/parcel etc.),配合一系列加载器快速搭建起一个 SPA 页面。

SPA 应用带来的好处非常明显;

  • 提升页面切换体验
  • 降低切换时间
  • 易于部署&前后端分离

但是也带来一系列性能问题:

  • 初始加载脚本较大
  • 首屏空白时间较长
  • 页面返回时,数据被动重新拉取

这些问题是使用 SPA 模式不可避免的,通过了解 SPA 加载运行过程,可以逐渐看清楚引起性能问题的根本原因,通过精细化应用加载,来解决这些问题。

熊猫办公https://www.wode007.com/sites/73654.html

SPA 之殇

愈发发福

比起一般的简单页面,SPA 最大的问题,就是在初始化之时引入大量框架方案脚本,这导致脚本体积随着项目发展体积愈发增大。

不仅仅是体积

很多人会关注脚本的加载体积,通过一系列方案来提升缓存命中率,减少脚本请求次数。在网络环境较差的移动端,尽量减少请求时间意义很大。

但这不是银弹,移动设备对脚本的解析、编译、执行性能较差(脚本加载参考《图说舌尖上的脚本》),即便可以完全利用缓存,执行时间也是性能一大瓶颈。

Keep SPA Fit

性能优化原则:贫则独善其身,富则兼济天下。

如何维护一个大型 SPA?

随着项目不断发展,页面不断增加,源源不断的第三方组件&工具库加入到Bundle里面,良好的 SPA 架构可以保证大型 SPA 项目依旧保持极致的性能与体验。下面介绍一个优秀性能&体验 SPA 具备的特性:

性能优化

1. 快速启动 —— 极大提升加载速度(important)

快速启动应用,并行发起 Bundle 加载&拉取初始数据。相信大家已经发现了,SPA 初始化时候,不得不等待 bundle 返回并执行后,才会发起数据加载。

由于在移动设备上(即便有缓存)bundle 加载极为耗时,我们可以充分利用这段时间将数据进行预加载。这项特性,使得后面的优化起到更加明显的效果。

如下示例代码:

// app.js
Promise.all([load('bundle'), load('data')])

2. 根据路由拆分 —— 减少初始加载体积

利用异步加载方式,在路由注册时提供异步拉取组件的方法,仅在需要进入对应路由时,对应组件才会被加载进来。

route({
Home: () => import('@/coms/home'),
About: () => import('@/coms/about')
})

3. 独立打包异步组件公共 Bundle —— 提高复用性&缓存命中率

在Home和About等路由里面,可能公用一套 UI 组件,若不将异步加载公用组件统一打包,每次加载 路由时,都会额外加载一套 UI 组件。通过将公用组件提取打包成Vendor,可以减少下次进入路由加载体积与时间。

BTW:在webpack < 4时,依旧需要手动维护异步加载组件公用组件。webpack4提供更丰富的异步组件抽离方案。

4. 组件预加载 —— 减少页面切换时间

当首屏加载完毕后,设备&网络处于空闲状态,可以对其他路由组件进行预加载,以便提升页面切换性能。

预加载是一个非常繁琐的过程,我们可以设计一个极小启动器,在页面渲染后快速预加载后续组件:

// 所有包含Page的路由组件均会被预加载
boostraper.loadMatch('Page')

5. 使用 ESM 语法 —— 按需打包工具库,降低 Bundle 体积

webpack4在 ESM tree shaking上做了极大优化,使得在引用工具库时候真正做到"按需打包",这要求无论是自己开发的工具库,抑或使用第三方工具库,打包&使用 ESM 版本非常必要。

6. 配合 PWA 使用,口感更佳 —— 降低首屏渲染时间,极大提升体验

根据 PWA 缓存策略,可以将访问的页面index.html缓存起来,下次打开时候优先利用缓存,再发起请求更新缓存。这使得 SPA 应用几乎不需要额外时间便可加载应用首屏文档流。

体验优化

1. 构建你的极简Skeleton Page

SPA 首屏加载面临较长时间白屏,骨架图是一个完美的"缓兵之计"。在谷歌研究员的文章 中有提到,骨架图对用户体验有极大的提升:

  • 快速展示

    • 配合 PWA 首屏缓存,骨架图可实现瞬间加载&展示,首屏视觉上有冲击性地提升
  • 稳定加载

    • 消除页面初始加载因多次重绘&资源加载导致的"抖动"

需要注意的是,骨架图应尽量保持足够小巧与简单,以确保不会严重影响页面后续加载。

2. 页面切换 Loading

无论如何优化性能加载,在页面切换时候依旧需要获取页面数据,若处理不好,可能会在数据返回前有短暂的不友好"空白"。通过以下方式可以很好处理这个问题:

  • 友好的切换前 Loading

    • 在确保组件&数据加载完毕前,可保证页面可交互性,减少用户阻塞感
  • 转场动画

    • 在大多数原生应用,转场动画属于标配
    • 即时组件&数据已经完全加载,在切换至新页面瞬间,依旧需要页面渲染时间,这段时间可能导致页面短暂空白或者"视觉阻塞"
    • 通过转场动画时间,可以很好地缓解这个问题,大多数页面保证在转场动画完毕之后依然渲染完毕

最后

除了上述提到的 SPA 优化方案,Web 性能基础也是必备的基石(如域名收敛、合理文档结构)。性能优化本质是一个页面精细化监控运营的过程,也要求我们对 Web 加载的过程与逻辑有更多的思考与理解。

极致Web性能 —— SPA性能指南的更多相关文章

  1. 极致 Web 性能 —— SPA 性能指南

    前言 前端框架时代,为开发体验.效率与页面性能带来,非常大的革命.大家纷纷拿起一系列打包工具(webpack/parcel etc.),配合一系列加载器快速搭建起一个 SPA 页面. SPA 应用带来 ...

  2. 移动 H5(PC Web)前端性能优化指南

    原文地址https://zhuanlan.zhihu.com/p/25176904?utm_source=wechat_session&utm_medium=social&utm_me ...

  3. Web标准中用于改善Web应用程序性能的各种方法总结

    提起Web应用程序中的性能改善,广大开发者们可能会想到JavaScript与DOM访问等基于各种既存技术的性能改善方法.最近,各种性能改善方法被汇总成为一个Web标准. 本文对Web标准中所包含的各种 ...

  4. 《Java性能优化权威指南》

    <Java性能优化权威指南> 基本信息 原书名:Java performance 原出版社: Addison-Wesley Professional 作者: (美)Charlie Hunt ...

  5. 【Vuejs】335-(超全) Vue 项目性能优化实践指南

    点击上方"前端自习课"关注,学习起来~ 前言 Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 D ...

  6. 优化Web中的性能

    优化Web中的性能 简介 web的优化就是一场阻止http请求最终访问到数据库的战争. 优化的方式就是加缓存,在各个节点加缓存. web请求的流程及节点 熟悉流程及节点,才能定位性能的问题.而且优化的 ...

  7. ASP.NET Web API 提升性能的方法实践

    ASP.NET Web API 是非常棒的技术.编写 Web API 十分容易,以致于很多开发者没有在应用程序结构设计上花时间来获得很好的执行性能. 在本文中,我将介绍8项提高 ASP.NET Web ...

  8. H5 缓存机制浅析 移动端 Web 加载性能优化

    腾讯Bugly特约作者:贺辉超 1 H5 缓存机制介绍 H5,即 HTML5,是新一代的 HTML 标准,加入很多新的特性.离线存储(也可称为缓存机制)是其中一个非常重要的特性.H5 引入的离线存储, ...

  9. 读书笔记系列之java性能优化权威指南 一 第一章

    主题:java性能优化权威指南 pdf 版本:英文版 Java Performance Tuning 忽略:(0~24页)Performance+Acknowledge 1.Strategies, A ...

随机推荐

  1. Java实现哥德巴赫猜想

    验证哥德巴赫猜想:任何一个大于 6 的偶数,都能分解成两个质数的和.要求输入一个整数,输出这个 数能被分解成哪两个质数的和. eg : 14 14=3+11 14=7+7 public class T ...

  2. Java实现第九届蓝桥杯递增三元组

    题目6.递增三元组 题目描述 给定三个整数数组 A = [A1, A2, - AN], B = [B1, B2, - BN], C = [C1, C2, - CN], 请你统计有多少个三元组(i, j ...

  3. java实现第七届蓝桥杯四平方和

    四平方和 四平方和 四平方和定理,又称为拉格朗日定理: 每个正整数都可以表示为至多4个正整数的平方和. 如果把0包括进去,就正好可以表示为4个数的平方和. 比如: 5 = 0^2 + 0^2 + 1^ ...

  4. java代码(2)---Java8 Stream

    stream Java8新特性Stream流,那Stream表达式到底是什么呢,为什么可以使你的代码更加整洁而且对集合的操作效率也会大大提高? 一.概述 1.什么是Stream Stream是一种可供 ...

  5. OAuth2.0系列之基本概念和运作流程(一)

    @ 目录 一.OAuth2.0是什么? 1.1 OAuth2.0简介 1.2 OAuth2.0官方文档 二.OAuth2.0原理 2.1 OAuth2.0流程图 三. OAuth2.0的角色 四.OA ...

  6. Java基础(九)

    一.总述 多线程程序在较低的层次上扩展了多任务的概念:一个程序同时执行多个任务.通常,每一个任务称为一个线程,它是线程控制的简称.可以同时运行一个以上线程的程序称为多线程程序. 多进程与多线程的区别: ...

  7. ZooKeeper搭建集群

    ZooKeeper ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性 ...

  8. 在k8s上部署日志系统elfk

    日志系统elfk 前言 经过上周的技术预研,在本周一通过开会研究,根据公司的现有业务流量和技术栈,决定选择的日志系统方案为:elasticsearch(es)+logstash(lo)+filebea ...

  9. Redis底层结构全了解

    第一篇文章,思来想去,写一写Redis吧,最近在深入研究它. 一丶Redis底层结构 1. redis 存储结构 redis的存储结构从外层往内层依次是redisDb.dict.dictht.dict ...

  10. PageHelper支持GreenPlum

    greenplum是pivotal在postgresql的基础上修改的一个数据库,语法和postgresql通用.使用PageHelper做分页插件的时候,发现目前没有针对greenplum做支持,但 ...