使用流式传输提升页面性能
Astro 的 SSR 使用 HTML 流式传输,在每个组件可用时将其发送到浏览器,以加快页面加载速度。为了进一步提高页面的性能,你可以有策略地构建组件,通过避免阻塞性数据获取来优化其加载。
下面的重构示例演示了如何通过将 fetch 调用移动到其他组件,从而将它们移出阻塞页面渲染的组件,以提高页面性能。
以下页面在其 frontmatter 中 await
了一些数据。Astro 会等待所有的 fetch
调用都解析完成后,才会向浏览器发送任何 HTML。
---const personResponse = await fetch('https://randomuser.me/api/');const personData = await personResponse.json();const randomPerson = personData.results[0];const factResponse = await fetch('https://catfact.ninja/fact');const factData = await factResponse.json();---<html> <head> <title>A name and a fact</title> </head> <body> <h2>A name</h2> <p>{randomPerson.name.first}</p> <h2>A fact</h2> <p>{factData.fact}</p> </body></html>
将 await
调用移到更小的组件中,可以让你利用 Astro 的流式传输。通过使用以下组件来执行数据获取,Astro 可以首先渲染一些 HTML,比如标题,然后在数据准备好后再渲染段落。
---const personResponse = await fetch('https://randomuser.me/api/');const personData = await personResponse.json();const randomPerson = personData.results[0];---<p>{randomPerson.name.first}</p>
---const factResponse = await fetch('https://catfact.ninja/fact');const factData = await factResponse.json();---<p>{factData.fact}</p>
下面使用这些组件的 Astro 页面可以更快地渲染页面的某些部分。<head>
、<body>
和 <h2>
标签不再被数据获取阻塞。服务器将并行获取 RandomName
和 RandomFact
的数据,并将生成的 HTML 流式传输到浏览器。
---import RandomName from '../components/RandomName.astro';import RandomFact from '../components/RandomFact.astro';---<html> <head> <title>A name and a fact</title> </head> <body> <h2>A name</h2> <RandomName /> <h2>A fact</h2> <RandomFact /> </body></html>
直接包含 Promise
标题为“直接包含 Promise”的部分你也可以直接在模板中包含 Promise。它不会阻塞整个组件,而是会并行地解析该 Promise,并且只阻塞其后的标记(markup)。
---const personPromise = fetch('https://randomuser.me/api/') .then(response => response.json()) .then(personData => personData.results[0].name.first);const factPromise = fetch('https://catfact.ninja/fact') .then(response => response.json()) .then(factData => factData.fact);---<html> <head> <title>A name and a fact</title> </head> <body> <h2>A name</h2> <p>{personPromise}</p> <h2>A fact</h2> <p>{factPromise}</p> </body></html>
在这个例子中,当 personPromise
和 factPromise
正在加载时,A name
会先渲染。一旦 personPromise
解析完成,A fact
就会出现,而 factPromise
会在它加载完成后渲染。