こんにちは。開発事業本部チームです。
開発事業本部にはいくつかの部署があり、その部署にローテーションでこのブログ記事の担当が回ってきます。
最初、人間がやらなくても良い事は機械にやらせるべきだな……とGitHub Copilot Chatにそれっぽい記事を書いて!とお願いしましたが、概要しか書いてくれず、詳細な記事は作ってくれませんでした。
仕方ないので自分で書くか……となると、ありきたりな○○を使ってみました!のような記事なら、それこそ生成AI系のサービスに投げればそれっぽいものを生成してくれるので、人が書く意味はないでしょう。
という事で、AIでは簡単には書いてくれなさそうな記事を書いてみたいと思います。
まずは参考までに、AIの書いてくれた記事を載せておきます。題材は個人的に今最も注目しているWebフレームワーク、Astroです。
Astroについて
こんにちは。開発事業本部チームです。
最近、フロントエンド開発の世界で注目を集めているフレームワークがあります。その名も「Astro」です。Astroは、モダンなWeb開発のための新しいフレームワークで あり、特にパフォーマンスと開発者体験の向上に焦点を当てています。
Astroの特徴
Astroは、以下のような特徴を持っています。
- コンポーネントベースのアーキテクチャ: React、Vue、Svelteなど、複数のフロントエンドフレームワークのコンポーネントをサポートしています。これにより、開発者は好みのフレームワークを選択して使用することができます。
- 静的サイト生成(SSG): Astroは、ビルド時に静的なHTMLを生成します。これにより、ロード時間が短縮され、SEOにも有利です。
- 部分的なハイドレーション: Astroは、ページ上の特定のコンポーネントだけをクライアントサイドでハイドレートすることができます。これにより、ページのパフォーマンスが向上します。
- 0kbのJavaScript: Astroは、デフォルトでクライアントサイドのJavaScriptを送信しません。これにより、ページのロード時間が大幅に短縮されます。
Astroの利点
Astroを使用することで、以下のような利点があります。
- 高速なページロード: 静的サイト生成と部分的なハイドレーションにより、ページのロード時間が短縮されます。
- 柔軟な開発: 複数のフロントエンドフレームワークのコンポーネントを組み合わせて使用することができるため、開発が柔軟になります。
- SEOの向上: 静的に生成されたHTMLは、検索エンジンによってより効率的にクロールされます。
まとめ
Astroは、モダンなWeb開発のための強力なフレームワークです。その特徴と利点を活かすことで、高速でユーザーフレンドリーなWebサイトやアプリケーションの開発が可能になります。Astroの時代が来るかもしれません。
なんとなく、分かるような分からないような、他との違いが分からない文章が出来上がりました。
続いて、Astroといえば?
そう、アイランドアーキテクチャですね!EtsyのフロントエンドアーキテクトであるKatie Sylor-Miller氏によって「コンポーネントアイランド」が提唱され、Preactの作者であるJason Miller氏の書いた記事によってアーキテクチャとしてまとめられたものになります。
アイランドアーキテクチャについても、Copilotに記事を書いて貰いましたので紹介します。
アイランドアーキテクチャとは何か?
こんにちは。開発事業本部チームです。
最近、Web開発の世界では「アイランドアーキテクチャ」という言葉をよく耳にします。この新しいアーキテクチャスタイルは、特に静的サイト生成(SSG)やサーバーサイドレンダリング(SSR)が主流となっている現代のWeb開発において、新たな可能性を提示しています。
アイランドアーキテクチャの概念
アイランドアーキテクチャは、ページを独立したコンポーネント("アイランド")の集合として扱います。これらのアイランドは、それぞれが独立して動作し、必要に応じてクライアントサイドで動的に読み込まれるか、あるいは静的に事前に生成されます。このアプローチにより、ページの重要な部分だけを動的にし、残りは静的に保つことができます。
なぜアイランドアーキテクチャなのか?
従来のSSGやSSRのアプローチでは、ページ全体を一度に生成またはレンダリングする必要がありました。これは、ページの一部分だけが動的である場合でも、全体のパフォーマンスに影響を与える可能性があります。アイランドアーキテクチャでは、必要な部分だけを動的にすることで、パフォーマンスを向上させるとともに、開発の柔軟性を高めることができます。
アイランドアーキテクチャの利点
- パフォーマンスの向上: 必要なコンポーネントだけを動的に読み込むことで、ページの読み込み時間を短縮できます。
- 開発の柔軟性: コンポーネントごとに開発を進めることができるため、大規模なプロジェクトでも管理しやすくなります。
- ユーザーエクスペリエンスの向上: ユーザーは必要な情報を素早く得られるため、サイトの使いやすさが向上します。
まとめ
アイランドアーキテクチャは、Web開発における新たなアプローチとして注目されています。パフォーマンスの向上、開発の柔軟性、ユーザーエクスペリエンスの向上など、多くの利点があります。今後、このアーキテクチャスタイルがどのように進化し、Web開発の世界にどのような影響を与えるか、非常に楽しみです。
かなり良い線に来ていますね!もうちょっと肉付けしてやれば、それっぽい記事になりそうです。
そこまで行けば、さも自分が書いたように提出して、偉い人を騙せるのでは……とそんな悪い事も考えてしまいますね。
次回以降の担当者の方には、もっとメタっぽい、プロンプトエンジニアリングの一環として、会社に出してもバレないブログ記事の生成方法を記事にしていただきたいですね。
全二回にして、一回分は生成した記事をそのまま使えば、一回分手が空くのでラッキー……と余計な事ばかり書くと怒られるので、そろそろ本題に入りたいと思います。
何故Astroか
まず、何故Astroに興味を持ったか。
これはまた後日、別の記事として書きますが(一粒で二度美味しい形式)、現在この技術ブログを別のサービスを使用して同じように再現してみる、という事を進めています。
このブログはSitecore JavaScript Service (JSS)で実装されています。
これを、CMS部分をHeadless CMSとして頭角を現しているmicroCMSを使用し、フロント部分は何か今っぽいものを使おう、という所までを決めていました。
フロント部分でぱっと思いついたのはNext.jsかNuxtで、Next.jsはReactベースでささっとやるのは面倒くさそう。おまけにSitecoreのXM CloudではNext.jsを使うので、被ると面白くない。
自分ではVueの経験が少しあり、Nuxtは社内で誰かが何かを作った、という話も聞かないので、とりあえずNuxtで行こう!と決めました。
何はともあれ、まず分析です。という事で、ざっくり分析しました。
静的コンテンツと動的コンテンツとありますが、ここではハードコーディングしてOKか、CMSから取って出さないといけないか、くらいの違いと思っていただければ。
さて、ここからが本番です。ブログは対外的な広報メディアのひとつとはいえ、なるべくコストはかけないで実現できるのであれば、嬉しい所。
となると、可能な限りSSG(Static Site Generation)として、コンピューターリソースを使用せずに配信できるようにしておきたい。SSR(Server Side Rendering)は可能な限り使いたくない、といった所になります。
その観点から分析をかけてみたのがこちら。
誰がアクセスしても変わらない部分、データ的に動的かどうかは置いておくとして、リクエスト的に静的な部分と動的な部分で切り分ける必要があります。
最新記事一覧やカテゴリー一覧、記事一覧などは静的ですが、「キーワード検索」に関しては動的です。
- アクセスしてきた閲覧者がキーワード入力欄に何らかのキーワードを入力
- 検索ボタンを押す
- 入力されたキーワードで記事を検索、一覧を返す
- その一覧を表示する
という流れとなり、入力されたキーワードに依存して、一覧内容が変わる事となります。
そうなると、SSRしか手段はありません。最初、ハイドレーションを使用してISRにすればそこそこ軽く行ける?と思ったのですが、結局最終的に表示するものは全てSSRでレンダリングとなり、SSGで取っておいたものの一部分だけをSSRで合成、とは行かないようでした。
やるだけやってみるか、という事でSSRで実装してはみたものの、当ブログをご覧になっていただくと分かるかと思いますが、左サイドバーのカテゴリー一覧、著者一覧、月別アーカイブのいずれも()内に件数が入っています。
つまり、SSRの度にここの件数も数えて出さないといけないという、厄介な構成になっています。結果的にこの仕様は無くすのですが、この時点では完コピが目標でしたので、そのような処理を実装しました。
provide/injectでシングルトンっぽい、インメモリに持った一つのインスタンスを返すような事も出来そうだったので、この部分を簡易なインメモリキャッシュ実装を入れる事である程度は応答時間の低下を緩和する事が出来ましたが、十分ではない。
ホスティング先は社の事情でAzure縛りのため、AppServiceのそこそこ良いスペックのもを使えば動きそうではあるが、静的Webアプリ程度ではかなりもっさりした動作になってしまいました。
余談ですが、静的Webアプリと言いつつ、BFF(Backend For Frontend)くらいの簡単なAPIは動くようにされており、Node.jsが動くので、SSRでも動いたりします。ただし動作は遅いです……。
さて、部分的にSSGに出来ても遅いSSRが残ってしまう、となるとよろしくない。そこそこ費用のかかるAppServiceに置くなら、Nuxtでやるよりも、当社が得意とする .NET Coreで実装し、検索のパスだけリバースプロキシでそっちに飛ばした方が……となってしまいます。
そこでふと思い出したのが、AWS Dev Dey 2023に行った時に聞いた、アイランドアーキテクチャとAstroの二つのキーワード。
Astroで行けるのか?
Astro公式ドキュメントのアイランドとは?によると、Astroにおけるアイランドとは下記のような考え方との事。図も併せてご覧ください。
Astroにおける「アイランド」とは、ページ上のインタラクティブなUIコンポーネントを指します。 アイランドとは、サーバーでレンダリングされた静的で軽量なHTMLの海に浮かぶ、インタラクティブなウィジェットのことだと考えてください。
ざっくりと言ってしまうと、コンポーネントとして実装したブロックごとに、独立して動作させる事ができる。引き続き、上記ページより部分的に引用していきます。
この柔軟性により、Astroは、React、Preact、Svelte、Vue、SolidJSなどの複数のUIフレームワークをサポートしています。それぞれが独立しているため、1つのページで複数のフレームワークを混在させることすら可能です。
その際、Astro以外のフレームワークをインテグレーションして使う事もできる。
デフォルトでは、AstroはすべてのUIコンポーネントをHTMLとCSSのみへと自動的にレンダリングし、クライアントサイドのJavaScriptを自動的に取り除きます。
これは厳しく聞こえるかもしれませんが、この挙動により、Astroウェブサイトはデフォルトで高速となり、またウェブサイトのパフォーマンスを低下させる可能性のある不要なJavaScriptを開発者が誤って送信することを防ぎます。
これは他のSSR/SSG系フレームワークでもそうですね。部分的にJavaScriptでの処理を残して、リクエストしてきたユーザー固有の処理が出来れば良いのに……と思っても、全てJavaScriptは処理済みのレンダリング結果に落とされ、残す事が出来ません。
一部ISR系では、部分的なSSRを遅延して取り込むためにJavaScriptのコードが出力されますが、自由に現在のページを操作するためのコードではありません(2024/6/19現在。それ以降、出ているかもしれませんが)。
静的なUIコンポーネントをインタラクティブなアイランドに変換するには、client:*ディレクティブを追加します。これによりAstroは、パフォーマンスの最適化のために、クライアントサイドのJavaScriptを自動的にビルドしてバンドルします。
アイランドでは、クライアントサイドのJavaScriptは、client:*ディレクティブを使って明示的にマークしたインタラクティブなコンポーネントに対してのみ読み込まれます。
また、インタラクティブにするかどうかはコンポーネント単位で設定されるため、各コンポーネントの使用状況に応じて読み込む優先度をそれぞれ指定できます。たとえば、client:idleは、ブラウザがアイドル状態になったときにコンポーネントをロードするように指示し、client:visibleは、コンポーネントがビューポートに入ったとき初めてロードするように指示します。
要するに クライアントサイドで動かす事もできる。
来ましたね!待望の部分的なクライアントサイドでの処理です。
従来型SSR環境
ここで一旦、少し考えてみたいと思います。従来型のサーバーサイドWebアプリケーションでは、基本SSRですし、その中にJavaScriptを入れて、部分的にインタラクティブな処理を実現する事ができます。普通に。
Visual Studio CodeとTypeScriptの組み合わせで大分良くなったとはいえ、やはりVisual StudioとC#の組み合わせの方が色々と手早く作りやすい部分があります。フレームワーク類の充実具合や、高機能なデバッガーなど、ソフトウェアを開発していく上で、きちんと動くものの品質を上げていく、という過程においては、一日の長があると思います。
加えて、.NET Framework から .NET Core を経て .NET 9まで来た現在では、Windowsプラットフォームのみならず、マルチプラットフォームで動作するようになっています。
Webアプリケーションも、他の環境と同じように組み込まれたWebサーバーであるKestrelを含む形でビルドでき、独立したWebサーバーとのインテグレーション無しに、単一バイナリでWebアプリケーションとして動かす事ができます。
勿論、Nginxやリバースプロキシ、L7のLoadBalancer等と組み合わせてマイクロサービスのように大きなサービスの部分として動かす事も可能です。
だったら、ASP.NET CoreとSPA系フレームワークを利用し、MPA(Multiple Page Application)でインタラクティブ性を持たせれば良いのではないか?
ごもっともです。実際、Reactだと面倒くさい(ごめんなさい)のでVueが主ですが、ASP.NET Coreのcshtml側で初期のサーバーサイドレンダリングを行い、以降のインタラクティブな部分はVueで実装する、といった形式での開発を行うケースも多くなっています。
ただ、この形式ですとやはりサーバーに要求されるコンピューターリソースはそこそこ大きいものになってしまいます。TTI(Time To Interactive)を重視するのであれば、サーバーサイドでの処理が一瞬で終わるスペックが必要となります。これはお高い!
また、SSR側でCSR(Client Side Rendering)側の処理が最小になるよう、CSRとしてはAOT(Ahead-Of-Time)じゃないですが、事前に必要な処理……例えばサーバーから初期データを取ってくる、のような部分はわざわざCSR側で行うのではなく、SSR側でHTML上にJSONで展開しておく等、どっちにとってどの部分を事前に処理するか、あるいはJIT(Just-In-Time)で実行時に処理するのか……などを考え出すと、夜も眠れなくなってしまうと思います。
あとは、そんな風に作ってしまうと、開発者しかいじれなくなってしまう!業務システムならまだしも、対外的な情報発信のための広報メディアでそんな事しようものなら、営業や人事がちょこっといじりたい、デザイナーが少しここを変えたい、そうした一切を開発者が行う必要が出てきます。
果たして、そんなシステムが良いシステムでしょうか?あんまり良くないのではないかと思います(強くは言いません)。
Astroなら行ける
前述したような、安く上げたいのに、少なくないコンピューターリソースを必用としてしてしまい、結果安くできない。この問題を解決するにはどうすれば良いか?
サーバーサイドで行う処理をゼロにしてしまえば、ファイルを置くだけで済むようになるので、今となってはより安価なホスティング方法が多数あります。つまり、SSGにしてしまえば良い訳です。
SSR、CSRともにRendering、つまり要求時に描画処理を行うというJITな処理に対し、SSGはGeneration、AOTでの生成となります。静的に出来たファイルをぽんと置くだけ……つまり、古のホームページ作成時代のような、FTP等でWebサーバーにファイルをアップロードすれば後は処理は不要となります。
さて、ここで最初の分析で挙げた、検索ページをどうするか、という部分を考えます。検索結果一覧以外に関しては、閲覧者ごとには変わらない部分なので、SSGが望ましい。毎回処理するのは無駄ですので。
そうなると、検索結果一覧を表示する部分だけが、CSRとして閲覧者ごとの操作に応えてくれれば良い。図の緑色の枠の部分をCSRを行うUIフレームワークコンポーネントアイランドとして、実装する事にしました。
具体的な実装例は後日microCMS編で使おうと思うので載せませんが、今回はCSR部分はSvelteを採用しました。理由は、
- 元がNuxtだったのでVueを使うとややこしくなりそうなのと面白くない
- Reactは面倒くさい(ごめんなさい)
- そんなに高度な画面要素の管理も必要なく、書き換えも頻繁ではない
事から、仮想DOMを使用せずに直接DOMをいじりながらも良い感じに抽象化してくれているSvelteを選択しました。単純に流行りそうだし読者ウケが良さそうなのもあります。
実際の検索処理は、microCMSのAPI呼び出しで行えるため、データに関する部分は完全に外出しにし、サイト自体は静的なファイルで完結する形となりました。
これにより、Azure Storageでの静的Webサイトホスティングという破格のホスティングサービスを利用する事ができるようになりました!勿論、今どき風にGitHubにプッシュしたらActionを使用してAzure Storageに配置、というCI/CDも行えます。
単にWebサイトとして配信できれば良い、という事であればこの時点で完了なのですが、従来のJSS環境固有の問題により、一部URLが素直ではない部分がありました。この素直でないURLをAstroで実現しようとすると厄介で、リダイレクトを決意します。
そこでAzure Application Gatewayを……と思いましたが、試しに試算するとこれだけで月に万単位の費用がかかります。ここまでで行ったコスト低減策が全て水の泡となりかねない費用感です。L7のLBでリダイレクトをかけるくらいなら、競合であれば月数百円~数千円程度で済む所、これは非常にいいただけません。
これについても、安価で解決する方法を見つけたため、microCMS編ででもご紹介しようと思います。ちなみに、Astroでリダイレクトをかけようとすると、元URLにindex.htmlができ、そこにmeta refreshで飛ばすためのタグが追加される、という形になります。
Webサイト的には、やはり301 Moved Permanently
で飛ばして、いつか不要な元URLはインターネット上から消えるようにしたい所なので、この案は不採用でした。
アイランドアーキテクチャとAstro
最後のまとめに入ります。この文章を簡潔にまとめると、次のようになります。
ほとんどが閲覧者のリクエストに対して静的であるWebサイトの中で、ごく一部部だけ動的に反応しなければならない箇所があった。
その問題の解決にあたって、アイランドアーキテクチャという概念が解決法に繋がり、この概念を実装したAstroという製品によって、実際に問題解決が行われた。
非常にあっさりしていますね。これだけ書いても全然面白くないので、分析や問題に悩んだり、意思決定したりの過程などを盛り込んで読み物として肉付けしたのがこの記事になります。
実はここまでの文章は、プロンプトを捻りに捻りまくってAIに出させたものでした!だとめちゃくちゃ面白いと思いますが、残念ならがら人の手によって書かれている内容となります。もし勉強不足で、実際と異なる部分がありましたらご容赦を🙇。
もうひとつ大事な事として、先にアイランドアーキテクチャという技術の概念があり、その実装としてAstroがある。という事です。Astroは素晴らしい製品ですが、同様の事が実装されればGatsbyでもNext.jsのuse clientなどでも構わない訳です。
製品というのは陳腐化しますし、場合によっては技術も陳腐化します。その時に、より良い問題解決のための技術選定をするためには、日々具体的な製品を把握してくよりも、技術や概念といったものを把握して、それを実装した製品を探して選定する、という方が遥かに楽です。知っていなければならない情報量が少なくて済むからです。
とはいえ、今簡単にアイランドアーキテクチャを活用したWebサイトを作れるのはAstroだけ!Deno向けのアイランドアーキテクチャを実装したフレームワークFreshもありますが、DenoであってNode.jsではおそらく使えません。
という事で、他の製品が出ないか気にはしつつも、当面の間はAstroを推していきたいと思います。この記事が面白かったら、チャンネル登録と高評価よろしくお願いします(冗談です)。