前不久,自诞生以来就备受关注的 Astro 发布了 1.0 版本。博主早就开始关注这个项目了,如今是时候好好谈谈了。
首先,Astro 是一个气质独特的前端框架网页生成器。它的主要卖点有:
- 零运行时
- 支持 React、Svelte、Vue、Solid、Preact、Lit 等流行的 UI 框架的集成
- SSG 以及 SSR
- …
博主第一次看见这些特性时,直接被吓了一跳;且不说零运行时和支持 React 怎么同时存在于一张 Feature 列表的?就单单让 React 和 Vue 相互兼容就非常的不可思议!这到底是什么黑魔法?!
阅读完 Astro Docs 后,Emmm… 它确实是 “零运行时”,也确实可以 “让 React 和 Vue 相互兼容”,不过代价是不加载 JavaScript!相当于将 React 和 Vue 在编译阶段就渲染成 HTML 和 CSS (默认行为),想要拥有状态?也不是不行,不过这样就必须有运行时了 (按需加载)。
这不就是另一个 Next.js 吗?不仅不是,还差的有点远;在 SSG 方面,Astro 比 Next.js 更激进更极端 (默认不加载任何 JavaScript);并且在某些方面,Astro 需要的代码更少,速度反而更快 (零运行时)。但对于动态能力要求比较高的网站,或者 SSR 领域,Astro 目前就完全只能被 Next.js 碾压了。
Astro 究竟是什么?
Astro 独特的个性使其很难被简单的分类为前端框架(类似于 Next.js) 或是网页生成器 (Jekyll、Hugo 之类的)。你说他是前端框架吧?它的运行方式更像是一个网页生成器;你说它是网页生成器吧?用起来的感觉到和 Remix 有几分相似。
思考了一下,我终于悟了。这不就是一个 “更好用的 HTML” 吗?!
首先,虽然使用了类 JSX 的语法来表达结构,但此 JSX 非彼 JSX,React 但 JSX 本质上是 JavaScript 函数,而 Astro 中的 JSX 更像是模版,是为了渲染 HTML 和 CSS 而存在的;在不使用 React 等框架的情况下,使用 <script>
加载 JavaScript;使用 <style>
加载 CSS,像什么 CSS in JS,也不是完全不可能,只是肯定非常的水土不服。就连开发思路也是传统 Web 开发的那一套。
零运行时,组件化… 这不就是 HTML 最想成为的那个样子吗?
扯了这么多,终于要正式进入 Astro 的世界了!
值得一提的是,Astro 的官方文档是支持中文的;我这篇文章只是带大家 “Take a look”,想要系统学习,还是更推荐看官方文档。
安装 Astro
安装 Astro 最简单的方式是通过官方脚手架 create-astro
来安装:
|
|
一个 Astro 的新项目是默认不包括 React、Svelte、Vue、Solid、Preact、Lit 这些额外的 UI 框架的,需要单独安装,但好在有脚手架可以帮助我们配置好一切 (官方称之为安装 Astro 集成):
|
|
此时你的项目结构可能看起来像这样:
|
|
其中:
src/*
- 项目的源代码 (组件、页面、CSS 等)。src/pages/*
- 页面文件 (必须要有),Astro 将根据它的目录结构构建路由public/*
- 非代码、不需要处理的资源 (字体、图标等)package.json
- 项目元数据列表。astro.config.mjs
- Astro 的配置文件 (可选)
Astro 组件
Astro 组件是 Astro 项目的基础构建块。它们是纯 HTML、无需客户端运行时的模板组件。
Astro 组件由两部分组成:
- 编译时运行 (SSG) 或运行在 Server 上 (SSR) 的 JavaScript 代码
- 组件模板 (类 JSX 语法)
|
|
组件 Script
Astro 的组件 Script 需要放在代码栅栏 (—) 里。是不是很像 Markdown 的 frontmatter?Astro 的组件 Script 的灵感就来源于此。
在 组件 Script 中,你可以:
- 导入其他 Astro 组件
- 导入其他框架 (如 React) 编写的组件
- 导入数据,如 JSON 文件
- 从 API 或数据库中获取内容 (使用
fetch
) - 创建你要在模板中引用的变量
|
|
组件 Script 只会在编译时,或服务器上运行。如果你在组件 Script 中使用 console.log()
,它也只将信息打印在运行 Astro 的终端 (Node.js) 上,而不会出现在浏览器的控制台里。
代码围栏的设计是为了保证你在其中编写的 JavaScript 被“围起来”。它不会逃到你的前端应用程序中,或落入你的用户手中。你可以安全地在这里写一些昂贵或敏感的代码(比如调用你的私人数据库),而不用担心它会出现在你的用户的浏览器中。
组件模板
在组件脚本下面的是组件模板。组件模板决定了你的组件的 HTML 输出。
Astro 组件模版跟 JSX 非常像,但 Astro 组件模版拥有一些特殊的 Astro 指令。
|
|
组件参数
Astro 组件可以通过 Astro.props
定义和接受参数。
例如下面这个 GreetingHeadline
(GreetingHeadline.astro
) 组件:
|
|
在不使用别的 UI 框架组件 (React、Svelte、Vue、Preact、SolidJS、AlpineJS、Lit) 的情况下,你可以在 Astro 组件模板中使用 <script>
标签编写运行在客户端 (浏览器) 中的 JavaScript 代码。
默认情况下,<script>
标签由 Astro 处理:
- 任何导入都将被打包,并且允许你导入本地文件或 Node.js 模块
- 处理后的脚本将通过
type="module"
注入你页面的<head>
- 全面支持 TypeScript 包括导入 TypeScript 文件
- 如果你的组件在页面上多次使用,则脚本标签将只包含一次
|
|
如果想避免打包脚本,你可以使用 is:inline
属性:
|
|
使用 React 组件
你可以在 Astro 文件中导入并使用 React 组件 (Vue、Svelte… 等 UI 框架也是一样的道理)。就像使用普通的 Astro 组件一样。
|
|
默认情况下, Astro 会将 React 组件将渲染为静态 HTML。
激活组件
框架组件可以使用 client:*
指令实现激活。它还可以定义 React 组件应该如何被渲染和激活。
|
|
框架组件所必须的渲染 JS(如 React、Svelte)都会随着页面一同下载。client:* 指令只决定了何时导入组件 JS,以及何时激活框架。
Astro 页面
src/pages/*
下的所有 Astro 文件 (*.astro
) 或 Markdown (*.md
) 文件都会被渲染成页面。并且 Astro 会根据你的目录结构生成路由。
Astro 文件
Astro 文件生成的 Astro 页面没什么好说的,更 Astro 组件是一回事。
Markdown 文件
对于 Markdown 文件,Astro 要求一个特殊的 frontmatter:layout
;你需要通过这个属性指定包裹内容的 Layout 组件:
|
|
路由
Astro 的路由基于文件,它根据项目的 src/pages
目录中的文件结构来在编译阶段为你生成 HTML 页面。
大体来讲,Astro 路由分为静态路由和动态路由。不过动态路由的本质仍然是静态路由。
静态路由
src/pages
目录中的 Astro 文件 (*.astro
) 和 Markdown 文件 (*.md
) 将自动成为网站页面。每个页面的路由都和其在 src/pages
目录中的路径和文件名相对应。
|
|
动态路由
动态路由就是通过一个 Astro 文件在编译阶段有条件的生成多个 HTML 页面。
这个 Astro 文件:
- 使用
[bracket]
标记来识别动态参数 (文件名必须是形如src/pages/[bracket].astro
的形式) - 导出
getStaticPaths()
函数来明确要由 Astro 进行预渲染的路径
简单来讲,Astro 会先运行这个 Astro 文件的 Astro 脚本区导出的 getStaticPaths()
,并根据这个函数返回的结果决定生成的 HTML 页面的数量和路径。然后在每个页面中用 Astro.params
接收由 getStaticPaths()
返回的参数 (params
)。
|
|
缺点
就目前 ([email protected]) 而言,Astro 还有一个挺致命的缺点的:Astro 目前还不支持任何一种测试框架 (无论 Vitest,Jest 还是 Cypress,都不支持)!这就注定 Astro 目前还只是个玩具;虽然已经发布正式版 (1.0 版) 了,但离真正的“正经项目”还是差最后一公里。
不过我也很高兴的看到 Astro 已经开始着手解决这一问题了!
结语
以上便是对 Astro 的基本介绍;一个令人眼前一亮又十分传统保守的前端框架网页生成器。
说什么取代 XXX 几乎是不可能的。但也不能说 Astro 就一无是处,未来 Astro 必定会凭借其独特的个性在某些细分领域闯出点名堂 (用来写博客就挺不错的)。