# Islands Architecture
Islands Architectureとは、2019年にKatie Sylor-Miller氏によって提唱されたアーキテクチャです。 Islands Architectureの目的は、JavaScriptを削除してパフォーマンスを最適化することです。ページ内の静的なコンテンツと動的なコンテンツを独立させてレンダリングし、余分なハイドレーションを無くすことで、JavaScriptをなるべく排除してパフォーマンスを向上させます。
SSRでは、初回アクセス時にサーバでHTMLを生成し、クライアント側でページ全体のハイドレーションを実行します。ハイドレーションとは、コンポーネントを再生成しDOMにイベントをバインディングする作業のことを言います。
クライアント側でハイドレーションすることでアプリケーションが機能するようになります。ハイドレーションをするためにはJavaScriptをダウンロードし、実行する必要があります。そのため、JavaScriptのダウンロードに時間がかかったり、実行が遅れるとアプリケーションが機能するまでの時間(TTI
)が遅くなる可能性があります。
Islands Architectureは、このハイドレーションのプロセスを極力無くすことを目的としています。 Islands Architectureでは、静的なコンテンツはHTMLとCSSだけで構成しJavaScriptを含みません。そのため、ハイドレーションのプロセスがなくなります。JavaScriptが必要な動的なコンテンツは遅延してレンダリングし、部分的にハイドレーションを実行します。コンテンツごとに独立して配信することで、無駄なJavaScriptを減らしパフォーマンスを最適化することができます。
このような仕組みはいくつかのフレームワークで実装されています。
Marko (opens new window)やEleventy (opens new window)などはIslands Architectureが提唱される以前からあり、部分的なハイドレーションやStreaming Renderingで同じようなパフォーマンスの最適化が行われています。
Astro (opens new window)はIslands Architectureの思想をベースにデザインされ、部分的なハイドレーションをサポートしパフォーマンスに特化して実装されています。
この章では、Astroを例にIslands Architectureの仕組みを見ていきましょう。
# MPAとSPA
AstroのIslands ArchitectureはMulti Page Application(MPA)で構成されます。
MPAは毎回サーバ側でレンダリングするアプリケーションです。MPAはページを移動するたびにサーバへのアクセスが必要になるため、毎回ブラウザーのリロードが伴います。
一方、Single Page Application(SPA)ではクライアント側でレンダリングを実行します。ページ遷移の際にサーバへアクセスする必要がないため、リロードをすることなくスムーズにページ移動が可能です。
近年、フロントエンド開発で言及されるCSRやSSRはSPAをベースにしています。SSRもMPA同様にサーバ側でレンダリングするアーキテクチャですが、あくまで初回レンダリングに限ります。初回アクセス以降は、クライアントでレンダリングしてSPAとして振る舞います。
MPAはSPAが登場する以前から広く使われており、PHPやRubyなどの言語を使って実装されていました。
AstroではJavaScript(or TypeScript)で実装することができ、従来よりもパフォーマンスに特化したアプリケーション開発が可能になります。
MPA | SPA | |
---|---|---|
レンダリング | サーバ | クライアント or (初回だけサーバ) |
アーキテクチャ | Islands Architecture | CSR、SSR、SSG、ISR |
フレームワーク | Astro | Next.js, Nuxt |
# MPAとSPAのレンダリング
SPAはクライアントでレンダリングを実行してコンテンツを生成します。 全てのコンテンツをクライアント側で生成するため、リッチなアプリケーション開発を得意としています。しかし、その分JavaScriptが肥大化し、初回アクセス時のパフォーマンスが低下する可能性があります。また、コンテンツを生成するまでに時間がかかるとSEOの評価にも影響します。
SSRを導入すれば、初回レンダリングのパフォーマンスを改善できるでしょう。また、コードを分割して(Code Splitting
)、JavaScriptの削減も可能です。しかし、依然としてハイドレーションをするためのJavaScriptが必要になります。
AstroのMPAでは、毎回サーバ側でコンテンツを生成します。静的なコンテンツだけの場合、HTMLとCSSだけでJavaScriptを含みません。SSRと比べるとハイドレーションのプロセスがなくなるため、その分パフォーマンスが大幅に向上します。動的なコンテンツが含まれている場合、レンダリングを遅延して部分的にハイドレーションを実行します。その際、必要な分のJavaScriptしかダウンロードしないため、SSRでページ全体のハイドレーションをするよりもファイル量を削減できます。
MPA | SPA | |
---|---|---|
レンダリング | サーバ | クライアント or (初回だけサーバ) |
JavaScript (ハイドレーション) | なし or 部分的 | ページ全体 |
# MPAとSPAのルーティング
SPAでは、ページ移動する際もクライアント側でコンテンツを生成するのでスムーズに遷移ができます。サーバにアクセスする必要がなく、ブラウザーのHistory API (opens new window)を使うことでURLの変更をします。
MPAでは、ページ移動のたびにサーバへアクセスします。そのため、SPAと比べるとページ遷移が遅れます。MPAは初回アクセスのパフォーマンスに優れていますが、それ以降はSPAの方が素早く動作するでしょう。しかし、MPAでもTurbo (opens new window)などの技術を使えばSPAのようなルーティングが可能となります。
MPA | SPA | |
---|---|---|
ページ遷移 | サーバ (Turboなどのライブラリを使用すれば クライアントも可能) | クライアント |
# Turboとは
Turbo (opens new window)とは、Hotwireが提供している技術でMPAでもSPAのような操作性を実現するためのライブラリです。
Turboは、フォームやリンクのリクエストをインターセプトしFetch APIを利用して非同期リクエストをサーバへ送ります。サーバはレンダリングを実行してHTMLをレスポンスとして送信します。クライアント側は、返されたHTMLの要素を抜き出して現在のページの要素と置き換えます。Fetch APIを使用して非同期に行うことで、ブラウザーをリロードすることなくページ遷移が可能となります。
SPAの場合もFetch APIを利用してデータを取得します。しかし、サーバからはJSONデータを受け取り、レンダリングはクライアントで実行します。
Ruby on RailsではTurbolinks (opens new window)を使用して部分的なHTMLの置換を実装していました。Ruby on Rails7からはHotwireがデフォルトになり、Turboも含まれるようになりました。
Astroでも@astro/torubolinks (opens new window)をインストールすることで、Turboを使うことができます。
Note
@astrojs/turbolinks
はdeprecatedになっているため、swup (opens new window)などのライブラリで代替可能です。
Turbolinks is no longer under active development. The @astrojs/turbolinks integration has been deprecated.
# Islands Architectureの仕組み
Astroを例にしてIslands Architectureの仕組みを見てみましょう。
AstroはSSGのようなStatic RenderingとSSRのようなDynamic Renderingの両方に対応しています。
今回は下記のようなブログサイトを想定して、Static Renderingを実装してみましょう。
# 静的コンテンツの実装
Astroのビルドが実行されて、クライアントへ配信されるまでのステップは次のようになります。
ビルド時に実行
- アプリケーションをビルドする (
astro build
) - ビルド時にHTMLファイルが生成される
サーバ側で実行
- ブラウザがサーバへリクエストをする
- サーバはリクエストを受け取り、生成されたコンテンツ(HTML)をブラウザ(クライアント)に返す
クライアント側で実行(動的なコンテンツがあれば)
- ブラウザ側でHTMLファイルを解析し、動的なコンテンツがあればJavaScriptファイルをダウンロードする
- JavaScriptファイルを実行し、部分的にハイドレーションを適用する
- ハイドレーション後、動的コンテンツが機能する状態になる
ビルドからサーバでコンテンツを返すプロセスまではSSGと同じになります。異なるのはクライアント側です。クライアントではハイドレーションする対象があれば部分的に実行します。もし静的コンテンツだけの場合、JavaScriptは含まれません。
pages/index.astro
というファイルを作り、以下のようなコードを記述してみましょう。
---
import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import Content from '../components/Content';
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
---
<!DOCTYPE html>
<html lang="en">
<head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head>
<body>
<Header title={SITE_TITLE} />
<main>
<h1>Astroのサイトです</h1>
<Content />
</main>
<Footer />
</body>
</html>
Content
コンポーネントはReactで実装しています。
export default function Content() {
return (
<>
<p>
なぜ他のWebフレームワークではなくAstroを選ぶのか? ここでは、Astroを構築した理由、Astroが解決すべき問題、そしてAstroがあなたのプロジェクトやチームに最適な理由を説明するのに役立つ5つのコアデザイン原則を紹介します。
</p>
<p>
Astroは、コンテンツが豊富なウェブサイトを構築するために設計されています。これには、ほとんどのマーケティングサイト、出版サイト、ドキュメントサイト、ブログ、ポートフォリオ、そして一部のeコマースサイトが含まれます。
</p>
<p>
これとは対照的に、最新のWebフレームワークのほとんどは、Webアプリケーションを構築するために設計されています。これらのフレームワークは、ブラウザ上でより複雑な、アプリケーションのような体験を構築するのに最適なものです。ログインした管理画面のダッシュボード、受信トレイ、ソーシャルネットワーク、Todoリスト、さらにはFigmaやPingのようなネイティブライクなアプリケーションなどです。
</p>
<p>
これは、Astroを理解する上で最も重要な違いの1つです。Astroはコンテンツにフォーカスしているため、アプリケーションにフォーカスしたWebフレームワークでは実装する意味がないようなトレードオフを行い、比類ないパフォーマンス機能を提供することができます。
</p>
<p>
Astroは、クライアントサイドレンダリングよりもサーバーサイドレンダリングを可能な限り活用します。これは、従来のサーバーサイドフレームワーク(PHP、WordPress、Laravel、Ruby on Railsなど)と同じアプローチです。-- 何十年も前から使われている手法です。しかし、それを解除するために2つ目のサーバーサイド言語を学ぶ必要はないのです。Astroでは、すべてがHTML、CSS、JavaScript(お好みでTypeScriptでも可)だけであることに変わりはありません。
</p>
</>
)
}
そして、yarn build
を実行すると、dist/index.html
ファイルが生成されます。
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="/_astro/about.18532c1a.css" />
<link rel="stylesheet" href="/_astro/HeaderLink.astro_astro_type_style_index_0_lang.c3840210.css" />
</head>
<body>
<header class="astro-3EF6KSR2">
<h2 class="astro-3EF6KSR2">
ブログ
</h2>
<nav class="astro-3EF6KSR2">
<a href="/" class="astro-3EF6KSR2 active astro-EIMMU3LG">
Home
</a>
<a href="/blog" class="astro-3EF6KSR2 astro-EIMMU3LG">
Blog
</a>
<a href="/about" class="astro-3EF6KSR2 astro-EIMMU3LG">
About
</a>
<a href="https://twitter.com/astrodotbuild" class="astro-3EF6KSR2 astro-EIMMU3LG" target="_blank">
Twitter
</a>
<a href="https://github.com/withastro/astro" class="astro-3EF6KSR2 astro-EIMMU3LG" target="_blank">
GitHub
</a>
</nav>
</header>
<main>
<h1>Astroのサイトです</h1>
<p>なぜ他のWebフレームワークではなくAstroを選ぶのか? ここでは、Astroを構築した理由、Astroが解決すべき問題、そしてAstroがあなたのプロジェクトやチームに最適な理由を説明するのに役立つ5つのコアデザイン原則を紹介します。</p>
<p>Astroは、コンテンツが豊富なウェブサイトを構築するために設計されています。これには、ほとんどのマーケティングサイト、出版サイト、ドキュメントサイト、ブログ、ポートフォリオ、そして一部のeコマースサイトが含まれます。</p>
<p>これとは対照的に、最新のWebフレームワークのほとんどは、Webアプリケーションを構築するために設計されています。これらのフレームワークは、ブラウザ上でより複雑な、アプリケーションのような体験を構築するのに最適なものです。ログインした管理画面のダッシュボード、受信トレイ、ソーシャルネットワーク、Todoリスト、さらにはFigmaやPingのようなネイティブライクなアプリケーションなどです。</p>
<p>これは、Astroを理解する上で最も重要な違いの1つです。Astroはコンテンツにフォーカスしているため、アプリケーションにフォーカスしたWebフレームワークでは実装する意味がないようなトレードオフを行い、比類ないパフォーマンス機能を提供することができます。</p>
<p>Astroは、クライアントサイドレンダリングよりもサーバーサイドレンダリングを可能な限り活用します。これは、従来のサーバーサイドフレームワーク(PHP、WordPress、Laravel、Ruby on Railsなど)と同じアプローチです。-- 何十年も前から使われている手法です。しかし、それを解除するために2つ目のサーバーサイド言語を学ぶ必要はないのです。Astroでは、すべてがHTML、CSS、JavaScript(お好みでTypeScriptでも可)だけであることに変わりはありません。</p>
</main>
<footer class="astro-SZ7XMLTE">
© 2023 YOUR NAME HERE. All rights reserved.
</footer>
</body>
</html>
ハイドレーションのためのJavaScriptファイルがないことに注意してください。SSGの章で紹介したように、Next.jsのSSGでは、動的コンテンツがなくてもハイドレーションのためのscript
タグが含まれていました。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
<link rel="preload" href="/_next/static/css/876d048b5dab7c28.css" as="style" />
<link rel="stylesheet" href="/_next/static/css/876d048b5dab7c28.css" data-n-g="" />
<noscript data-n-css=""></noscript>
<script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script>
<script src="/_next/static/chunks/webpack-8fa1640cc84ba8fe.js" defer=""></script>
<script src="/_next/static/chunks/framework-2c79e2a64abdb08b.js" defer=""></script>
<script src="/_next/static/chunks/main-74c4d6b2b5c362f3.js" defer=""></script>
<script src="/_next/static/chunks/pages/_app-cff197596e2d3fb7.js" defer=""></script>
<script src="/_next/static/chunks/pages/about-c9c253072c621717.js" defer=""></script>
<script src="/_next/static/LZ95_3iccW5qecKk2uZPx/_buildManifest.js" defer=""></script>
<script src="/_next/static/LZ95_3iccW5qecKk2uZPx/_ssgManifest.js" defer=""></script>
</head>
<body>
<div id="__next">
<div><h1>Frontend Design会社について</h1></div>
</div>
<script id="__NEXT_DATA__" type="application/json">
{ "props": { "pageProps": {} }, "page": "/about", "query": {}, "buildId": "LZ95_3iccW5qecKk2uZPx", "nextExport": true, "autoExport": true, "isFallback": false, "scriptLoader": [] }
</script>
</body>
</html>
Astroでは静的コンテンツだけの場合、ハイドレーションが必要ないのでビルドされたファイルにJavaScriptが含まれません。
そして、yarn preview
でサーバを起動すると上記の静的コンテンツが配信されます。
# 動的コンテンツの実装
では、次に以下のようなカルーセルを追加してみましょう。
カルーセルは動的コンテンツのためJavaScriptが必要になります。Astroで動的コンテンツを追加する場合、明示的にclient:load
を追記します。
---
import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import Content from '../components/Content';
import Slider from '../components/Slider';
import { slideData } from '../slideData';
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
---
<!DOCTYPE html>
<html lang="en">
<head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head>
<body>
<Header title={SITE_TITLE} />
<main>
<h1>Astroのサイトです</h1>
<Slider slides={slideData} client:load />
<Content />
</main>
<Footer />
</body>
</html>
client:load
の場合、ページがロードされたタイミングでハイドレーションを実行します。clientディレクティブはハイドレーションの優先度を指定でき、load以外にも以下のようなオプションがあります。
- client:idle (opens new window)
- client:visible (opens new window)
- client:media (opens new window)
- client:only (opens new window)
yarn build
を実行してみましょう。dist/index.html
が生成されます。
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="/_astro/about.18532c1a.css" />
<link rel="stylesheet" href="/_astro/HeaderLink.astro_astro_type_style_index_0_lang.c3840210.css" />
<link rel="stylesheet" href="/_astro/index.27b7077f.css" /></head>
<body>
<header class="astro-3EF6KSR2">
<h2 class="astro-3EF6KSR2">
ブログ
</h2>
<nav class="astro-3EF6KSR2">
<a href="/" class="astro-3EF6KSR2 active astro-EIMMU3LG">
Home
</a>
<a href="/blog" class="astro-3EF6KSR2 astro-EIMMU3LG">
Blog
</a>
<a href="/about" class="astro-3EF6KSR2 astro-EIMMU3LG">
About
</a>
<a href="https://twitter.com/astrodotbuild" class="astro-3EF6KSR2 astro-EIMMU3LG" target="_blank">
Twitter
</a>
<a href="https://github.com/withastro/astro" class="astro-3EF6KSR2 astro-EIMMU3LG" target="_blank">
GitHub
</a>
</nav>
</header>
<main>
<h1>Astroのサイトです</h1>
<style>astro-island,astro-slot{display:contents}</style><script>(self.Astro=self.Astro||{}).load=a=>{(async()=>await(await a())())()},window.dispatchEvent(new Event("astro:load"));var l;{const c={0:t=>t,1:t=>JSON.parse(t,o),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(JSON.parse(t,o)),5:t=>new Set(JSON.parse(t,o)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(JSON.parse(t)),9:t=>new Uint16Array(JSON.parse(t)),10:t=>new Uint32Array(JSON.parse(t))},o=(t,s)=>{if(t===""||!Array.isArray(s))return s;const[e,n]=s;return e in c?c[e](n):void 0};customElements.get("astro-island")||customElements.define("astro-island",(l=class extends HTMLElement{constructor(){super(...arguments);this.hydrate=()=>{if(!this.hydrator||this.parentElement&&this.parentElement.closest("astro-island[ssr]"))return;const s=this.querySelectorAll("astro-slot"),e={},n=this.querySelectorAll("template[data-astro-template]");for(const r of n){const i=r.closest(this.tagName);!i||!i.isSameNode(this)||(e[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(const r of s){const i=r.closest(this.tagName);!i||!i.isSameNode(this)||(e[r.getAttribute("name")||"default"]=r.innerHTML)}const a=this.hasAttribute("props")?JSON.parse(this.getAttribute("props"),o):{};this.hydrator(this)(this.Component,a,e,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),window.removeEventListener("astro:hydrate",this.hydrate),window.dispatchEvent(new CustomEvent("astro:hydrate"))}}connectedCallback(){!this.hasAttribute("await-children")||this.firstChild?this.childrenConnectedCallback():new MutationObserver((s,e)=>{e.disconnect(),this.childrenConnectedCallback()}).observe(this,{childList:!0})}async childrenConnectedCallback(){window.addEventListener("astro:hydrate",this.hydrate);let s=this.getAttribute("before-hydration-url");s&&await import(s),this.start()}start(){const s=JSON.parse(this.getAttribute("opts")),e=this.getAttribute("client");if(Astro[e]===void 0){window.addEventListener(`astro:${e}`,()=>this.start(),{once:!0});return}Astro[e](async()=>{const n=this.getAttribute("renderer-url"),[a,{default:r}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),i=this.getAttribute("component-export")||"default";if(!i.includes("."))this.Component=a[i];else{this.Component=a;for(const d of i.split("."))this.Component=this.Component[d]}return this.hydrator=r,this.hydrate},s,this)}attributeChangedCallback(){this.hydrator&&this.hydrate()}},l.observedAttributes=["props"],l))}</script><astro-island uid="ZpkIIm" component-url="/_astro/Slider.697520ed.js" component-export="default" renderer-url="/_astro/client.f6ebef58.js" props="{"slides":[1,"[[0,{\"image\":[0,\"https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80\"]}],[0,{\"image\":[0,\"https://images.unsplash.com/photo-1676869503942-79e94f62862d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80\"]}],[0,{\"image\":[0,\"https://images.unsplash.com/photo-1676765374032-57d90e318b8f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80\"]}],[0,{\"image\":[0,\"https://images.unsplash.com/photo-1677116719762-fd4f4c4b7e35?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80\"]}],[0,{\"image\":[0,\"https://images.unsplash.com/photo-1676920410907-8d5f8dd4b5ba?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80\"]}]]"]}" ssr="" client="load" opts="{"name":"Slider","value":true}" await-children=""><div class="carousel-root" tabindex="0"><div class="carousel carousel-slider" style="width:100%"><ul class="control-dots"><li class="dot selected" value="0" role="button" tabindex="0" aria-label="slide item 1"></li><li class="dot" value="1" role="button" tabindex="0" aria-label="slide item 2"></li><li class="dot" value="2" role="button" tabindex="0" aria-label="slide item 3"></li><li class="dot" value="3" role="button" tabindex="0" aria-label="slide item 4"></li><li class="dot" value="4" role="button" tabindex="0" aria-label="slide item 5"></li></ul><button type="button" aria-label="previous slide / item" class="control-arrow control-prev"></button><div class="slider-wrapper axis-horizontal"><ul class="slider animated" style="-webkit-transform:translate3d(-100%,0,0);-moz-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);-o-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);-webkit-transition-duration:350ms;-moz-transition-duration:350ms;-ms-transition-duration:350ms;-o-transition-duration:350ms;transition-duration:350ms;-ms-transition-duration:350ms"><li class="slide"><img src="https://images.unsplash.com/photo-1676920410907-8d5f8dd4b5ba?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="slide selected"><img src="https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="slide"><img src="https://images.unsplash.com/photo-1676869503942-79e94f62862d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="slide"><img src="https://images.unsplash.com/photo-1676765374032-57d90e318b8f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="slide"><img src="https://images.unsplash.com/photo-1677116719762-fd4f4c4b7e35?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="slide"><img src="https://images.unsplash.com/photo-1676920410907-8d5f8dd4b5ba?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="slide selected"><img src="https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li></ul></div><button type="button" aria-label="next slide / item" class="control-arrow control-next"></button><p class="carousel-status">1 of 5</p></div><div class="carousel"><div class="thumbs-wrapper axis-vertical"><button type="button" class="control-arrow control-prev control-disabled" aria-label="previous slide / item"></button><ul class="thumbs animated" style="-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-webkit-transition-duration:350ms;-moz-transition-duration:350ms;-ms-transition-duration:350ms;-o-transition-duration:350ms;transition-duration:350ms;-ms-transition-duration:350ms"><li class="thumb selected" aria-label="slide item 1" style="width:80px" role="button" tabindex="0"><img src="https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="thumb" aria-label="slide item 2" style="width:80px" role="button" tabindex="0"><img src="https://images.unsplash.com/photo-1676869503942-79e94f62862d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="thumb" aria-label="slide item 3" style="width:80px" role="button" tabindex="0"><img src="https://images.unsplash.com/photo-1676765374032-57d90e318b8f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="thumb" aria-label="slide item 4" style="width:80px" role="button" tabindex="0"><img src="https://images.unsplash.com/photo-1677116719762-fd4f4c4b7e35?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li><li class="thumb" aria-label="slide item 5" style="width:80px" role="button" tabindex="0"><img src="https://images.unsplash.com/photo-1676920410907-8d5f8dd4b5ba?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1800&q=80" height="auto" width="800px" style="aspect-ratio:4/3"/></li></ul><button type="button" class="control-arrow control-next control-disabled" aria-label="next slide / item"></button></div></div></div></astro-island>
<p>なぜ他のWebフレームワークではなくAstroを選ぶのか? ここでは、Astroを構築した理由、Astroが解決すべき問題、そしてAstroがあなたのプロジェクトやチームに最適な理由を説明するのに役立つ5つのコアデザイン原則を紹介します。</p><p>Astroは、コンテンツが豊富なウェブサイトを構築するために設計されています。これには、ほとんどのマーケティングサイト、出版サイト、ドキュメントサイト、ブログ、ポートフォリオ、そして一部のeコマースサイトが含まれます。</p><p>これとは対照的に、最新のWebフレームワークのほとんどは、Webアプリケーションを構築するために設計されています。これらのフレームワークは、ブラウザ上でより複雑な、アプリケーションのような体験を構築するのに最適なものです。ログインした管理画面のダッシュボード、受信トレイ、ソーシャルネットワーク、Todoリスト、さらにはFigmaやPingのようなネイティブライクなアプリケーションなどです。</p><p>これは、Astroを理解する上で最も重要な違いの1つです。Astroはコンテンツにフォーカスしているため、アプリケーションにフォーカスしたWebフレームワークでは実装する意味がないようなトレードオフを行い、比類ないパフォーマンス機能を提供することができます。</p><p>Astroは、クライアントサイドレンダリングよりもサーバーサイドレンダリングを可能な限り活用します。これは、従来のサーバーサイドフレームワーク(PHP、WordPress、Laravel、Ruby on Railsなど)と同じアプローチです。-- 何十年も前から使われている手法です。しかし、それを解除するために2つ目のサーバーサイド言語を学ぶ必要はないのです。Astroでは、すべてがHTML、CSS、JavaScript(お好みでTypeScriptでも可)だけであることに変わりはありません。</p>
</main>
<footer class="astro-SZ7XMLTE">
© 2023 YOUR NAME HERE. All rights reserved.
</footer>
</body></html>
カルーセル部分にscript
タグが埋め込まれているのに注目してください。カルーセルを動かすのに必要なJavaScriptが記述されています。この部分はページがロードされると即座に実行され、ハイドレーションが適用されます。
yarn preview
を実行して、動作を見てみましょう。
カルーセルが動くのを確認できました。また、Networkタブ見るとJavaScriptファイルがダウンロードされているのが分かります。
AstroのIslands Architectureでは、このように静的コンテンツと動的コンテンツを独立させることでパフォーマンスを最適化しています。
# メリット
# パフォーマンスに特化
AstroのIslands ArchitectureはStatic RenderingまたはDynamic Rendering、部分的なハイドレーションによるJavaScriptの削減でパフォーマンスを最大化させています。ハイドレーションのプロセスを減らすことで、Next.jsのSSRやSSGよりもJavaScriptの通信量が削減できます。そのため、アプリケーションが機能するまでの時間(TTI
)のパフォーマンスが向上します。
出典: 2023 Web Framework Performance Report (opens new window)
# デメリット
# フレームワークが限られる
Islands Architectureの考え方自体は、従来のMPAで実装可能です。 しかし、JavaScriptで実装でき、コンポーネントベースの開発となると使えるフレームワークに限りがあります。 現状、Astroが使われることが多いですが、今後他の選択肢が増えていく可能性はあるでしょう。
# リッチなアプリケーションには不向き
Islands Architectureの強みはパフォーマンスに特化していることです。余分なJavaScriptを極力減らすことでパフォーマンスを最大化させます。 そのため、ダッシュボードやCMSサイト、SNSのようなインタラクティブな動きを多く伴うアプリケーションには不向きです。 リッチなアプリケーションの場合は、SPAで実装するのが適切でしょう。