拆分代码 + 动态加载 + 预加载,减少首屏资源,提升首屏性能及应用体验
github 原文地址
我们看一些针对《如何提升应用首屏加载体验》的文章,提到的必不可少的措施,便是减少首屏幕加载资源的大小
,而减少资源大小必然会想到按需加载
措施。本文提到的便是一个基于webpack 插件与 react 组件实现的一套研发高度自定义、组件按需加载
的资源预加载方案
. 简单来说是为了通过配置 webpack 插件及少量业务代码即可实现Code Splitting + 组件懒加载 + 组件预加载。
🧐 为什么要做这么一套预加载方案?它存在的必要性在哪里?🧐
常规组件按需加载方案缺点
- React.lazy 组件按需加载 - 组件
渲染时
加载组件资源
react.lazy(()=>import('xxxx/component'))
优点:拆分组件代码,按需加载, 减少首屏的资源加载大小及数量,提升页面首屏渲染速度。
- import 动态加载 - 执行代码
import()
时加载组件资源
useEffect(() => {import('xxxx/component').then((loadScript) => {})
}, [])
优点:拆分组件代码,开发者可以更细粒度地控制组件按需加载的时机。
共有缺点:
代码拆分后,组件资源异步加载存在耗时
,当组件资源特别大或网络不稳定时
都有可能会出现 loading 时间过长导致组件迟迟无法渲染到视图上,以致于影响用户体验
。
如图是我们项目中实际出现的场景之一:
由于资源加载存在近4s
的耗时,组件渲染被延迟,这种情况下,便导致了我们虽然通过减少了首屏资源提升了首屏加载体验,但却让用户在后续使用过程中出现了体验断层
,甚至是页面白屏的情况,这对用户而言是不能接受的用户体验。
且这种情况并非网络不好或资源过大等极端情况下才会出现,随着应用使用量的上升,该情况会多次出现,影响用户体验,以下为网络波动的场景之一:
那么如果要保证一个spa应用的后续交互体验,那么就是不拆包,要么就需要引入组件预加载机制。
预加载的必要性:让被懒加载的组件资源提前进行对应的资源请求
,而不是渲染时请求以减少组件渲染时间,保证应用不会因为组件拆包影响用户体验
。
react.lazy
有一个局限就是必须放在<Suspense>
组件内,无法独立渲染<LazyComponent />
。
为什么不是react-lodable?
其实 react 社区提供的 react-lodable 解决了以上两个问题:
- 不强依赖
<Suspense>
,可独立渲染<LazyComponent />
- 提供了
preload
预加载方案,减少异步加载耗时,保证用户体验。
但是有个问题是模块过多
时,侵入式的代码也变多了
,且看起来重复且冗余
,同时被预加载的模块并没有进行统一管理
,后续维护也不会很方便,不直观。
那么我们在 webpack 编译层面是可以获取到打包chunk
的详细信息的,是不是可以在 plugin 层面对按需加载的chunk
进行统一维护
,同时减少侵入式代码
,于是便有了此方案 route-resource-preload, 其具备的特性:
-
拆分模块按需加载,减少应用首屏资源请求大小及数量,提升加载体验.
dynamic
是基于import()
做的一个封装函数。
-
支持组件资源批量自动预加载,同时支持自定义触发时机,如hover到某个组件上、某组件渲染时、出现在视图内时。( Component / Module-Federation / UMD / Svg / Png 等静态资源).
自动预加载步骤:
2.1 构建时添加插件
2.2 基于暴露的 dynamic API 对组件进行动态加载(拆包)并渲染, 同时可基于<PreloadLink>
进行自动预加载。
-
支持手动调用预加载, 类 react-lodable 的方式,但支持批量.
单个组件手动预加载
多个组件手动预加载
-
支持React
<Suspense>
,但不依赖。 -
完备的 typescript 类型推导.
DEMO演示
在线体验地址
react.lazy 正常拆包并加载效果.gif
route-resource-preload 拆包并预加载效果.gif
正常懒加载(react.lazy)
普通组件 及 Module-Federation
route-resource-preload 预加载
普通组件 及 Module-Federation
加载耗时如下:
资源 | 正常懒加载 - react.lazy (ms) | 预加载 (ms) |
---|---|---|
普通组件 (单个资源文件) | 184 | 1 |
Module-Federation 组件 (6个资源文件) | 405 | 8 |
从表中可以看出,预加载显着提升了组件的加载速度,尤其是对于复杂的组件,加载速度的提升更为明显。 这说明在复杂的业务场景下,
预加载可以显着提升组件加载速度和用户体验
.
方案&流程介绍
该方案基于 @route-resource-preload/webpack-plugin 及 @route-resource-preload/react, 分别对应构建时
与运行时
:
构建时流程图:
构建时
通过 dynamic API 及 webpack plugin 对模块进行拆包的同时,还会将preloadKey(开发者自定义的预加载标识)
、import-module-url(import 模块路径)
、chunk(output产物)
三者之间的关系以json
形式进行保存,并允许应用端访问。
生成的JSON文件:
JSON:
开发者基于 JSON,可以判断出可被预加载的chunk
及已配置预加载的chunk
具体有哪些,同时也能知道插件中配置的预加载标识preloadKey
与chunk
间的映射关系。
运行时流程图:
运行时
则是基于构建出的json
,开发者通过设置Preloader 或者是<PreloadLink>
的preloadKey
,对应的相关资源将被预加载,并基于 dynamic API 渲染组件。
项目效果演示
1. 真实用户场景打开 Modal( Modal基于 webpack module federation 引入)体验模拟
- 无预加载时:
点击按钮后
,拉取对应的拆包资源及远程 module federation 组件资源,请求完成后渲染组件,存在体验卡顿
,如下图。
- 有预加载时:hover到某个区域/某个组件渲染时(开发者自定义)即可触发资源预加载,
点击按钮后立即渲染组件,不存在体验卡顿
,如下图。
2. 离线场景体验模拟
为了对比效果(有/无预加载)更加直观,以下将采用离线网络
的场景下进行展示。
- 无预加载时:按需加载在离线网络环境下会无法正常渲染,导致白屏。
- 有预加载时:按需加载在离线网络环境下,页面渲染体验正常,即
实现拆包按需加载的用户体验等同于未拆包
。
预加载机制存在的必要性
Any code can be split
: 通过以上的预加载机制,实现应用内 Any code can be split(一切代码都可以被拆包),且能保证不影响用户体验,让开发者没有了因为单页面资源过大影响应用性能的烦恼,SPA(单页面应用) 也可以拥有极致的首屏幕加载体验和交互体验,🐟与🐻掌兼得。module federation(模块联邦) 组件预加载
: 对于 webpack 的 module federation(模块联邦)而言,由于 module federation 打包出来的资源默认采用了按需动态加载
的方案,因此当我们渲染一个比较大的 module federation 组件时,也会存在体验卡顿
的情况,这时对该 module federation 组件进行预加载便可解决该体验问题。革新开发者对组件懒加载的了解,减少开发者心智负担
:开发者可以简单粗暴地基于页面
维度对某个路由渲染的组件进行懒加载,不需要再从组件纬度
去分析是因为哪个组件资源包过大导致的体验问题。
相关文章:

拆分代码 + 动态加载 + 预加载,减少首屏资源,提升首屏性能及应用体验
github 原文地址 我们看一些针对《如何提升应用首屏加载体验》的文章,提到的必不可少的措施,便是减少首屏幕加载资源的大小,而减少资源大小必然会想到按需加载措施。本文提到的便是一个基于webpack 插件与 react 组件实现的一套研发高度自定…...

在 Vue3 中使用 mitt 进行组件通信
npm 包地址 mitt 是一个轻量级的 JavaScript 事件触发器, 只有200b。有基本的事件触发、订阅和取消订阅功能,还支持用命名空间来进行更高级的事件处理。 功能特点: Microscopic —— weighs less than 200 bytes gzippedUseful —— a wil…...
SQLite 3.44.0 发布!
SQLite 开发团队于 2023 年 11 月 01 日发布了 SQLite 3.44.0 版本,带来了一些 SQL 和优化器增强,本文给大家做一个简要分分析。 新增 concat() 函数 新版本增加了两个连接字符串的函数:concat() 以及 concat_ws()。它们可以兼容 PostgreSQ…...

本地生活新赛道-视频号团购怎么做?
目前有在做实体行业的商家一定要看完,只要你进入了这个本地生活新的赛道,那你的生意自然会源源不断,那这个赛道又是什么呢? 这就是十月份刚刚上线的视频号团购项目,开通团购之后,就可以通过发短视频&#…...
输入一个url后,会发生什么事?
Internet上的每一个网页都具有一个唯一的名称标识,通常称之为URL(Uniform Resource Locator,统一资源定位器)。它是www的统一资源定位标志,简单地说URL就是web地址,俗称“网址”。 所以当我们在浏览器上输入一个url后&…...

R语言和jsonlite库编写代码示例
R语言和jsonlite库来下载的程序。 r # 导入jsonlite库 library(jsonlite) # 设置代理主机和端口 proxy_host <- "" proxy_port <- # 使用httr库创建一个对象 proxy <- create_proxy(proxy_host, proxy_port) # 使用httr库的GET方法下载网页内容 url <…...

容联七陌携手岚时科技,解决医美机构回访3大痛点
近日,岚时科技研发中心联合容联七陌发布了全新的智能呼叫中心系统,5大功能模块解决了医美机构回访过程中的3大难题:客户资产保全困难、客户回访技术被卡脖子、回访人员(客服、咨询)效率管理困难。 “智能呼叫中心”通过…...

自动计算零售数据分析指标?BI软件表示可行
随着BI技术的飞速发展,借助系统来计算分析指标也不是什么难事,即便是面对组合多变的零售数据分析指标,奥威BI软件也依旧可以又快又精准地完成指标计算。 BI软件可以自动计算零售数据分析指标,如销售额、库存量、订单量等。在计算…...
Qt读取xml文件并把内容显示到QTableview上
本例子中把xml文件作为数据库表。 xml文件名作为函数参数,把不同的xml文件名传入函数,会显示不同的文件内容。 以下为代码: void MainWindow::ShowContent(QString FileName) {LoadXmlContent(FileName);ShowContentInView();}bool MainWi…...
xv6-x86在ubuntu14.04 i386下正常编译、调试,在ubuntu23.04下编译各种报错--google镜像
来源 原git仓库 xv6-x86(xv6-public) 文档 mit 6.828/2023/ 文档 MIT 6.828/2018/xv6/book-rev11.pdf 原readme 注: xv6-x86(xv6-public) 已经被放弃了, 原作者转向了xv6-riscvxv6-x86文档来源:mit-pdos/xv6-book.git, 它需要 heirloom-doctools 来编译成pdf&#x…...

关于unity中 编辑器相关逻辑的记录
prefab 在场景中 , 用这个方法可以获取它的磁盘路径: [MenuItem("Gq_Tools/↓获取prefab路径")] public static void SaveDecalParameters() { var objs Selection.objects; var obj objs[0] as GameObject; Object parentObject Prefab…...
linux安装配置MongoDB并设置开机启动
linux安装配置MongoDB并设置开机启动 文章目录 linux安装配置MongoDB并设置开机启动1. 下载 MongoDB 的linux安装包2. 上传 MongoDB 安装包到linux系统中3. 解压 MongoDB 安装包4. 创建 MongoDB 必要目录5. 移动 MongoDB 安装目录6. 设置 MongoDB 环境变量7. 添加 MongoDB 配置…...

1366 - Incorrect string value: ‘\xE5\xB9\xBF\xE5\x85\xB0...‘ for column编码错误
1366 - Incorrect string value: ‘\xE5\xB9\xBF\xE5\x85\xB0…’ for column ‘campus_name’ at row 1 > 查询时间: 0s 原因是数据库创建的时候使用的默认编码latin1,导致表和字段的编码格式都是这种编码,显然这种编码不支持中文。 自己修改了数据库…...
K8S篇之谈谈kubelet的上报机制
浅析一下Kubelet的上报机制 1 kubelet上报节点状态 在K8S集群中,由运行在每个节点的Kubelet定期上报心跳到ApiServer,由此来判断Node是否存在,若Node超过一定时间没有上报心跳,则该节点的状态就会被设置为NotReady,同…...

混沌系统在图像加密中的应用(小波混沌神经网络)
混沌系统在图像加密中的应用(小波混沌神经网络) 前言一、小波混沌神经网络模型二、拓展三、python代码 前言 小波混沌神经网络是一种神经网络模型,结合了小波变换和混沌理论,用于信号处理、分类和预测。该模型基于多层前向神经网…...

Node.js中的文件系统(file system)模块
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

react组件间通信之context
一般用于【祖组件】与【后代组件】间通信 案例: A,B,C,D四个组件的关系分别为:爷爷,爸爸,儿子,孙子 从A向C传递参数:C组件为类式组件 从A向D传递参数:D组件为函数组件 import React, { Componen…...

京东数据分析:2023年10月京东洗衣机行业品牌销售排行榜
鲸参谋监测的京东平台10月份洗衣机市场销售数据已出炉! 10月份,洗衣机市场整体销售呈上升走势。鲸参谋数据显示,今年10月,京东平台洗衣机市场的销量为143万,环比增长约23%,同比增长约1%;销售额约…...

QQ恢复聊天记录,就用这3个方法!
无论是因为误操作、手机丢失、系统崩溃,还是因为更换了新手机,恢复重要的QQ聊天记录都是一件必做的事情。通过聊天记录,用户可以随时查看之前的信息,以便了解事情的经过。 那么,如何恢复丢失的QQ聊天记录呢࿱…...

高能数造电池3D打印智能制造小试线,开启全固态电池数字化新时代
在科技创新的浪潮中,电池制造领域又迎来了一次突破性的进展。近日,高能数造(西安)技术有限公司重磅推出了其最新电池数字制造装备——全固态电池3D打印智能制造小试线 ,这一创新性的技术开启了全固态电池的数字化智造新时代,为全固…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...

UE5 音效系统
一.音效管理 音乐一般都是WAV,创建一个背景音乐类SoudClass,一个音效类SoundClass。所有的音乐都分为这两个类。再创建一个总音乐类,将上述两个作为它的子类。 接着我们创建一个音乐混合类SoundMix,将上述三个类翻入其中,通过它管理每个音乐…...