Astro

Astroは、さまざまなツールや連携機能を柔軟に利用できるメタフレームワークであり、多くのエコシステムを活用できます。

また、お気に入りのUIフレームワーク(またはフレームワークなし)を使用してコンポーネントを作成したり、ビルド時にページを静的HTMLとしてレンダリングしたり、サーバーサイドレンダリング(SSR)を使用してサーバー上で動的にレンダリングしたりできます。

これにより、あらゆる静的ホスティング環境またはサーバーにデプロイできる、高速でSEOフレンドリーな出力が得られます。

統合の詳細とソースコードについては、GitHubのQwikDev Astro連携を参照してください。

Qwik Cityの代わりにAstro

AstroとQwikを連携させる場合、Qwik City APIはAstroと互換性がないことに注意することが重要です。

Astroは、これらの懸念に対処するための独自のAPIと機能セットを提供するメタフレームワークです。これらには、次のものが含まれます。

  • ルーティング
  • ページ
  • レイアウト
  • データフェッチ
  • サーバーサイドレンダリング(SSR)

したがって、QwikとAstroを連携させる場合は、Qwik CityのAPIの代わりにAstroのAPIと機能を使用する必要があります。これにより、QwikコンポーネントがAstro環境内で正しく動作することが保証されます。詳細については、Astroドキュメントを参照してください。

@qwikdev/astro 💜

この連携機能は、Qwikコンポーネントを使用して、Astro内で再開可能性の力を活用します。

インストール

連携機能を追加するには2つの方法があります。最も簡単なものから始めましょう!

Astro CLI

Astroには、組み込みの連携機能を取り込むためのコマンドラインツールastro addが付属しています。このコマンドは、次のことを行います。

  1. 必要に応じて、必要な依存関係とピア依存関係をすべてインストールします
  2. 必要に応じて、連携機能を適用するために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構成の設定

この連携機能では、TypeScriptがQwikのJSX型を認識するために、tsconfig.jsonに次のものが必要です。

"compilerOptions": {
  "jsx": "react-jsx",
  "jsxImportSource": "@builder.io/qwik"
}

問題が発生した場合は、Githubに投稿し、以下の手動インストールを試してください。

手動インストール

まず、次のように@qwikdev/astro連携機能をインストールします

npm install @qwikdev/astro

通常、パッケージマネージャーはピア依存関係をインストールします。ただし、Astroの起動時にCannot find package '@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:onlyclient: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の主要な機能の一つは、デフォルトでゼロJSであることです。残念ながら、JavaScriptフレームワークや、それに続くコンポーネントを追加すると、通常はそうではなくなります。

React、Vue、Svelteなどのフレームワークでインタラクティビティを導入したい場合、フレームワークのランタイムが導入されます。ページに追加されるコンポーネントの数も、JavaScriptの量に応じて線形的にO(n)で増加します。

Astro + Qwik

Qwikは、AstroのデフォルトでゼロJSの原則をさらに発展させたものです。リジューム可能性のおかげで、コンポーネントは再開されるまで実行されません。インタラクティビティがあっても、フレームワークは必要な時まで実行されません。これはO(1)の定数であり、開発者の労力はゼロです。

代わりに、ページのロード時に、Qwikloaderと呼ばれる1KBに圧縮された小さなJavaScriptコードが、必要に応じてアプリケーションの残りをダウンロードします。

きめ細かい遅延ロード

ハイドレーションは、コードを積極的に実行せざるを得なくします。これは、モーダルのようにツリーの外にあるコンポーネントでは問題ありませんが、レンダリングツリー内の各コンポーネントを念のため徹底的にチェックする必要があります。

Qwikは、リジューム可能性と、きめ細かい方法でコードを遅延ロードする能力により、Astroで非常にうまく機能します。特に、多くのコンポーネントを持つマーケティングサイト、ブログ、コンテンツ指向のサイトに適しています。

瞬時のインタラクティビティ

@qwikdev/astro v0.4以降、Astroでの推測的なモジュールフェッチのサポートを追加しました。

これにより、Qwikコンポーネントで瞬時のインタラクティビティが可能になります。推測的なモジュールフェッチは、サービスワーカーのバックグラウンドでアプリケーションバンドルをプリフェッチするため、必要になったときにコードがすでにブラウザのキャッシュに存在します。

あなたはQwik insightsをすぐに使えるはずです!

コンテナ vs. アイランド

Astroは一般的に他のフレームワークでアイランドアーキテクチャを採用していますが、QwikはQwikコンテナと呼ばれる異なる戦略を使用しています。アプローチの違いはありますが、どちらも同様の制限を共有しています。

DOMには、<astro-island>カスタム要素がないことに気づくかもしれません。これは、AstroにとってQwikが静的データのように見えるためです。

これは、Qwikでは、ハンドラー自体がアプリケーションのルート/エントリポイントであるためです。

コンテナ間の通信

よくある制限の1つは、別のアイランドまたはコンテナに状態を渡そうとすることです。

状態の共有は、現代のWeb開発において非常に重要です。問題は、異なるコンテナまたはアイランド間で状態を共有する必要がある場合に、これをどのように実現できるかということです。

グローバルシグナルまたはナノストアを使用しないのはなぜですか?

Astroを使用する他のフレームワークは、ナノストアグローバルシグナルを使用することでこれに対処しています。

すべてのテストが合格し、アプリケーションが期待どおりに動作しているのを確認できるかもしれませんが、ナノストアやグローバルシグナルの使用はお勧めしません。これらは、SSRコンテキストで予期しない動作を引き起こす可能性があります。

例えば、Solidのチュートリアルでは、次の点が言及されています。

グローバルな状態と計算を使用することは可能ですが、Contextの方が適している場合があります。さらに、グローバルな状態は、Solid StartのようなSSR(サーバーサイドレンダリング)ソリューションで使用すべきではないことに注意することが重要です。サーバー上では、グローバルな状態はリクエスト間で共有され、データ分離の欠如がバグ、メモリリーク、およびセキュリティ上の問題につながる可能性があります(そしてそうなるでしょう)。アプリケーションの状態は常にグローバルに依存するのではなく、コンテキストを通じて提供することをお勧めします。

カスタムイベント

Qwikでは、グローバルなシグナル状態を含めないことが設計上の決定でした。

代わりに、カスタムイベントの使用をお勧めします。これにはいくつかの利点があります。

  • パフォーマンス(不要な状態の同期を回避)
  • ページロード時にフレームワークを起動しない
  • マイクロフロントエンド(MFE)のサポート
  • ページ上に異なるバージョンが存在できる
  • イベント駆動型
  • 疎結合

この例は、カスタムイベントをアプリケーション全体でどのように使用できるかを示しています。counter.tsxrandom-island.tsx、およびindex.astroページに注意してください。

複数のJSXフレームワークの使用

AstroでQwik、React、Preact、またはSolidのような複数のJSXフレームワークを使用するには、各フレームワークがどのファイルを処理するかを設定する必要があります。

例えば、すべてのQwikコンポーネントをqwikという名前のフォルダーに配置できます。次に、このフォルダー内のファイルをQwikインテグレーションを使用して処理するようにAstroを設定します。

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:ハイドレーションディレクティブプレフィックスを使用していることに注意してください。これは、標準で提供されているAstroのハイドレーションディレクティブとの競合を避けるためです。

client:*プレフィックスも使用できますが、tsxファイルでのみ使用できます。ディレクティブのリストは、Qwikドキュメントのインタラクティビティの追加セクションで確認できます。

Qwik Reactコンポーネントは依然としてハイドレーションを使用するため、Qwik-Reactを再開可能なコンポーネントへの移行戦略として使用することをお勧めします。

jsxImportSource

残念ながら、TypeScriptにはデフォルトでjsxImportSourceを1つしか設定できません。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内の名前付きスロットの場合、マークアップにq:slotを追加する代わりに、代わりに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の対応物で期待どおりに動作します。

コミュニティガイド

動画

  • LWJ showで、JasonとSteveがQwik Astroインテグレーションについて議論するのをご覧ください。

  • AwesomeのQwik + Astroビデオでは、Astroがいかにさらに高速になったかを解説しています。

貢献

あなたの貢献を歓迎します!まず、貢献ガイドをお読みください。これには、インテグレーションがどのように動作するかの詳細なセクションを含め、参加するために必要なすべての情報が含まれています。

また、builder.io discordには、APIの変更、インテグレーションの可能性のあるアイデア、その他のクールなものを議論するためのqwik-astroチャンネルがあります。😊

クレジット

AstroコアチームのMatthewとNateに感謝します!彼らの助けなしにこの統合は実現しませんでした。

Nateのハンドル

貢献者

このドキュメントを改善するのに協力してくれたすべての貢献者に感謝します!

  • thejackshelton
  • hamatoyogi