拆分代码 + 动态加载 + 预加载,减少首屏资源,提升首屏性能及应用体验

github 原文地址

我们看一些针对《如何提升应用首屏加载体验》的文章,提到的必不可少的措施,便是减少首屏幕加载资源的大小,而减少资源大小必然会想到按需加载措施。本文提到的便是一个基于webpack 插件与 react 组件实现的一套研发高度自定义、组件按需加载的资源预加载方案. 简单来说是为了通过配置 webpack 插件及少量业务代码即可实现Code Splitting + 组件懒加载 + 组件预加载。

🧐 为什么要做这么一套预加载方案?它存在的必要性在哪里?🧐

常规组件按需加载方案缺点

  • React.lazy 组件按需加载 - 组件渲染时加载组件资源
react.lazy(()=>import('xxxx/component'))

优点:拆分组件代码,按需加载, 减少首屏的资源加载大小及数量,提升页面首屏渲染速度。

  • import 动态加载 - 执行代码 import() 时加载组件资源
useEffect(() => {import('xxxx/component').then((loadScript) => {})
}, [])

优点:拆分组件代码,开发者可以更细粒度地控制组件按需加载的时机。

共有缺点:

代码拆分后,组件资源异步加载存在耗时,当组件资源特别大或网络不稳定时都有可能会出现 loading 时间过长导致组件迟迟无法渲染到视图上,以致于影响用户体验

如图是我们项目中实际出现的场景之一:

image.png

image.png

由于资源加载存在近4s的耗时,组件渲染被延迟,这种情况下,便导致了我们虽然通过减少了首屏资源提升了首屏加载体验,但却让用户在后续使用过程中出现了体验断层,甚至是页面白屏的情况,这对用户而言是不能接受的用户体验。

且这种情况并非网络不好或资源过大等极端情况下才会出现,随着应用使用量的上升,该情况会多次出现,影响用户体验,以下为网络波动的场景之一:
image.png

那么如果要保证一个spa应用的后续交互体验,那么就是不拆包,要么就需要引入组件预加载机制。
预加载的必要性:让被懒加载的组件资源提前进行对应的资源请求,而不是渲染时请求以减少组件渲染时间,保证应用不会因为组件拆包影响用户体验

react.lazy有一个局限就是必须放在<Suspense>组件内,无法独立渲染<LazyComponent />
image.png

为什么不是react-lodable?

其实 react 社区提供的 react-lodable 解决了以上两个问题:

  • 不强依赖 <Suspense>,可独立渲染<LazyComponent />
  • 提供了preload预加载方案,减少异步加载耗时,保证用户体验。
    image.png

但是有个问题是模块过多时,侵入式的代码也变多了,且看起来重复且冗余,同时被预加载的模块并没有进行统一管理,后续维护也不会很方便,不直观。

那么我们在 webpack 编译层面是可以获取到打包chunk的详细信息的,是不是可以在 plugin 层面对按需加载的chunk进行统一维护,同时减少侵入式代码,于是便有了此方案 route-resource-preload, 其具备的特性:

  1. 拆分模块按需加载,减少应用首屏资源请求大小及数量,提升加载体验.
    image.png
    dynamic 是基于 import()做的一个封装函数。
    image.png

  2. 支持组件资源批量自动预加载,同时支持自定义触发时机,如hover到某个组件上、某组件渲染时、出现在视图内时。( Component / Module-Federation / UMD / Svg / Png 等静态资源).

    自动预加载步骤:

    2.1 构建时添加插件
    image.png
    2.2 基于暴露的 dynamic API 对组件进行动态加载(拆包)并渲染, 同时可基于<PreloadLink>进行自动预加载。
    image.pngimage.png

  3. 支持手动调用预加载, 类 react-lodable 的方式,但支持批量.
    单个组件手动预加载
    image.png 多个组件手动预加载
    image.png

  4. 支持React <Suspense>,但不依赖。

  5. 完备的 typescript 类型推导.
    image.png

DEMO演示

在线体验地址
react.lazy 正常拆包并加载效果.gif
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

route-resource-preload 拆包并预加载效果.gif
preoload.gif

正常懒加载(react.lazy)普通组件 及 Module-Federation

WX20230424-113712.png

route-resource-preload 预加载普通组件 及 Module-Federation

WX20230424-113747.png

加载耗时如下:

资源正常懒加载 - react.lazy (ms)预加载 (ms)
普通组件 (单个资源文件)1841
Module-Federation 组件 (6个资源文件)4058

从表中可以看出,预加载显着提升了组件的加载速度,尤其是对于复杂的组件,加载速度的提升更为明显。 这说明在复杂的业务场景下,预加载可以显着提升组件加载速度和用户体验.

方案&流程介绍

该方案基于 @route-resource-preload/webpack-plugin 及 @route-resource-preload/react, 分别对应构建时运行时:

构建时流程图:
image.png

构建时 通过 dynamic API 及 webpack plugin 对模块进行拆包的同时,还会将preloadKey(开发者自定义的预加载标识)import-module-url(import 模块路径)chunk(output产物)三者之间的关系以json形式进行保存,并允许应用端访问。
image.png

生成的JSON文件:
image.png

JSON:
image.png

开发者基于 JSON,可以判断出可被预加载的chunk已配置预加载的chunk具体有哪些,同时也能知道插件中配置的预加载标识preloadKeychunk间的映射关系。

运行时流程图:
image.png
运行时 则是基于构建出的json,开发者通过设置Preloader 或者是<PreloadLink>preloadKey,对应的相关资源将被预加载,并基于 dynamic API 渲染组件。

项目效果演示

1. 真实用户场景打开 Modal( Modal基于 webpack module federation 引入)体验模拟
  • 无预加载时:点击按钮后,拉取对应的拆包资源及远程 module federation 组件资源,请求完成后渲染组件,存在体验卡顿,如下图。
    iShot_2023-07-20_18.25.23.gif
  • 有预加载时:hover到某个区域/某个组件渲染时(开发者自定义)即可触发资源预加载,点击按钮后立即渲染组件,不存在体验卡顿,如下图。
    iShot_2023-07-20_18.34.29.gif
2. 离线场景体验模拟

为了对比效果(有/无预加载)更加直观,以下将采用离线网络的场景下进行展示。

  • 无预加载时:按需加载在离线网络环境下会无法正常渲染,导致白屏。
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 有预加载时:按需加载在离线网络环境下,页面渲染体验正常,即实现拆包按需加载的用户体验等同于未拆包

预加载机制存在的必要性

  1. Any code can be split: 通过以上的预加载机制,实现应用内 Any code can be split(一切代码都可以被拆包),且能保证不影响用户体验,让开发者没有了因为单页面资源过大影响应用性能的烦恼,SPA(单页面应用) 也可以拥有极致的首屏幕加载体验和交互体验,🐟与🐻掌兼得。
  2. module federation(模块联邦) 组件预加载: 对于 webpack 的 module federation(模块联邦)而言,由于 module federation 打包出来的资源默认采用了按需动态加载的方案,因此当我们渲染一个比较大的 module federation 组件时,也会存在体验卡顿的情况,这时对该 module federation 组件进行预加载便可解决该体验问题。
  3. 革新开发者对组件懒加载的了解,减少开发者心智负担:开发者可以简单粗暴地基于页面维度对某个路由渲染的组件进行懒加载,不需要再从组件纬度去分析是因为哪个组件资源包过大导致的体验问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/186394.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电路布线问题动态规划详解(做题思路)

对于电路布线问题&#xff0c;想必学过动态规划的大家都很清除。今天就来讲解一下这个动态规划经典题目。 目录 问题描述输入分析最优子结构代码 问题描述 在一块电路板的上、下2端分别有n个接线柱。根据电路设计&#xff0c;要求用导 线(i,π(i))将上端接线柱与下端接线柱相…

通配符匹配

题目链接 通配符匹配 题目描述 注意点 s 仅由小写英文字母组成p 仅由小写英文字母、‘?’ 或 ‘*’ 组成‘?’ 可以匹配任何单个字符‘*’ 可以匹配任意字符序列&#xff08;包括空字符序列&#xff09; 解答思路 最初想到的是dfs 剪枝&#xff0c;但是用例超时了参照题…

搜索引擎Elasticsearch基础与实践

倒排索引 将文档中的内容分词&#xff0c;然后形成词条。记录每条词条与数据的唯一表示如id的对应关系&#xff0c;形成的产物就是倒排索引&#xff0c;如下图&#xff1a; ElasticSearch数据的存储和搜索原理 这里的索引库相当于mysql中的database。一个文档&#xff08;do…

SAP ABAP基础语法-Excel上传(十)

EXCEL BDS模板上传及赋值 上传模板事务代码&#xff1a;OAER l 功能代码&#xff1a;向EXCEL模板中写入数据示例代码如下 REPORT ZEXCEL_DOI. “doi type pools TYPE-POOLS: soi. *SAP Desktop Office Integration Interfaces DATA: container TYPE REF TO cl_gui_custom_c…

OpenGL_Learn08(坐标系统与3D空间)

目录 1. 概述 2. 局部空间 3. 世界空间 4. 观察空间 5. 剪裁空间 6. 初入3D 7. 3D旋转 8. 多个正方体 9. 观察视角 1. 概述 OpenGL希望在每次顶点着色器运行后&#xff0c;我们可见的所有顶点都为标准化设备坐标(Normalized Device Coordinate, NDC)。也就是说&#x…

uniapp使用vue

uniapp集成了Vuex&#xff0c;&#xff0c;并不需要安装vuex 定义自己的vuex vuex中独立命名空间&#xff1a; 可以在模块中使用 namespaced 属性&#xff0c;设置为 true&#xff0c;&#xff0c;这样做的好处是&#xff0c;&#xff0c;不同模块之间的state&#xff0c;mut…

istio 学习笔记

参考&#xff1a;istio简介和基础组件原理&#xff08;服务网格Service Mesh&#xff09;-CSDN博客 Istio 微服务框架 服务治理。 Istio的关键功能: HTTP/1.1&#xff0c;HTTP/2&#xff0c;gRPC和TCP流量的自动区域感知负载平衡和故障切换。 通过丰富的路由规则&#xf…

12 # 手写 findIndex 方法

findIndex 的使用 findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回 -1。 <script>var arr [1, 3, 5, 7, 8];var result arr.findIndex(function (ele, index, array) {console.log("ele----->", ele);conso…

C#中.NET 7.0控制台应用使用LINQtoSQL、LINQtoXML

目录 一、新建控制台应用和数据库连接 二、手动添加System.Data.Linq程序包 三、手动添加System.Data.SqlClient程序包 四、再次操作DataClasses1.dbml 五、示例 1.源码 2.xml文件 默认安装的.NET 7.0控制台应用是不支持使用LINQtoSQL、LINQtoXML的。 默认安装的.NET F…

如何用Java高效地存入一万条数据?这可能是你面试成功的关键!

大家好&#xff0c;我是你们的小米&#xff0c;一个热爱技术、喜欢分享的29岁程序猿。今天我要和大家聊一聊一个常见的面试题&#xff1a;在Java中&#xff0c;当我们需要将一万条数据存储到数据库时&#xff0c;如何能够提高存储效率呢&#xff1f; 在面试过程中&#xff0c;…

设计模式(3)-结构型模式

结构型模式 结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式&#xff0c;前者采用继承机制来组织接口和类&#xff0c;后者釆用组合或聚合来组合对象。 由于组合关系或聚合关系比继承关系耦合度低&#xff0c;满足“合成复用原则…

【机器学习】梯度下降预测波士顿房价

文章目录 前言一、数据集介绍二、预测房价代码1.引入库2.数据3.梯度下降 总结 前言 梯度下降算法学习。 一、数据集介绍 波士顿房价数据集&#xff1a;波士顿房价数据集&#xff0c;用于线性回归预测 二、预测房价代码 1.引入库 from sklearn.linear_model import Linear…

Python爬虫实战-批量爬取美女图片网下载图片

大家好&#xff0c;我是python222小锋老师。 近日锋哥又卷了一波Python实战课程-批量爬取美女图片网下载图片&#xff0c;主要是巩固下Python爬虫基础 视频版教程&#xff1a; Python爬虫实战-批量爬取美女图片网下载图片 视频教程_哔哩哔哩_bilibiliPython爬虫实战-批量爬取…

【Java】I/O流—缓冲流的基础入门和文件拷贝的实战应用

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;Java ⭐每日一句&#xff1a;你能坚持到什么程度&#xff0c;决定你能达到什么高度 &#x1f4e2;欢迎大家关注&#x1f50d;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 文章目录 一.&…

RapidSSL证书

RapidSSL是一家经验丰富的证书颁发机构&#xff0c;主要专注于提供标准和通配符SSL证书的域验证SSL证书。在2017年被DigicertCA收购后&#xff0c;RapidSSL改进了技术并开始使用现代基础设施。专注于为小型企业和网站提供基本安全解决方案的SSL加密。RapidSSL它具有强大的浏览器…

ZYNQ_project:key_led

条件里是十进制可以不加进制说明&#xff0c;编译器默认是10进制&#xff0c;其他进制要说明。 实验目标&#xff1a; 模块框图&#xff1a; 时序图&#xff1a; 代码&#xff1a; include "para.v"module key_filter (input wire …

python3.8.10虚拟环境安装talib总报平台不匹配

目录 环境&#xff1a; 需求&#xff1a; 问题&#xff1a; 概述 过程及解决 解决方案总结 环境&#xff1a; 操作系统&#xff1a;window10、64位 开发工具&#xff1a;pycharm python版本&#xff1a;python3.8.10 需求&#xff1a; 在python3.8.10的虚拟环境中安…

短短 45 分钟发布会,OpenAI 如何再次让 AI 圈一夜未眠

目录 前言 1. GPT-4 Turbo&#xff0c;更快&#xff0c;更省钱 2. GPT Store 来了&#xff01; 3. 零代码创建 AI Agent 前言 对于 AI 行业从业者来说&#xff0c;刚刚可能是一夜未眠。 北京时间 11 月 7 日凌晨&#xff0c;美国人工智能公司 OpenAI 的开发者大会正式开…

HTTParty库数据抓取代码示例

使用HTTParty库的网络爬虫程序&#xff0c; ruby require httparty # 设置服务器 proxy_host proxy_port # 使用HTTParty库发送HTTP请求获取网页内容 response HTTParty.get(/, :proxy > { :host > proxy_host, :port > proxy_port }) # 打印获取的网页内容 …

亚马逊云科技产品测评』活动征文|通过使用Amazon Neptune来预测电影类型初体验

文章目录 福利来袭Amazon Neptune什么是图数据库为什么要使用图数据库什么是Amazon NeptuneNeptune 的特点 快速入门环境搭建notebook 图神经网络快速构建加载数据配置端点Gremlin 查询清理 删除环境S3 存储桶删除 授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转…