React路由间百分比预加载进度条实现方法咨询
嘿,这个需求我之前也琢磨过,不用现成包完全可以自己实现核心逻辑,我给你拆解成几个关键步骤,你跟着思路走就行:
核心实现思路拆解
一、先明确:document/window没有直接获取待下载总量的方法
浏览器本身没有提供直接拿到路由切换时要加载的所有资源总量的API,因为这些资源(比如路由对应的组件代码chunk)是webpack打包后的产物,所以我们得提前从打包环节拿到每个chunk的大小信息,这是实现百分比进度的前提。
二、第一步:获取路由对应Chunk的大小
React路由切换时的代码分割(比如用React.lazy)会把每个路由组件打包成单独的chunk,webpack在构建时会生成包含所有chunk大小的stats.json文件。你可以:
- 构建后把这个
stats.json引入项目,或者在webpack配置里通过DefinePlugin把chunk大小注入全局变量,比如:
这样你就能通过// webpack.config.js const { StatsWriterPlugin } = require('webpack-stats-plugin'); // 先生成stats.json,再读取它把chunk大小注入全局 new DefinePlugin({ 'window.__CHUNK_SIZES__': JSON.stringify(require('./stats.json').assetsByChunkName) })window.__CHUNK_SIZES__['About']拿到对应路由组件chunk的大小了(这里的About是你用/* webpackChunkName: "About" */指定的chunk名)。
三、第二步:监听Chunk加载进度
有了总大小,接下来要追踪加载的实时进度,有两种常用方式:
方式1:手动用Fetch加载Chunk(替代React自动加载)
如果不想用React.lazy的默认加载逻辑,可以手动fetch chunk,这样能直接拿到ProgressEvent的loaded和total:
const loadRouteComponent = async (chunkName) => { // 先从全局变量拿到chunk的URL和大小 const chunkUrl = `/static/js/${chunkName}.bundle.js`; const totalSize = window.__CHUNK_SIZES__[chunkName]; const response = await fetch(chunkUrl); const reader = response.body.getReader(); let loaded = 0; while (true) { const { done, value } = await reader.read(); if (done) break; loaded += value.length; // 计算百分比,传递给进度条状态 const progress = Math.min(Math.round((loaded / totalSize) * 100), 100); updateProgressBar(progress); } // 加载完成后执行chunk代码,获取组件 const module = await import(/* webpackChunkName: "[request]" */ `./routes/${chunkName}`); return module.default; };
方式2:用PerformanceObserver监听资源加载
如果还是想用React.lazy,可以用浏览器的PerformanceObserver监听资源加载事件,过滤出当前路由的chunk:
const observer = new PerformanceObserver((list) => { const entries = list.getEntriesByType('resource'); entries.forEach(entry => { // 判断当前资源是不是目标路由的chunk if (entry.name.includes(window.__CURRENT_ROUTE_CHUNK__)) { const progress = Math.round((entry.transferSize / entry.decodedBodySize) * 100); updateProgressBar(progress); } }); }); observer.observe({ entryTypes: ['resource'] });
注意:这里需要在路由跳转时记录当前要加载的chunk名(__CURRENT_ROUTE_CHUNK__),方便过滤。
四、第三步:React中管理进度条状态
- 用React Context或者轻量状态管理工具(比如Zustand)维护进度百分比的全局状态,进度条组件订阅这个状态,实时更新UI。
- 路由切换的完整流程:
- 开始跳转:初始化进度为0%,显示进度条;
- 加载中:实时更新进度;
- 加载完成:把进度拉到100%,延迟几秒后隐藏进度条;
- 加载失败:重置进度,显示错误提示(可选)。
五、边界情况处理
- 缓存资源:如果chunk已经在浏览器缓存里,直接设置进度为100%,避免进度条闪一下;
- 多Chunk加载:如果一个路由依赖多个chunk,要把所有chunk的总大小相加,再累加每个chunk的已加载量;
- 进度条动画:可以用CSS过渡让进度条的变化更平滑,避免跳变。
内容的提问来源于stack exchange,提问作者R.Thompson
相关产品推荐
相关产品推荐

