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

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.mfbz.cn/a/126766.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI 时代的企业级安全合规策略

目录 漏洞分类管理的流程 安全策略管理 在扫描结果策略中定义细粒度的规则 有效考虑整个组织中的关键漏洞 确保职责分离 尝试组合拳 本文来源&#xff1a;about.gitlab.com 作者&#xff1a;Grant Hickman 在应用程序敏捷研发、敏捷交付的今天&#xff0c;让安全人员跟上…

【亚马逊云科技产品测评】活动征文|AWS EC2 部署Echarts大屏展示项目

前言 Echarts简介 ECharts是一个使用JavaScript开发的&#xff0c;开源的可视化库。它可以让数据变得生动起来&#xff0c;提供直观&#xff0c;交互性强&#xff0c;可高度个性化定制的数据可视化图表。ECharts支持大部分的浏览器&#xff0c;如IE6、Chrome、Firefox、Safari等…

不用开会员就能在线编辑、管理及分享各类地理空间数据!

「四维轻云」作为一款地理空间数据云管理平台&#xff0c;具有三维模型、正射影像、激光点云、数字高程模型、人工模型和矢量数据等地理空间数据的在线管理、浏览及分享等功能&#xff0c;致力于为用户提供更加方便、快捷的地理空间数据解决方案。 一、发布、管理超大空间数据…

韩语图片文字如何转为纯文本?

如何将上图为韩语的图片转为文本文件&#xff1f;这个需要用到OCR程序&#xff0c;操作方法如下&#xff1a; 一、打开金鸣识别网站。 二、点击“点击添加图片/PDF”&#xff0c;将待识别的图片添加到列表。 三、识别模块点选“通用文字”&#xff0c;输出格式选择“纯文本输…

Python3 API 的封装及调用

一、API 的封装 API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力&#xff0c;而又无需访问源码&#xff0c;或理解内部工作…

【Node.js入门】1.3 开始开发Node.js应用程序

1.3 开始开发Node.js应用程序 学习目标 &#xff08;1&#xff09;熟悉开发工具Visual Studio Code的基本使用&#xff1b; &#xff08;2&#xff09;掌握Node.js应用程序的编写、运行和调试的基本方法。 构建第一个 Node.js应用程序 代码 const http require("htt…

前端js实现将数组对象组装成自己需要的属性,或者去掉对象中不必要的属性

前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 需求&#xff1a;前端js实现将数组对象组装成自己需要的属性&#xff0c;或者前端js实现去掉对象中不必要的属性 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、示例数组对象…

浅谈多回路电表在荷兰光伏系统配电项目中的应用

1.背景信息 Background&#xff1a; 随着全球化石能源&#xff08;石油&#xff0c;煤炭&#xff09;越来越接近枯竭&#xff0c;污染日趋严重&#xff0c;气候日益变暖等问题&#xff0c;全球多个国家和地区相继出台了法规政策&#xff0c;推动了光伏产业的发展。但是现有的光…

vioovi的ECRS工时分析软件:食品加工行业的生产效率提升利器

在食品加工行业&#xff0c;提高生产效率、降低成本、优化资源配置是至关重要的。随着科技的不断发展&#xff0c;越来越多的企业开始借助先进的软件工具来助力生产管理。本文将介绍一款备受食品加工企业青睐的工业工程软件——vioovi的ECRS工时分析软件&#xff0c;并探讨其如…

PR如何开启GPU加速

1.首先在 NCIDIA控制面板 找到 管理3D设置 &#xff08;记得前提是你的显卡驱动程序是最新的或者已经安装了显卡驱动程序&#xff09; 2.在管理3D设置里面 找到程序设置 自定义程序&#xff1a; Adobe premiere 里面的 CUDA - GPUs 改成 使用全局设置 &#xff08;如果还有…

面试题:在 Java 中 new 一个对象的流程是怎样的?彻底被问懵了。。

文章目录 前言JVM内存JVM生成.class文件类加载器加载.class文件知识扩展&#xff1a;Class对象首先搞清楚 newInstance 两种方法区别&#xff1a; 连接和初始化创建实例 前言 对象怎么创建&#xff0c;这个太熟悉了&#xff0c;new一下(其实还有很多途径&#xff0c;比如反射、…

结合element的el-tooltip实现文本溢出进行省略,鼠标移入显示全部

结合element的el-tooltip实现文本溢出进行省略&#xff0c;鼠标移入则显示全部。如果没有出现省略&#xff0c;鼠标移入则不进行浮出显示。 多简单的一个功能&#xff0c;搜了一下其它人写的&#xff0c;写的简直是一言难尽。 <!--* 轮子的作者: 轮子哥* Date: 2023-08-29…

SAM + 用于文本到图像修复的稳定扩散

推荐基于稳定扩散(stable diffusion) AI 模型开发的自动纹理工具&#xff1a; DreamTexture.js自动纹理化开发包 - NSDT 什么是SAM&#xff1f; 今年早些时候&#xff0c;Meta AI 发布了新的开源项目&#xff1a;Segment Anything Model &#xff08;SAM&#xff09;&#xff…

day3 ARM

【昨日作业】 .text .global start _start: mov r0,#0 存放sum mov r1,#1 存放相加的数值 loop: cmp r1,#100 bhi wh add r0,r0,r1 add r1,r1,#1 b loop wh: b wh .end 【内存读写指令】 通过内存读写指令可以实现向内存中写入指定数据或者读取指定内存地址的数据 c语言内存…

MySQL最新2023年面试题及答案,汇总版(3)【MySQL最新2023年面试题及答案,汇总版-第三十三刊】

文章目录 MySQL最新2023年面试题及答案&#xff0c;汇总版(3)01、隔离级别与锁的关系&#xff1f;02、SQL 约束有哪几种呢&#xff1f;03、如何优化子查询&#xff1f;04、什么是前缀索引&#xff1f;05、MySQL5.6和MySQL5.7对索引做了哪些优化&#xff1f;06、MySQL有关权限的…

Linux学习第34天:Linux LCD 驱动实验(一):星星之火可以燎原

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 LCD显示屏是由一个一个的像素点构成的。当你能控制一个像素点的亮暗及颜色变化的时候&#xff0c;你就能让LCD显示瓶显示五颜六色的整幅图案。甚至可以让LCD屏幕…

Spring-Security前后端分离权限认证

前后端分离 一般来说&#xff0c;我们用SpringSecurity默认的话是前后端整在一起的&#xff0c;比如thymeleaf或者Freemarker&#xff0c;SpringSecurity还自带login登录页,还让你配置登出页,错误页。 但是现在前后端分离才是正道&#xff0c;前后端分离的话&#xff0c;那就…

Django快速入门(一)

Django三板斧 1. 基本使用 三板斧: HttpResponse,render,redirect from django.shortcuts import HttpResponse,render,redirect# 一. 返回字符串类型的数据 return HttpResponse(字符串) # 二. 返回HTML文件 # 1. 动态HTML页面: return render(request,login.html) def ab…

极智开发 | CUDA线程模型与全局索引计算方式

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文分享一下 CUDA线程全局索引计算方式。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq CUDA 线程全局索引的计算,是很容…

图文加多个测试带你彻底搞懂Netty ChannelPipeline的执行顺序(附源码)

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 netty version 4.1.65.Final ChannelPipeline 是什么 Pipeline&#xff0c;管道、流水线&#xff0c;类似于责任链模式。基本上我们使用Netty开发程序需要编写…
最新文章