Astro
Astro 是一個靈活的元框架,可以容納各種工具和整合,讓您能夠利用眾多生態系統。
它也允許您使用您喜歡的 UI 框架(或完全不使用框架)來編寫元件,並在建構時將您的頁面渲染為靜態 HTML,或使用伺服器端渲染(SSR)在伺服器上動態渲染。
這會產生快速、對 SEO 友好的輸出,可以部署到任何靜態託管環境或伺服器。
如需有關整合的詳細資訊以及檢視原始碼,請前往 GitHub 上的 QwikDev Astro 整合。
使用 Astro 取代 Qwik City
在將 Astro 與 Qwik 整合時,請注意 Qwik City API 與 Astro 不相容。
Astro 是一個元框架,它提供了自己的一組 API 和功能來處理這些問題。 這些包括
- 路由
- 頁面
- 佈局
- 資料提取
- 伺服器端渲染 (SSR)
因此,在將 Qwik 與 Astro 整合時,您應該使用 Astro 的 API 和功能,而不是 Qwik City 的 API。 這將確保您的 Qwik 元件在 Astro 環境中正常運作。 如需更多資訊,請參閱 Astro 文件。
@qwikdev/astro 💜
此整合利用了 Astro 內部 可恢復性 的強大功能,並使用 Qwik 元件。
安裝
新增整合的方法有兩種。讓我們從最簡單的一個開始!
Astro CLI
Astro 附帶了一個用於整合內建整合的命令列工具:astro add
。 此命令將
- 選擇性地安裝所有必要的相依性和對等相依性
- 選擇性地修改您的
astro.config.*
檔案以應用整合
要安裝 @qwikdev/astro
,請從您的專案目錄執行以下命令並按照提示操作
# Using NPM
npx astro add @qwikdev/astro
# Using Yarn
yarn astro add @qwikdev/astro
# Using PNPM
pnpm astro add @qwikdev/astro
設定 TypeScript 配置
整合需要在 tsconfig.json
中加入以下內容,以便 TypeScript 能夠辨識 Qwik 的 JSX 類型。
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@builder.io/qwik"
}
如果您遇到任何問題,請 在 Github 上發布 並嘗試以下手動安裝。
手動安裝
首先,像這樣安裝 @qwikdev/astro
整合
npm install @qwikdev/astro
通常,套件管理器會安裝對等相依性。但是,如果您在啟動 Astro 時收到 找不到套件 '@builder.io/qwik'
警告,請安裝 Qwik。
npm install @builder.io/qwik
現在,使用 integrations
屬性將整合新增到您的 astro.config.*
檔案中
// astro.config.mjs
import { defineConfig } from 'astro/config';
+ import qwikdev from '@qwikdev/astro';
export default defineConfig({
// ...
integrations: [qwikdev()],
// ^^^^^
});
如果您也在使用其他整合,例如
react()
或preact()
,您需要將qwikdev()
放在清單中的它們前面。 否則您將會遇到Not a QRL
錯誤。 就像這樣:integrations: [qwikdev(), react(), preact()]
。
Qwik 不會進行水合,它在根本上有所不同
Astro 以其部分水合方法而聞名,而 Qwik 不需要水合。
新增 Qwik 元件
在其他 UI 框架中,互動性需要水合指令,例如 client:only
或 client:load
。 Qwik 不需要這些,因為它沒有水合!
在像 Astro 或 Qwik City 這樣的元框架中使用 Qwik 時,元件會載入到伺服器上,在單獨的執行緒中進行預取,並在客戶端上「恢復」。
例如,以下是如何在 Qwik 中建立計數器元件(例如,在 src/components/counter.tsx
中)。
import { component$, useSignal } from "@builder.io/qwik";
export const Counter = component$(() => {
const counter = useSignal(0);
return <button onClick$={() => counter.value++}>{counter.value}</button>;
});
它可以在我們的 index.astro
頁面中使用,如下所示
---
import { Counter } from "../components/counter";
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>Astro</title>
</head>
<body>
<h1>Astro.js - Qwik</h1>
/* no hydration directive! */
<Counter />
</body>
</html>
啟動快速,保持快速
Astro 的主要功能之一是預設為零 JavaScript。遺憾的是,在添加 JavaScript 框架和任何後續組件後,通常情況並非如此。
如果我們想使用 React、Vue、Svelte 等框架引入互動性,則會引入框架運行時。添加到頁面的組件數量也會隨著 JavaScript 的數量線性增加 O(n)。
Astro + Qwik
Qwik 建立在 Astro 的預設為零 JavaScript原則之上,甚至更上一層樓。由於可恢復性,除非恢復,否則不會執行組件。即使具有互動性,框架也不會執行,直到需要執行為止。它是 O(1) 常數,並且開發人員無需付出任何努力。
相反,在頁面加載時,一個稱為 Qwikloader 的小型 1kb 壓縮 JavaScript 會根據需要下載應用程序的其餘部分。
細粒度的延遲加載
激活迫使您 急切地執行程式碼。對於樹外部的組件(例如模態)來說,這不是問題,但它必須窮舉地檢查渲染樹中的每個組件,以防萬一。
由於可恢復性及其以細粒度方式延遲加載程式碼的能力,Qwik 在 Astro 中表現出色。特別適用於營銷網站、部落格和具有許多組件的內容導向網站。
即時互動性
從 @qwikdev/astro
v0.4 開始,我們在 Astro 中添加了對 預測性模組提取 的支持。
這為您的 Qwik 組件啟用了即時互動性。預測性模組提取將在服務工作程序的後台預取應用程序捆綁包,以便在需要時,程式碼已經存在於瀏覽器緩存中。
您應該能夠立即使用 Qwik Insights!
容器與孤島
雖然 Astro 通常採用帶有其他框架的孤島架構,但 Qwik 使用一種稱為 Qwik 容器 的不同策略。儘管方法不同,但兩者都有類似的局限性。
在 DOM 中,您可能會注意到沒有任何 <astro-island>
自定義元素,這是因為對於 Astro 來說,Qwik 看起來像是靜態數據。
這是因為在 Qwik 中,處理程序本身就是應用程序的根目錄/入口點。
跨容器通信
一個常見的限制是嘗試將狀態傳遞到另一個孤島或容器。
在現代 Web 開發中,共享狀態至關重要。問題是,當狀態需要在不同的容器或孤島之間共享時,我們如何實現這一點?
為什麼不使用全局信號或納米存儲?
Astro 的其他框架通過使用 納米存儲 或 全局信號 來解決此問題。
雖然您可能會看到所有測試都通過了,並且應用程序按預期工作,但我們不建議使用納米存儲或全局信號。它們可能會在 SSR 上下文中導致一些意外行為。
例如,在 Solid 的教程中提到了以下內容
雖然可以使用全局狀態和計算,但上下文有時是更好的解決方案。此外,請務必注意,不應在 SSR(服務器端渲染)解決方案(例如 Solid Start)中使用全局狀態。在服務器上,全局狀態在請求之間共享,並且缺乏數據隔離會(並且將)導致錯誤、內存洩漏並具有安全隱患。建議應用程序狀態應始終通過上下文提供,而不是依賴全局。
自訂事件
在 Qwik 中,不包含全域信號狀態是一個設計決策。
我們建議使用自訂事件,它具有以下幾項優點:
- 效能(避免不必要的狀態同步)
- 在頁面載入時不會喚醒框架
- 微前端 (MFE) 支援
- 頁面上可以存在不同的版本
- 事件驅動
- 解耦
此範例 顯示如何在整個應用程式中使用自訂事件。請注意 counter.tsx
、random-island.tsx
和我們的 index.astro
頁面。
使用多個 JSX 框架
若要在 Astro 中使用多個 JSX 框架(如 Qwik、React、Preact 或 Solid),您需要設定規則,以決定每個框架應該處理哪些檔案。
例如,您可以將所有 Qwik 元件放在名為 qwik
的資料夾中。然後,將 Astro 設定為使用 Qwik 整合來處理此資料夾中的任何檔案。
import { defineConfig } from "astro/config";
import qwik from "@qwikdev/astro";
import react from "@astrojs/react";
export default defineConfig({
integrations: [
qwik({ include: "**/qwik/*" }),
react({ include: "**/react/*" }),
solid({ include: "**/solid/*" }),
],
});
以上我們在同一個 Astro 專案中使用了 Qwik、React 和 Solid 整合。
如果我們查看第一個整合,它會在 qwik
資料夾中尋找任何檔案,並對此資料夾中的任何檔案使用 Qwik。
為了簡單起見,請考慮將常見的框架元件分組在同一個資料夾中(例如 /components/react/
和 /components/qwik/
)。不過,這只是選用的。
Qwik React
如果您使用的是 React,我們建議您使用 @builder.io/qwik-react
整合。它是 @astrojs/react
的替代方案,並且可以讓您無縫地轉換到 Qwik。
import { defineConfig } from "astro/config";
import qwikdev from "@qwikdev/astro";
import { qwikReact } from "@builder.io/qwik-react/vite";
// https://astro.build/config
export default defineConfig({
integrations: [qwikdev()],
vite: {
plugins: [qwikReact()],
},
});
使用 Qwik-React,我們可以將 React 元件「Qwik 化」,並在我們的 Qwik 應用程式中使用它們,甚至可以在 Astro 檔案之外巢狀 Qwik 和 React 元件!
您不需要使用 qwikReact 指定 include 屬性。
這裡有一個範例,說明如何使用 qwik-react
整合來建立 React 元件。
/** @jsxImportSource react */
import { qwikify$ } from "@builder.io/qwik-react";
import { useState } from "react";
const ReactCounter = () => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>React {count}</button>;
};
// "Qwikified" React component
export const QReactCounter = qwikify$(ReactCounter);
建立計數器後,可以在我們的 index.astro 檔案中使用它。
<QReactCounter qwik:visible />
請注意,在 .astro
檔案中,我們使用 qwik:
hydration 指令前置字元,這是為了防止與 Astro 預設提供的 hydration 指令衝突。
您也可以使用 client:*
前置字元,但只能在 tsx 檔案中使用。您可以在 Qwik 文件的 新增互動性 章節中找到指令清單。
Qwik React 元件仍然具有 hydration 功能,因此建議將 Qwik-React 作為轉移到可恢復元件的策略。
jsxImportSource
遺憾的是,TypeScript 只能有一個 jsxImportSource
預設值。如果您在 Astro 應用程式中同時使用 React、Solid 或 Preact 的 Astro 整合,請覆寫每個元件的匯入來源。
如果您使用的是 @astrojs/react,則可以使用 qwik-react 來代替。系統將會預設支援正確的設定。
/** @jsxImportSource react */
import { useState } from "react";
export const ReactCounter = () => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
};
例如,Solid JS 是
/** @jsxImportSource solid-js */
例如,Preact 是
/** @jsxImportSource preact */
具名插槽
對於 Astro 中的具名插槽,請在標記中新增 slot
,而不是新增 q:slot
。
my-slot-comp.tsx
import { Slot, component$, useSignal } from "@builder.io/qwik";
export const MySlotComp = component$<{ initial: number }>((props) => {
return (
<>
<Slot name="test" />
</>
);
});
index.astro
<MySlotComp>
<div slot="test">Content inside the slot named test!</div>
</MySlotComp>
預設插槽在其 Qwik City 對應項目中按預期運作。
社群指南
-
Paul Scanlon 展示了 在 Astro 中使用 Qwik 優於 React 和 Vanilla JS 的實際操作。
-
Rishi Raj Jain 撰寫了一篇關於使用 Astro 的 Vercel SSR Adapter 來設定 Qwik 的精彩指南。
-
Paul Scanlon 探討在 Astro 中使用 Qwik 作為 React 的替代方案。
影片
-
在 LWJ 節目 上觀看 Jason 和 Steve [討論 Qwik Astro 整合]。
-
Awesome 的 Qwik + Astro 影片 介紹了 Astro 如何變得更快。
貢獻
我們非常歡迎您的貢獻!首先請閱讀我們的 貢獻指南。它包含您參與所需的所有資訊,包括關於整合如何在幕後運作的深入說明。
在 builder.io discord 中還有一個 qwik-astro
頻道,用於討論 API 變更、整合的可能想法,以及其他很酷的東西。😊
致謝
特別感謝 Astro 核心團隊的 Matthew 和 Nate!沒有他們的幫助,這個整合將無法實現。
Nate 的聯絡方式