使用rollup、esbuild等非webpack打包器时React SSR代码拆分有哪些替代方案?
非Webpack环境下React SSR代码拆分的替代方案及实现逻辑
一、Rollup、esbuild等打包器的可用替代方案
- React.lazy + 自定义SSR适配层:React 16.6+ 原生提供的
React.lazy本身仅支持客户端渲染,你可以基于它做轻量封装适配SSR场景。Rollup、esbuild都原生支持标准import()语法的代码拆分,不需要额外的打包器专属插件做特殊逻辑注入,只需要自行实现服务端动态组件收集、客户端chunk预加载的逻辑即可。 - 改造@loadable/component剥离Webpack依赖:可以保留
@loadable/component的运行时组件包裹逻辑,去掉它绑定的webpack专属插件部分,自行生成资源映射表:Rollup可以通过rollup-plugin-manifest输出chunk和源文件的对应关系,esbuild可以开启metafile参数生成构建元数据,写少量代码即可生成符合loadable运行时要求的资源映射表,完全可以替代原webpack插件的能力。 - React 18+ 流式SSR + Suspense:如果项目已经升级到React 18,配合流式SSR和Suspense可以实现和打包器解耦的代码拆分:服务端渲染时Suspense会自动处理动态组件的加载状态,不需要提前收集所有依赖的chunk,客户端只需要按需加载对应资源即可,适配成本非常低。
- 通用动态组件库:可以使用
react-async-component这类不绑定特定打包器的开源库,它只依赖标准ES动态导入语法,SSR适配逻辑和打包工具完全解耦,只需要自行维护动态组件和对应chunk的映射关系即可。
二、无需手动遍历React树预配置代码块
没有绑定特定打包器的辅助库时,完全不需要手动遍历React树来提前配置组件对应的代码块。
通用的实现逻辑如下:
- 首先封装统一的动态导入高阶函数,包裹所有需要拆分的组件的
import()语句,给每个动态组件分配唯一的标识(通常可以用组件源文件的相对路径作为ID),这个高阶函数在服务端运行时会自动收集本次请求触发渲染的所有动态组件ID。 - 构建阶段通过Rollup/esbuild的插件或者原生构建元数据能力,生成一份全局的「组件唯一ID - 对应chunk资源路径」映射表,分别注入到服务端和客户端的基础bundle中。
- 服务端渲染完成后,根据收集到的组件ID查映射表,得到本次请求需要的所有chunk路径,将其作为预加载标签注入到返回的HTML头部,客户端在hydration之前就会加载完所有需要的chunk,不会出现hydration不匹配的问题。
- 如果使用React 18的流式SSR,甚至不需要提前收集所有动态组件,Suspense的fallback会先在服务端输出占位内容,对应chunk加载完成后再流式替换实际内容,整个过程不需要预先遍历整个React组件树。
内容的提问来源于stack exchange,提问作者jwkoo
相关产品推荐
相关产品推荐

