Skip to content

使用流式传输来提高页面性能

Astro 的 SSR 使用 HTML 流将每个组件发送到浏览器(当可用时)以加快页面加载速度。为了进一步提高页面的性能,你可以策略性地构建组件,通过避免阻止数据获取来优化其加载。

¥Astro’s SSR uses HTML streaming to send each component to the browser when available for faster page loading. To improve your page’s performance even further, you can build your components strategically to optimize their loading by avoiding blocking data fetches.

以下重构示例演示了如何通过将 fetch 调用移至其他组件、将它们移出阻止页面渲染的组件来提高页面性能。

¥The following refactoring example demonstrates how to improve page performance by moving fetch calls to other components, moving them out of a component where they block page rendering.

下面 await 页的一些数据在其前面。Astro 将等待所有 fetch 调用解析,然后再将任何 HTML 发送到浏览器。

¥The following page awaits some data in its frontmatter. Astro will wait for all of the fetch calls to resolve before sending any HTML to the browser.

src/pages/index.astro
---
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,例如标题,然后在数据准备好时渲染段落。

¥Moving the await calls into smaller components allows you to take advantage of Astro’s streaming. Using the following components to perform the data fetches, Astro can render some HTML first, such as the title, and then the paragraphs when the data is ready.

src/components/RandomName.astro
---
const personResponse = await fetch('https://randomuser.me/api/');
const personData = await personResponse.json();
const randomPerson = personData.results[0];
---
<p>{randomPerson.name.first}</p>
src/components/RandomFact.astro
---
const factResponse = await fetch('https://catfact.ninja/fact');
const factData = await factResponse.json();
---
<p>{factData.fact}</p>

下面的 Astro 页面使用这些组件可以更快地渲染部分页面。<head><body><h2> 标签不再被数据获取阻止。然后,服务器将并行获取 RandomNameRandomFact 的数据,并将生成的 HTML 流式传输到浏览器。

¥The Astro page below using these components can render parts of the page sooner. The <head>, <body>, and <h2> tags are no longer blocked by data fetches. The server will then fetch data for RandomName and RandomFact in parallel and stream the resulting HTML to the browser.

src/pages/index.astro
---
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>

¥Including Promises directly

你还可以直接在模板中包含 Promise。它不会阻塞整个组件,而是并行解析 Promise,并且仅阻塞其后的标记。

¥You can also include promises directly in the template. Instead of blocking the entire component, it will resolve the promise in parallel and only block the markup that comes after it.

src/pages/index.astro
---
const personPromise = fetch('https://randomuser.me/api/')
.then(response => response.json())
.then(arr => arr[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>

在此示例中,A name 将在 personPromisefactPromise 加载时进行渲染。一旦 personPromise 解析完毕,A fact 将出现,factPromise 将在加载完成后渲染。

¥In this example, A name will render while personPromise and factPromise are loading. Once personPromise has resolved, A fact will appear and factPromise will render when it’s finished loading.

Astro 中文网 - 粤ICP备13048890号