Astro 1.0 正式发布,给前端带来了什么?

就在上周,Astro 团队发布了 1.0 的正式版本。

从年初我就开始关注这个项目了,但当时只是学习了一下仓库的工程化搭建相关的东西 (changesets 自动发包之类),并没有深入了解它本身的功能。借着正式发版的机会,这几天熟悉了一下 Astro 1.0,发现了很多有意思的地方,下文会分别从团队背景框架定位核心优势几个维度给大家展开介绍,最后也会推荐一些学习资料。

团队背景

在正式介绍 Astro 之前,先给大家聊一聊相关的背景。Astro 的作者是 Fred K. Schott,没错,就是那个开发 Snowpack 的老哥,可以说是 Unbundle 构建工具的祖师爷,但无奈的是 Vite 发展势头实在太猛,而 Snowpack 渐渐日薄西山,他本人也写了文章发出下面的感慨:

image.png

文章链接: dev.to/fredkschott…

大意就是 Snowpack 前途渺茫,用户越来越少,感觉要做到头了啦,而 Vite 发展的非常好,那后面开发的 Astro 就基于 Vite 来做吧。现在连 Snowpack 的官网都表示弃坑了,主动给 Vite 引流:

当然,除了 Snowpack,Fred K. Schott 的团队(叫Pika)还做了一件比较知名的产品: Skypack,即 NPM 包的 ESM CDN 服务:

不幸的是,Skypack 也很长时间(一年多)没有维护了,可以看出团队也不再想继续投入这个项目了,个人感觉主要有两个原因:

  • 竞争对手的强大。竞品 esm.sh 一直在持续迭代且已经得到了 Deno 的官方推荐。
  • 方案落地困难。此类 ESM CDN 应用到实际的业务项目中仍然有诸多的现实障碍,如请求数量多、不能 Tree Shaking、不能本地调试等等,要落地是一个比较难的问题,本人在 一文中也有过专门的总结。

在近些年的时间里,Fred K. Schott 团队一直将重心放在了新项目 Astro 上面,经过 16 个月的打磨, Astro 在全球拥有了 30000 多个用户,被 Google、Netlify 等大公司使用,Github 的 star 已经达到 15k +。

值得一提的是,Fred K. Schott 为了这个项目专门成立了一个创业公司: The Astro Technology Company,并且已经融到了 700 万美刀的种子轮投资,打算一直以开源的方式发展下去。相比于一些知名开源项目的赞助收入,如 Webpack 22 w 刀/年、Babel 30 w 刀/年,Astro 在经济方面有如鱼得水的优势。

框架定位

接下来聊一聊 Astro 框架的定位,是像 Vue、React 这样的底层渲染框架,还是像 Next.js 这种上层的研发框架?

这一点其实挺困扰初学者的,因为 Astro 既自创了类似于.vue.jsx文件的 .astro 语法,又提供了像 Next.js 里面各种运行时的能力,比如约定式路由、构建优化、SSR 等等。

但实际上它给自己的定位非常清晰,即 content-focused 应用开发框架,换句话说,就是重内容、轻交互场景下的上层研发框架,比如大多数电商网站、文档站、博客站、证券网站等等。

你可以将 Astro 理解为一个垂直场景下的Next.js,但它可以在它适用的领域里面可以胜过其它所有竞品(如Next.jsRemixVuepress 等),这是它能够做起来的重要原因。接下来,我们就来看看 Astro 的优势在于哪些地方。

核心优势

Astro 的主要优势包括如下几点:

  • Islands 架构,解决传统 SSR/SSG 框架的全量 hydration 问题,做到尽可能少的 Client 端 JS 的开销,甚至是 0 JS。
  • 学习成本低。.astro 语法和传统的 .jsx.vue 非常相似,对于新手前端来说也比较容易掌握。
  • 使用灵活。对于页面的开发,你既可以使用官方的.astro 语法,也同样可以使用 .md.vue.jsx 语法,也就是说,你可以自由选择其它前端框架的语法来开发,甚至可以在一个项目中同时写 Vue 组件和 React 组件!
  • 构建迅速。底层构建体系基于 Vite 以及 Esbuild 实现,项目启动速度非常快。

Islands 架构

在如上的几个优点中,我们来重点说一说 Astro 的 Islands 架构,因为这是它高性能最主要的原因。

Islands 架构模型早在 2019 年就被提出来了,并在 2011 年被 Preact 作者Json MillerIslnads Architecture 一文中得到推广。这个模型主要用于 SSR (也包括 SSG) 应用,我们知道,在传统的 SSR 应用中,服务端会给浏览器响应完整的 HTML 内容,并在 HTML 中注入一段完整的 JS 脚本用于完成事件的绑定,也就是完成 hydration (注水) 的过程。当注水的过程完成之后,页面也才能真正地能够进行交互。

那么当应用的体积逐渐增大时,需要在客户端执行的 JS 脚本也会越来越多,这也意味着 TTI(可交互时间) 指标越来越高:

为了解决这个问题,Islands 架构将页面拆分为各自独立的组件,包含静态组件可交互组件,如下图的例子所示:

可以清楚的看到,一个页面中只有部分的组件交互,那么对于这些可交互的组件,我们可以并行地执行 hydration 过程,因为组件之间是互相独立的。

而对于静态组件,即不可交互的组件,我们可以让其不参与 hydration 过程,直接复用服务端下发的 HTML 内容。

可交互的组件就犹如整个页面中的孤岛(Island),因此这种模式叫做 Islands 架构:

相比于传统 SSR 中的全量 hydration,Islands 模式可以实现局部(partial) hydration,从而优化 JS 的体积,减少网络传输的成本和 JS 运行时的开销。

在 Astro 中,默认所有的组件都是静态组件,比如:

// index.astro
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<MyReactComponent />
复制代码

值得注意的是,这种写法不会在浏览器添加任何的 JS 代码。但有时我们需要在组件中绑定一些交互事件,那么这时就需要激活孤岛组件了,在 Astro 如何来激活呢?其实很简单,在使用组件时加上client:load指令即可:

// index.astro
---
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<MyReactComponent client:load />
复制代码

如此一来,Astro 会给浏览器传输一部分 JS 代码供这个组件完成 hydration,以便后续的交互。

对比 Next.js 和 Remix

读到这里,你可能会说了,相比于其它的业界方案,Astro 到底优势在哪里呢?我们不妨来盘点一下。

首先是大名鼎鼎的 Next.js,我们知道 Next.js 是一个非常经典的 React SSR 框架,也是使用传统的 SSR/SSG 技术,可以适用于几乎所有的 Web 开发场景。而 Astro 在其适用的content-focused场景下,性能会明显高于 Next.js,以下是两个真实的迁移案例:

可以看到,Astro 相比 Next.js 可以大幅度减少 JS 代码的体积(90% 以上),同时页面的运行时性能也提升了 30% 以上。除此之外,Astro 不仅支持使用 React 框架,而且支持 Vue、Solid 等在内的各种前端框架,灵活性更高。

其次是最近比较火的新秀框架 Remix,它基于 react-router 管理组件,通过 loader 和 action 的概念尽可能将逻辑代码放到服务端的 bundle,从而减少客户端 JS 的代码体积,同样是崇尚 0 JS 的理念,Remix 却仍然需要全量 hydration,无法完成 partial hydration。此外,Astro 还有两大优势:

  • 除了 React,也支持其它的众多前端框架;
  • 同时支持 SSR 和 SSG,而 Remix 不支持 SSG。

对比 React 18 的 Selection Hydration 特性

React 18 提供了 renderToPipeableStream API,真正实现了 SSR 场景下的 Selection Hydration,主要有如下的几个特点:

  • 在完整的 HTML 渲染之前就可以进行组件的 hydrate,而不用等待 HTML 的内容发送完毕
  • hydration 可中断。比如页面中有两个组件: Sidebar 和 Comment,当这个部分的 HTML 发送至浏览器时,React 打算开始对 Sidebar 组件进行 hydrate:

如果用户在这个过程中点击了 Comment 组件,那么 React 会中断当前对于 SideBar 组件的 hydrate,从而去执行 Comment 组件的 hydrate:

详情可见 React 18 SSR Architecture: github.com/reactwg/rea…

那么 Astro 中的 Islands 架构,即 Partial Hydration,和 React 的 Selection Hydration 到底是不是一个东西呢?

答案是否定的。两者存在着非常大的区别:

  • 从渲染框架上来看, Selection Hydration 依附于具体框架的实现,而 Partial Hydration 可以做到框架无关,即使是 Vue、Solid 的项目也可以做到 Partial Hydration
  • 从客户端执行的 JS 总量来看, Partial Hydration 可以做到加载部分组件的 JS 代码,而 Selection Hydration 仍然需要加载和执行全量的 JS 代码。
  • 从服务端和客户端的交互来看, Selection Hydration 严重依赖于流式(Streaming)渲染,服务端需要加上 transfer-encoding: chunked 的响应头,而 Partial Hydration 没有这个限制。

因此,虽然两者都是在 Hydration 上做文章,但其实是两种完全不同的方案,而且 Partial Hydration 更加通用,限制更少,执行的 JS 更少。

小结

以上就是对 Astro 的介绍和分析,后面有机会给大家剖析一下内部的源码实现。文中如有不妥的地方,欢迎大家评论和指正。最后给大家推荐一些 Astro 的学习资料,方便大家读完文章进一步了解:

猜你喜欢

转载自juejin.im/post/7131928500373553160