内容

  • 简介

  • 特点

  • 服务器端渲染

  1. 初始负载

2.开始补水

3.完成补水

  • 性能和用户体验 (UX)

  • 部分补水

  • 个插槽

  • 缺点

  • 结论

简介

Astro 是一个新框架,它采用不同的方法来挑战许多其他框架(Gatsby、Next.js 和 Remix.run 等等)使用的现有渲染模式。

尽管该框架仍处于测试阶段,但该团队提供的功能迄今为止令人印象深刻。它带来了许多我认为值得研究的新鲜想法。

我能感觉到团队真的试图通过利用他们自己的Astro 编译器来连接开发人员体验 (DX) 和性能。

在本文中,我们将讨论 Astro 提供的主要功能,然后详细探讨其中的一些功能。

然后,我们将从基础层面进入服务器端渲染 (SSR),以形成我们围绕 Astro 引入的概念进行讨论的基础。然后,开始讨论 Astro 如何以不同的方式做事!

最后,我们将看一下它的一些缺点以及它目前最适用于哪种类型的应用程序。

特征

  • 开箱即用的功能

  • 模板(通过“插槽”)

  • 页面布局

  • 降价支持

  • 代码块

  • 拿来

  • 文件系统路由约定(类似于 Next.js)

  • Astro 组件 (.Astro)

  • 支持多种框架(Vue.js、React.js、Svelte、Solid.js 等)

  • 选择加入交互优化

  • 通过 hydration 指令(client:*- Astro 编译器提供)

  • 分页

  • RSS 提要

服务器端渲染

服务器端渲染的用例是改进搜索引擎爬取的 SEO。

这是因为单页应用程序或仅在客户端运行的网站很难让搜索引擎对其数据(如元标记和其他开放图详细信息)进行索引。

因此,如果没有生成的包含这些细节的 HTML,当用户搜索谷歌时,它会对网站的排名产生很大影响。

因此,服务器端渲染是解决这个问题的一个方法。这个过程是这样的:一个 HTML 文件(连同 CSS 和 js)在初始请求时提供给用户,然后客户端应用程序将“水合”DOM 元素。

最后,一旦完成了前面的所有步骤,它就可以观察用户的交互(即点击)。

让我们看一下这个过程的可视化,以便更好地理解它。

1.初始加载(HTML、js、CSS)

用户只看到空白页面的初始页面加载。

![](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%27391%27%20height=%27413%27/%3e)SSR 初始负载

<img altu003d"SSR 初始加载" srcsetu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-iv93sge.png&wu003d640&qu003d75 1x, /_next/image ?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-iv93sge.png&wu003d828&qu003d75 2x" srcu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com %2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-iv93sge.png&wu003d828&qu003d75" 解码u003d"async" data-nimgu003d"intrinsic" styleu003d"position:absolute;top:0;left:0;bottom:0;right:0;box-大小:边框框;填充:0;边框:无;边距:自动;显示:块;宽度:0;高度:0;最小宽度:100%;最大宽度:100%;最小高度:100% ;max-height:100%;object-fit:contain" classu003d"image" loadingu003d"lazy">

SSR 初始负载

2.开始补水

这是 Javascript 开始附加 DOM 事件侦听器(即 Click、KeyPress)的地方。

此时,CSS 也应该已加载并可用。

![](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%27391%27%20height=%27454%27/%3e)SSR 开始水合或绑定 DOM 事件

<img altu003d"SSR 开始水合或绑定 DOM 事件" srcsetu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-sya3s0y.png&wu003d640&qu003d75 1x, / _next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-sya3s0y.png&wu003d828&qu003d75 2x" srcu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn .hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-sya3s0y.png&wu003d828&qu003d75" 解码u003d"async" data-nimgu003d"intrinsic" styleu003d"position:absolute;top:0;left:0;bottom:0;right: 0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-高度:100%;最大高度:100%;对象拟合:包含“类u003d“图像”加载u003d“懒惰”>

SSR 开始水合或绑定 DOM 事件

3.完成补水

最后,在水合作用的开始和结束之间会有一段时间。如果您使用的是 React (<18),那么这个过程会同时发生并且它是“阻塞的”。意思是,它将滋润整个应用程序。然后,只有完成后,用户才能与之交互。

对于性能关键的应用程序,这可能会产生重大影响,尤其是在低端设备上和使用慢速网络连接(即 3G)时。

![](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%27391%27%20height=%27454%27/%3e)SSR 完成保湿

<img altu003d"SSR 补水" srcsetu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-i0b3sk6.png&wu003d640&qu003d75 1x, /_next/image ?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-i0b3sk6.png&wu003d828&qu003d75 2x" srcu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com %2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-i0b3sk6.png&wu003d828&qu003d75" 解码u003d"async" data-nimgu003d"intrinsic" styleu003d"position:absolute;top:0;left:0;bottom:0;right:0;box-大小:边框框;填充:0;边框:无;边距:自动;显示:块;宽度:0;高度:0;最小宽度:100%;最大宽度:100%;最小高度:100% ;max-height:100%;object-fit:contain" classu003d"image" loadingu003d"lazy">

SSR完成补水

性能和用户体验 (UX)

换个角度看上面的步骤,在时间线上看起来是这样的:

![](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%27800%27%20height=%27600%27/%3e)来源:Jason Miller 和 Addy Osmani 在网络上渲染。

<img altu003d"来源:Jason Miller 和 Addy Osmani 在网络上渲染。" srcsetu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-bdc3sdh.png&wu003d828&qu003d75 1x, /_next/image?urlu003dhttps%3A%2F% 2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-bdc3sdh.png&wu003d1920&qu003d75 2x" srcu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4Xrj-bdc3gkglSwSK413sdh 1920&qu003d75" 解码u003d"async" data-nimgu003d"intrinsic" styleu003d"position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0 ;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object -fit:contain" classu003d"image" loadingu003d"lazy">

资料来源:Jason Miller 和 Addy Osmani 在网络上的渲染。

如您所见,在 First Content Paint (FCP) 和 Time to Interactive (TTI) 之间有一小段时间,客户端应用程序正在经历水合阶段。

这会影响性能;随着您的捆绑包变得越来越大,加载请求以补充您的客户端站点/应用程序所需的时间越长。

此外,性能不是唯一受到影响的因素,UX 也受到影响。水化过程花费的时间越长,用户与您的网站或 Web 应用程序交互所需的时间就越多。

这可能会让用户在页面上的某个元素仍在补水并且根本不做任何事情时单击它,这可能会令人沮丧。

部分补水

那么,Astro究竟是如何解决这个问题的呢?

它通过部分水合作用来做到这一点。正如我在功能部分中提到的,使用 Astro 构建的网站默认是静态的。这意味着,不会提供任何 JS,并且在此过程中将剥离所有 JS。

⚠️ 注意: 当我们说“不提供 JS”时,我们指的是来自我们应用程序的 JS,而不是 Astro 的核心 JS 包。这对于延迟加载和组件水合(如果适用)等事情是必需的。

你可能会问,“好吧,如果我们的应用程序中的 JS 被剥离,那么你如何获得按钮上的点击事件?”好问题!

Astro 提供了指令,允许您明确指定您想要补水的组件以及何时补水。

此外,Astro 遵循“岛式建筑”的好处:

1.允许组件彼此独立加载

  1. 允许组件单独渲染

水合过程(部分/选择性水合)

![](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%27391%27%20height=%27454%27/%3e)部分/选择性水化渲染

<img altu003d"部分/选择性水化渲染" srcsetu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-qcd3sxf.png&wu003d640&qu003d75 1x, /\ _next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-qcd3sxf.png&wu003d828&qu003d75 2x" srcu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn. hackernoon.com%2Fimages%2FTlU0qyilehYV4XrjqgkglSwSK413-qcd3sxf.png&wu003d828&qu003d75" 解码u003d"async" data-nimgu003d"intrinsic" styleu003d"position:absolute;top:0;left:0;bottom:0;right:0 ;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height :100%;max-height:100%;object-fit:contain" classu003d"image" loadingu003d"lazy">

部分/选择性水化渲染

在此示例中,虽然页面的其余部分是静态的,但<Nav /><Button />组件在加载时是水合的。

福利

这样做的好处如下:

  1. 为客户端提供更少的 JS(更小的 JS 包)

  2. 独立的“岛”来单独加载和水合组件,而不是整个应用程序

示例:

根据用例,您还可以使用client:visible,它仅在组件可见时加载和水合组件。还有一些其他指令;随时查看文档。

如果您只是想确保您的组件在加载时获得水分,那么您将添加以下指令:

<Nav client:load />

<Button client:load />

对我来说,使用 Astro,你真的可以在 HTML 的速度和 Javascript 的活力之间找到一个很好的平衡点。

通过提供的指令优化代码非常容易。编译器处理所有繁重的工作。不需要编写额外的代码来处理这个问题。这是一件大事!

📝 有用的参考:

  • Astro - Hydrate 交互式组件

  • Astro - Island Architecture

  • Astro - 部分补水

  • Jason Miller - Island Architecture 概念

个插槽

我发现另一个有趣的功能是 Astro 的老虎机。与 react 的propchildren相比,这提供了更强大的原语。

我觉得这个插槽更类似于其他模板库,如 (Rails)erb,您可以在其中定义不同的children组件在布局组件中的位置,并让模板引擎将其渲染到正确的位置。

示例

// Card.tsx
import * as React from 'react';

import {
  CardHeading,
  CardWrapper,
} from '~/components';

interface CardProps {};
const Card: React.FC<CardProps> = (props) => {
  return (
    <CardWrapper>
      <CardHeading>
        <slot name="card-heading">
      </CardHeading>
      <CardImageWrapper>
        <slot name="card-image">
      </CardImageWrapper>
      <CardFooter>
        <slot name="card-footer">
      </CardFooter>
    </CardWrapper>
  );
};

// App.tsx
import { Card, Footer } from '~/components';
import * as React from 'react';

interface AppProps {};
const App: React.FC<AppProps> = (props) => {
  return (
    <Card>
      <div slot="card-heading">
        <h2>Suzy</h2>
      </div>
      <div slot="card-image">
        <img src="/images/cat-suzy.png" slot="card-image">
      </div>
      <Footer slot="card-footer" />
    </Card>
  );
};

天文组件

Astro 提供了自己的组件,它与 svelte 非常相似(如果您以前使用过它)。

所有内容(HTML、js、CSS)都在一个文件中,并且使用扩展名.Astro

💡 注意: 在 Astro 组件内部,您可以导入和渲染不同的组件(.vue.tsx.jsxsvelte)

示例

---
const title = "this is my title";
---

<h1 class="title">{title}</h1>

<style>
  .title {
    color: grey;
  }
</style>

💡 注意: astro 组件中的 CSS 默认作用域为组件!

📝 有用的参考:

  • Astro - 造型

数据获取

在 Astro 的脚本块中,支持await/asynctypescriptfetch等常见语法。

获取数据很简单,如下所示:

---
interface PokemonResult {
  name: string;
  url: string;
}
interface PokemonResponse {
  count: number;
  next: string;
  previous: number | null;
  result: PokemonResult[];
}
const response = await fetch('https://pokeapi.co/api/v2/pokemon');
const data: PokemonResponse = await response.json();
const result: PokemonResult = data?.result ?? [];
---

<ul>
  {(result) => <li>{result}</li>}
</ul>

<style></style>

📝 有用的参考:

  • Astro - 数据获取

环境变量

Astro 通过.env*文件提供环境变量。它使用的约定与其他框架非常相似。

环境变量有两类

  1. 公共(在客户端)- 在运行时可用,可以通过PULIC_*前缀定义

  2. Private (on server/build) - 在构建时可用,这是默认设置

⚠️ 所有环境变量都是私有的,除非使用 PUBLIC_ 前缀明确定义

用途

.env 文件:

UNSPLASH_API_KEY=xxxxxx

天文文件:

---
const requestUrl = 'https://api.unsplash.com/search/photos?page=1&per_page=15&query=surfing';
const response = await fetch(requestUrl, {
  headers: {
    'Authorization': `Client-ID ${import.meta.env.UNSPLASH_API_KEY}`
  }
});

const data = await response.json();
const results = data?.results || [];
const images = results.map(images => images.urls);
---

<section class="image-section">
  <ul>
    {images.map((imageSizes) => (
      <li class="image-container">
        <img src={imageSizes.small} />
      </li>
    ))}
  </ul>
</section>

<style></style>

📝 有用的参考:

  • Astro - 环境变量

  • Astro - 数据获取

缺点

在当前阶段,Astro 的唯一缺点是它的用例感觉有点小众。

许多开箱即用的功能,如代码块和降价,似乎都非常专注于构建开发者博客。我相信这只是暂时的,只是为了获得开发人员的采用,然后他们会在以后扩展到其他用例。

关于支持多个框架的问题,没有提到对路由和状态管理的支持,似乎也没有潜在的解决方案。

这是可以理解的,因为该框架仍处于测试阶段。尽管如此,我很高兴看到团队为即将发布的版本计划了什么。

不幸的是,尽管到目前为止令人印象深刻,但由于缺乏工具和生态系统,我还犹豫要不要用它来构建一个大型应用程序。

但是,这并不意味着您不应该跳进去尝试一下。文档清晰易懂。

我仍然相信 Astro 引入了许多有趣的新概念,无论您是否使用 Astro,都可以应用这些概念。

结论

总而言之,Astro 是一个在构建快速网站方面具有独特见解的项目。它带来了许多新的想法,我觉得这些想法很可能会传授给其他框架——这是很常见的事情。

此外,我注意到在提供的功能中真正关注 DX,我非常欣赏。

我们开始讨论基础知识,以更好地理解服务器端渲染 (SSR)。然后进一步分解它以了解 Astro 究竟做了哪些不同的事情以使其变得更好,以及这如何影响性能和用户体验。

在开发网站时,Astro 允许您在静态(使用 HTML)和动态(来自 js)之间找到最佳平衡点。它通过分层使用高级技术来做到这一点,例如先静态和选择性/部分水合,我们的页面被认为是孤立的“岛屿”,它们独立加载和水合。

试一试,自己看看。 Astro 在其示例存储库中提供了许多示例应用程序,这是一个很好的实验起点!

Logo

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐