我非常看好的网络框架之一就是Astro。我主张并现在使用它,因为大约一年,坦率地说,它可以完成工作。最近,我有机会建立了一个会议网站(请参阅Micro Frontends Conference),该网站最终应在Azure托管。对于这样一个信息驱动的静态页面,astro不仅是理想的。作为Azure的托管服务,我选择了Azure静态Web应用程序(SWA)。
在本文中,我想向您介绍Astro是什么,以及为什么它是这样一个项目的理想选择。我将向您介绍Azure SWA作为托管候选人,以及您去那里时可能要考虑的事情。话...
什么是Astro?
Astro是一个专注于内容的现代网络框架。它最初是静态站点生成器(即,为您预先渲染所有内容,这是将页面上传到一些廉价静态存储的理想之选),但已经发展到了这一点。现在,您可以选择几种托管模型。对于我创建的静态站点模式的页面就足够了。
Astro还试图使开发人员非常友好。正如其他Web Frameworks普及的那样,Astro也是基于组件的,这使其可重复使用性和合成性非常好。 Astro组件分为两个部分:组件脚本和组件模板。前者负责模板中可以使用的所有事物,而后者是实际表示形式,即将要渲染的内容。
一个快速示例,显示Astro组件的外观:
---
import SpeakerPreview from "./SpeakerPreview.astro";
export interface Props {
title: "string;"
speakers: Array<{
id: string;
name: string;
avatar: string;
}>;
}
const { title, speakers } = Astro.props;
---
<a href="/schedule" class="backlink">
Back to schedule
</a>
<div class="talk-details">
<h3 class="socials-header">{title}</h3>
</div>
<div class="talk-details">
<h3 class="socials-header">Speakers</h3>
{
speakers.map((speaker) => (
<a href={`/speakers/${speaker.id}`}>
<SpeakerPreview speakers={[speaker]} />
</a>
))
}
</div>
在上一个示例中,我们教模板有关要使用的另一个组件(SpeakerPreview
)。这是由其导入定义的。这样,我们只能导入任何*.astro
文件以获取对Astro组件的引用。
通过惯例,我们可以使用Typescript来定义Astro组件的道具。我们需要的只是在组件脚本中导出Props
接口。在这里,Astro支持打字条开箱即用,而无需进行任何更改。但是,按照JSX的规则,模板部分非常接近HTML。因此,我们可以使用Curly Bracs {}
进行表达开关。同样,只需使用pascalcase而不是蛇形案例,就可以参考导入的组件。
作为Astro的主要目标是HTML(而不是DOM),是内置元素(例如a
或div
)的道具是他们的属性(“ class”),而不是其属性(“ className”)。您可以使用their docs在Astro上找到更多信息。
是什么使Astro吸引人?
Astro试图通过优化和剥离不必要的部分来使最快的页面成为可能。对于我们的会议网站,这看起来如下:
要实现这一行为做几件事:
- 由于组件模板本质上是JSX,因此HTML将以缩合形式得出(即使用此技术,不必要的whitespace的剥离是微不足道的)。 。
- Astro使用特殊的
style
和script
块。style
在SSR的CSS-IN-JS上有些接近,即,将其组合到单个style
Block per < / em> page-page-删除未使用的类 /代码。script
元素也正在捆绑。 - 可以通过使用例如
Image
元素(以下更多)来优化图像和其他资源。
有些人可能还想提到,Astro使用所谓的岛屿建筑将来自其他框架的组件(例如,反应)进行交互式。我认为,尽管这可能是使用的好功能,但这不应该是您的主要问题。例如,我将本文用作示例的网站使用React组件为其管理页面,但实际上只是静态内容,它试图避免尽可能多地使用JavaScript。
让我们看看如何使用optin @astrojs/image
软件包与sharp
(另一个软件包,可以由@astrojs/image/sharp
使用)来优化图像:
import { defineConfig } from "astro/config";
import image from "@astrojs/image";
export default defineConfig({
integrations: [
image({
serviceEntryPoint: "@astrojs/image/sharp",
}),
],
});
使用此信息,我们现在可以避免编写<img src="...">
,而是写下:
---
import { Image } from "@astrojs/image/components";
---
<Image
alt="Some text"
src="../path-to-image/file.png"
loading="lazy"
format="webp"
width={220}
height={260}
/>
很棒的是,优化不仅将图像转换为所需的格式(例如WebP),而且还将考虑给定的维度(上面的情况为220x260)。因此,我们真的不需要手动优化,剪切或缩放图像。我们让Astro做这项繁琐的工作。
什么是Azure静态Web应用程序?
向Azure发布一组静态文件非常容易且非常有效。我们需要的只是一个存储帐户,其中包含BLOB存储。然后,我们可以在刀片中启用具有相同名称的刀片中的“静态网站”功能:
如果我们想进一步优化交付,我们还可以获得CDN服务并将其链接到Azure Blob存储。问题解决了。现在,我们已经获得了静态资产的第一批交付。但是,...
呢- 安全性(身份验证和授权)
- 动态后端功能(例如,访问某些数据库)
- 多个环境(例如,作为开发或预览环境)
使其更容易,Microsoft向名为Azure static Web应用程序的Azure引入了专用服务。从本质上讲,它将边缘第一资产交付与预定义的可自定义路由规则和Azure功能相结合。按照惯例,使用/api
段的路径将通过相应的Azure函数来处理,而其他路径将导致上载的静态资产。该路由规则还允许对某些错误进行自定义(不仅找不到“ 404”错误,而且还找不到任何其他错误,例如内部服务器“ 500”错误)。以/.auth
开头的特殊路径将非常轻松地连接身份验证。
整个配置可以在staticwebapp.config.json
中进行,看起来像这样:
{
"routes": [
{
"route": "/.auth/login/twitter",
"statusCode": 404
},
{
"route": "/.auth/login/github",
"statusCode": 404
},
{
"route": "/admin",
"allowedRoles": ["administrator"]
}
],
"auth": {
"rolesSource": "/api/get-roles",
"identityProviders": {
// ...
}
},
"platform": {
"apiRuntime": "node:16"
},
"responseOverrides": {
"401": {
"redirect": "/.auth/login/aad?post_login_redirect_uri=.referrer",
"statusCode": 302
},
"404": {
"rewrite": "/404",
"statusCode": 404
}
}
}
在此处,我们定义了一些路由(尤其是 *de *通过Twitter和github激活登录),并引入一些响应替代。在后者中,我们告诉SWA,应将401(未经授权)错误重定向到登录页面,而404错误应通过自定义页面显示。此外,我们将Azure函数的平台设置为节点V16。
是什么使Azure SWA吸引人?
这种托管的提供商在市场上有很多可用的产品。诸如Fly.io,Vercel,Heroku等之类的东西提供了相同的(以及更多)。但是,对于这些产品,您通常会支付更高的价格。当然,这是有道理的,因为他们的产品超出了我们在这里所看到的,但这正是重点:为什么要少付更多。
如果
,所有的azure swa都非常适合- 您已经有Azure订阅
- 可以使用一些API调用来增强的大多数静态(即非服务器端渲染)页面很好
- 想要开箱即用的许多东西(即以更无用的方式) - 例如身份验证
如果您有服务器端渲染页面或需要自定义的大部分身份验证流程。
就个人而言,我喜欢Aure SWA,因为它快速且易于部署,并且使用了一个非常有效的模型,可以深入集成到Azure中。例如,要查看Azure功能的日志输出,您将连接应用程序Insights Workbook。在此工作簿中,您将获得完整的日志内省和可视化。不需要完整的麋鹿堆栈或类似的东西 - 一切已经存在。当然,如果这不是您想要的,那么整个过程是一个问题。记录部分上的自定义很麻烦。
开发和部署
使用简单的静态存储与某些后端动力学形式的SSG组合可以非常吸引人,但需要一些额外的接线才能获得方便的开发体验。
进行开发和部署的主要驱动力是@azure/static-web-apps-cli
。这有助于我们使事情变得更轻松。它的CLI工具(swa
)实际上只是一个编排者 - 使用Azure Functions Core Tools或Astro的CLI等事物。
使用swa start
对我有用的配置是以下 swa-cli.config.json :
{
"$schema": "https://aka.ms/azure/static-web-apps-cli/schema",
"configurations": {
"app": {
"appLocation": "src",
"apiLocation": "api",
"outputLocation": "dist",
"appBuildCommand": "npm run build",
"apiBuildCommand": "npm run build --if-present",
"run": "npm run dev",
"appDevserverUrl": "http://localhost:3000"
}
}
}
虽然apiLocation
指的是具有自己的 package.json 的目录,但其余的人会教SWA CLI有关如何使用Astro的信息。例如,npm run build
本质上只是astro build
和npm run dev
是astro dev
。当启动时(通常这将从4280
之类的港口开始),4280
代理在3000
港口提供的资产。同样,API(位于Azure函数核心工具CLI定义的某个端口上)也被代理(使用/api
段)。
总结一下 - 几乎在这里处理。部署还利用了SWA CLI:
swa deploy ./dist --env production --api-location api --deployment-token $SWA_TOKEN
在这里,我们明确地告诉SWA CLI,应将./dist
文件夹用于静态Web App Assets,而./api
目录应用于使用的Azure函数。在CI/CD运行期间,部署令牌将作为环境变量注入。
Azure功能的打字稿
就个人而言,我几乎只使用Typescript开发。但是,Azure功能需要使用JavaScript(或其他内容,例如C#)。幸运的是,Typescript总是可以被转移,但是然后我们需要提出二级结构。例如,我要做的是以下内容:
api/function-name/function.json
api/function-name/index.ts
api/function-name/...
function.json
包含对scriptFile
的重新引用(即,通常它会隐式地转到“ index.js”,但是由于我们使用Typescript,我们需要将其更改为移植的伪像):
{
"bindings": [
// ...
],
"scriptFile": "../dist/function-name.js"
}
在常见的dist
文件夹中收集功能的文件是有道理的,但是只有没有冲突。确保无冲突处理和快速启动性能的一种好方法是避免使用tsc
进行转介。相反,我们可以使用像esbuild
这样的捆绑器来优化资产。
以下片段显示了build.js
文件的示例,该文件可用于触发构建:
const { build } = require("esbuild");
const { readdirSync, statSync } = require("fs");
const { resolve } = require("path");
const entryFileNames = ["index.tsx", "index.ts", "index.js"];
const watch = process.argv.includes("--watch");
const entryPoints = {};
for (const dir of readdirSync(__dirname)) {
const p = resolve(__dirname, dir);
if (statSync(p).isDirectory()) {
const names = readdirSync(p);
if (names.includes("function.json")) {
const [name] = names.filter((m) => entryFileNames.includes(m));
if (name) {
const fn = resolve(p, name);
entryPoints[dir] = fn;
}
}
}
}
build({
watch,
entryPoints,
bundle: true,
outdir: resolve(__dirname, "dist"),
format: "cjs",
platform: "node",
});
在这里,我们浏览当前目录中包含的所有目录。如果我们找到匹配(例如, function-name/index.ts ),我们将其添加为入口点。每个入口点都使用index.ts
或index.tsx
(或类似)文件作为参考,其中源目录的名称被用作输出文件的名称。此外,我们可以使用--watch
选项以观察模式调用此。
结论
Azure静态Web应用程序是一个出色的平台,可以按一些后端需求推出静态网页。 Azure功能的开发模型既容易又灵活,这为我们提供了有效工作的适量界限。
将Astro用作静态资产的SSG具有多种优势,可以与Azure SWA结合使用。可以将更多的互动式(例如会议页面中的管理区域)作为交互性岛包括,而整体内容完全由Astro驱动,从而预先渲染。