使用关键路线的“快照”(静态渲染)加速大型 React 项目的最佳方法
Posted
技术标签:
【中文标题】使用关键路线的“快照”(静态渲染)加速大型 React 项目的最佳方法【英文标题】:Best way to speed up a big React project by using "Snapshots" of critical routes (static renders) 【发布时间】:2021-03-26 15:47:21 【问题描述】:我们有一个大型而复杂的传统 React 应用程序,我们在过去几年中一直在构建它。它加载一个 index.html 注入 javascript 并像往常一样从 API 获取数据。不幸的是,冷加载时间非常糟糕(平均 5 - 7 秒)。加载完所有内容后,它会像往常一样快速,但冷加载时间会在特定的“关键”页面中杀死我们。这些是我们的公共用户页面,格式为:https://mywebsite/userId
我们正在寻找一种方法来显着加快这些路线的加载时间,其方法不仅限于代码拆分或资源优化。我们已经这样做了,并且正在通过 CDN 为我们的应用提供服务。
我们已经研究过如何为这些用户页面创建静态“快照”,我们需要使用 react-static 之类的工具快速加载它们,并将它们作为静态版本提供并在以后对其进行水合。使用 next.js 或 gatsby 之类的东西重写我们的项目不是一种选择,因为它需要太多的工作。 s-s-r 也不是一个选项,因为我们的整个后端都是用 Django 而不是 Node.js 编码的
我们是否走在正确的轨道上?是否有可能/值得使用 react-static (或类似的工具)来做到这一点?有很多关于如何从头开始创建 react-static 项目的文档,但没有关于如何转换现有项目的文档,即使它只是我们需要的一小部分路由。
此外,一旦我们的用户页面上的数据发生变化,我们如何触发相应快照的“重建”?用户不会经常更新他们的数据,大约每月 4 次中的 3 次,但我们有 3000 个用户,所以平均每小时更新 15 次。我们可以只触发实际更改的路由的重建吗?
【问题讨论】:
使用服务工作者缓存这些路由怎么样?包括 api 路由,具有本地优先策略?第一次没有帮助,但后续加载会更快。 不幸的是,第一次对我们来说是最关键的。 95% 的流量来自在 FB 和 IG 等社交网站上使用这些链接的新用户。 我觉得 s-s-r 是您的性能问题的缺失环节。我注意到您提到您不能使用 node.js 功能为反应应用程序提供 s-s-r,但您是否尝试过使用 Django s-s-r 来反应集成?使用某种中间层在 Django 和 react 应用程序之间进行转换,可能不是最干净的解决方案,但我认为它值得一试,而无需进行任何其他重大更改以获得更好的性能。可能会通过搜索“django react s-s-r”查看谷歌上出现的任何内容 【参考方案1】:就像你说的,你可以使用 react-static。 他们有一个功能可以完全满足您的需求(用户的特定页面)。
在他们的示例中,他们使用一组帖子为每个帖子生成一个特定的静态文件。 由于它只是 html 静态文件,因此加载时间会大大减少。
想象一下这个场景:
[
id: 'foo',
...
,
id: 'bar',
...
,
...
]
按照下面的示例,这将生成类似这样的内容(在运行时):
- src
- pages
- blog
- posts
- foo // Specific post page
- bar // Specific post page
看例子:
//static.config.js
export default
// resolves an array of route objects
getRoutes: async () =>
// this is where you can make requests for data that will be needed for all
// routes or multiple routes - values returned can then be reused in route objects below
// ATTENTION: In here, instead of posts you'd fetch your users json data
const data: posts = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
return [
// route object
// React Static looks for files in src/pages (see plugins below) and matches them to path
path: "/blog",
// function that returns data for this specific route
getData: () => (
posts
),
// an array of children routes
// in this case we are mapping through the blog posts from the post variable above
// and setting a custom route for each one based off their post id
children: posts.map(post => (
path: `/post/$post.id`,
// location of template for child route
template: "src/containers/Post",
// passing the individual post data needed
getData: () => (
post
)
))
,
];
,
// basic template default plugins
plugins: [
[
require.resolve("react-static-plugin-source-filesystem"),
location: path.resolve("./src/pages")
],
require.resolve("react-static-plugin-reach-router"),
require.resolve("react-static-plugin-sitemap")
]
;
【讨论】:
感谢您的回答,我倾向于 react-static。我的问题是我可以使用 react-static 结构让它在一个简单的新项目中正常工作。但是我的大型 React 项目的结构不同,使用 React Router (v4) 并且到处都使用窗口和文档,所以它甚至不会构建。如果可以,我将对其进行更多研究并选择此答案。【参考方案2】:您可以使用 Service Worker。 将重要的快速页面加载为静态页面,然后在后台使用 Service Worker 加载更长的资源。
您还可以使用 Service Worker 进行智能缓存。 例如,服务器可以使用当前资源版本(第一页附带)设置一个 cookie,Service Worker 可以将其与它的资源版本进行比较,并决定是从缓存中加载它还是转到服务器。
【讨论】:
有趣的方法。服务工作者会在所有 JS 加载之前开始“工作”吗?请记住,这些“关键页面”是进入网站的入口点,因此如果 Service Worker 只能在所有内容加载后开始提供静态页面版本,那么问题仍然存在。以上是关于使用关键路线的“快照”(静态渲染)加速大型 React 项目的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
求运行3D MAX,MAYA,AE,RealFlow,Vray等,大型 三维软件,渲染的配置单。