Astro 4.10

作者
Matthew Phillips

Astro 4.10 已发布,带来了实验性的类型安全环境变量,以及对容器 API 和重写(Rewrites)的增强。

完整版本亮点包括

要升级现有项目,请使用自动化的 @astrojs/upgrade CLI 工具。或者,通过运行包管理器的升级命令来手动升级

# Recommended:
npx @astrojs/upgrade
# Manual:
npm install astro@latest
pnpm upgrade astro --latest
yarn upgrade astro --latest

实验性:astro:env

Astro 4.10 引入了一个新的实验性内置模块 `astro:env`,以便更方便地使用环境变量。

环境变量允许您在不同环境中为应用程序配置不同的值。但这带来了很大的复杂性

  • 有些变量在客户端需要,有些则只在服务器端需要。
  • 服务器变量通常是**机密信息**,例如 API 密钥,您不希望它们在客户端暴露,也不希望它们被内联到服务器构建中(任何有权访问构建输出的人都可以查看)。
  • 有些变量对于您的应用程序正常运行是**必需的**;而另一些则是可选的增强功能。
  • 变量可以在您的 shell 中、`.env` 文件中或在构建配置中定义。
  • 诸如CloudflareDeno 等运行时读取变量的 API 不同,这造成了您需要处理的开发/生产环境差异。

我们构建了 `astro:env` 以提供对环境变量更多的控制和结构。通过模式(schema)直接在您的配置中管理这种复杂性

import { defineConfig, envField } from 'astro/config';
export default defineConfig({
experimental: {
env: {
schema: {
API_PORT: envField.number({
context: 'server',
access: 'secret',
default: 7000
}),
PUBLIC_DASHBOARD_V2: envField.boolean({
context: 'server',
access: 'public',
default: false
}),
}
}
}
})

定义后,您可以通过从 `astro:env/server` 和 `astro:env/client` 模块导入来使用您的变量

import { PUBLIC_DASHBOARD_V2, getSecret } from 'astro:env/server';
if (PUBLIC_DASHBOARD_V2) {
const API_PORT = getSecret("API_PORT") // number
await fetch(`https://my-secret-api.com:${API_PORT}/v2`)
}

客户端的 `astro:env/client` 可以在组件、脚本或任何您运行客户端代码的地方使用。例如,仅在启用功能标志时显示增强功能

import { SOME_FEATURE_FLAG } from 'astro:env/client';
export default function() {
return (
<section>
{ SOME_FEATURE_FLAG && (
<div id="fancy-enhanced-feature"></div>
)}
...
</section>
)
}

当您需要读取模式中未定义的变量时,请使用 `getSecret()`,它适用于任何运行时(Cloudflare、Node.js、Deno)。

import { getSecret } from 'astro:env/server';
function getServerEndpoint(num: number) {
return getSecret(`BACKUP_SERVER_${num}`); // string | undefined
}

`astro:env` 是一个实验性功能,与所有实验性功能一样,可能会有所更改。感谢 Florian Lefebvre 成为 RFC 的倡导者并提供实现!请在 RFC 上留下您的反馈,以帮助指导这项新功能的开发,直至其稳定。

所有 HTTP 方法的重写

重写是 4.9 中发布的一项新的实验性功能。第一个版本针对 `GET` 请求,这是重写最常见的情况。现在在 4.10 中,可以通过克隆初始请求来使用重写来更改任何请求的路由。

这是一个在中间件中进行重写的示例,用于将您定向到版本化 API 的默认版本

import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(({ request, url }, next) => {
if(request.method === 'POST' && url.pathname === '/api') {
return next('/api/v2');
}
});

进行重写时,会创建一个指向新 URL 的新请求。现有请求头和请求体将被复制到新请求中。

嵌入 Astro

在 4.9 中,我们引入了容器 API,这是一种在 Astro 框架上下文之外渲染 Astro 组件的新方式。我们最初的重点是**测试**方面:使用容器 API 来测试 Astro 组件。创建一个容器,使用 `container.renderToString()` 渲染组件,并检查生成的 HTML。

我们一直知道人们会希望以其他方式使用容器 API,我们也不想让他们失望。在 4.10 中,您现在可以使用此 API 渲染任何使用 `astro build` 构建的组件,这意味着您可以在 Astro 站点之外使用它们!

为了演示其工作原理,我们构建了一个 Astro-in-PHP 演示应用程序。PHP 专家们,请勿评价代码!😅

容器部分看起来像这样

import * as components from './dist/server/all.mjs';
import { renderers } from './dist/server/renderers.mjs';
import { manifest } from './dist/server/entry.mjs';
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
const container = await AstroContainer.create({
manifest,
renderers,
resolve(s) {
const found = manifest.entryModules[s];
if(found) {
return `/astro-project/dist/client/${found}`;
}
return found;
}
});
const html = await container.renderToString(components.ReactWrapper);
// Log to the console so that PHP injects the HTML into its page.
console.log(html);

容器 API 是一个低级 API,它反映了 Astro 内部渲染其自身路由的方式。我们渴望社区能够构建集成,以弥补其不足之处,并提供更简单的方式来嵌入 Astro。亲自尝试一下,并向我们展示您在何处添加了 Astro!

容器 API 辅助函数

我们还添加了一些方便的辅助函数,用于在 Vite 环境(`vitest`、Astro 集成等)中渲染您的 UI 框架组件时使用容器 API。

这意味着您不再需要知道(或弄清楚!)每个包的客户端和服务器渲染脚本的单独直接文件路径。新的 `getContainerRenderer()` 从我们的官方渲染器集成包(`@astrojs/react`、`@astrojs/preact`、`@astrojs/solid-js`、`@astrojs/svelte`、`@astrojs/vue`、`@astrojs/lit` 和 `@astrojs/mdx`)提供适当的渲染脚本。请务必同时升级您的集成以获得此新功能!

新的 `astro:container` 虚拟模块中的 `loadRenderers()` 函数将为您从每个包中加载这些渲染器

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import ReactWrapper from '../src/components/ReactWrapper.astro';
import { loadRenderers } from "astro:container";
import { getContainerRenderer } from "@astrojs/react";
test('ReactWrapper with react renderer', async () => {
const renderers = await loadRenderers([getContainerRenderer()])
const renderers = [
{
name: '@astrojs/react',
clientEntrypoint: '@astrojs/react/client.js',
serverEntrypoint: '@astrojs/react/server.js',
},
];
const container = await AstroContainer.create({
renderers,
});
const result = await container.renderToString(ReactWrapper);
expect(result).toContain('Counter');
expect(result).toContain('Count: <!-- -->5');
});

对 `renderers` 的这种类型更改还将允许无 Vite 环境手动加载和传递渲染器模块。

有关更多信息,请参阅容器 API 文档

错误修复

一如既往,Astro 4.10 包含了更多本文中未能提及的错误修复和小改进!查看完整的发布说明以了解更多信息,并观看 Astro Together 的 4.10 完整发布揭示!特别感谢 Sarah、Erika、Bjorn、Ema、Chris、Florian 以及所有为此次发布做出贡献的人员。

播放