このブログを Astro 6.0 にアップデートしてみた

3 min read
Table of Contents

おっと、Astro 6.0 のリリース、きましたね!
ブログの「衣替え」は、技術者にとって一大イベントです。
今回のアップデート、結構「これは!」というポイントがいくつかありました。
特に astro-pagefind の件は、個人的にも「ふむむ…」となったので、皆さんと共有したいなと。

今回のアップデートで、いくつかの「まさか」と「なるほど」がありました。

astro-pagefind との別れ、そして新しい出会い?

全文検索って、あるとやっぱり便利ですよね。このブログでも Pagefind を活用していたんですが、
Astro 6.0 に対応するインテグレーションがまだなかったんです。そこで、泣く泣く自作インテグレーションに切り替えることに…。

やっていることは、ざっくり言うとこんな感じです。

  1. ビルド後、Pagefind の Node.js API で「検索用データ」を生成。
  2. @pagefind/default-ui から必要なファイル(CSS/JS)を public/pagefind/ にコピー。
  3. 開発時には sirv を使って、これらのファイルをサクッと提供。

これらを plugins/pagefind/index.ts というファイルに、Astro のインテグレーションとして実装しました。

JavaScript の「モジュール」の罠

さて、自作インテグレーションを動かしてみたところ、開発サーバーでブラウザのコンソールに「Uncaught SyntaxError: Cannot use import statement outside a module」というエラーが! Pagefind の UI ファイル(ui.js)が import 文を使っているのに、HTML側で <script> タグに type="module" を付けていなかったのが原因でした。

「よし、type="module" を付けよう!」と思ったのも束の間…。今度は ui-core.js が Svelte に依存しているという問題が浮上。
いやはや、一筋縄ではいきませんね。

結局、@pagefind/default-ui の中にある npm_dist/mjs/ui-core.mjs という、外部 import をすべてバンドルしてくれた「完成品」を見つけ出しました。
これに window.PagefindUI = PagefindUI; を追記して、type="module" 付きの <script> タグで読み込むことで、なんとか解決。
JavaScript のモジュール周りは、まだまだ奥が深いと実感した次第です。

z のインポート元、変えなきゃダメなんですって

Astro 6.0 では、Zod のバージョンが v3 から v4 にアップグレードされました。
それに伴って、astro:content から z をインポートするのが「非推奨」になっちゃったんですよね。

- import { defineCollection, z } from 'astro:content';
+ import { defineCollection } from 'astro:content';
+ import { z } from 'astro/zod';

いきなり npx astro check を実行したら、「'z' is deprecated. ts(6385)」という警告が14件も! 「おっと、これはまずいぞ」と気づきました。

実は、最初は「getStaticPaths の中で Astro オブジェクトを使っているところを直せばいいのかな?」なんて勘違いをしていました。
でも、このブログにはそういうコードはほとんどなく、本当の原因は z のインポート元だったというオチ。
マイグレーションガイドは、やっぱり隅から隅まで読むべきですね、教訓です。

設定フラグ、整理整頓タイム!

Astro 6.0 では、いくつか「実験的」だった機能が「正式版」になりました。
これで、astro.config.tsexperimental ブロックがスッキリするわけです。

CSP (Content Security Policy) が正式対応

- experimental: { csp: true }
+ security: {csp: true }

これ、地味に嬉しい変更です。セキュリティを固めるのが、ぐっと手軽になりました。

Fonts API も正式対応

- experimental: { fonts: [...] }
+ fonts: [...]

このブログでは、fontProviders.fontsource() を使って「Noto Sans JP」をセルフホストするように設定しました。

fonts: [
  {
    provider: fontProviders.fontsource(),
    name: 'Noto Sans JP',
    cssVariable: '--font-noto-sans-jp',
    weights: ['100 900'],
    styles: ['normal'],
  },
],

これで、Google Fonts に頼らずとも、フォントの管理が Astro に任せられるようになりました。
パフォーマンス的にも安心感がありますね。

Tailwind CSS v4 にも衣替え

@astrojs/tailwind インテグレーションが廃止されたので、@tailwindcss/vite を Vite プラグインとして直接使う形に変更しました。

import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  vite: {
    plugins: [tailwindcss()],
  },
});

Tailwind CSS v4 自体の設定変更もありましたが、このブログは Tailwind の設定をそこまで複雑にしてなかったので、比較的スムーズに進みました。
Tailwind の進化についていくのも、また一苦労ですね。

Vite 7 の、あの「プチバグ」をパッチ!

Astro 6.0 から Vite 7 が使われるようになったんですが、Vite 7.3.1 の時点で、開発サーバーが動かないという「残念なバグ」がありました。
具体的には、node_modules/vite/dist/client/client.mjs の先頭にある import のパスが、本来 "/@vite/env" であるべきなのに、"/\@vite/env" になっていたんです。ブラウザがこれを見つけられなくてエラーに…。

この問題、npm install のたびに自動で修正されるように、postinstall スクリプトでパッチを当てるようにしました。

"scripts": {
  "postinstall": "node tools/fix-vite-client-import.mjs"
}

「こんなところでデバッグに時間を費やすとは…」と思いつつも、これでひとまずは安心。あとは、公式での修正を待つばかりです。

新しい「実験的」フラグ、触ってみた!

Astro 6.0 では、さらに未来の機能に触れられる「実験的」なフラグもいくつか追加されています。

Rust コンパイラ (rustCompiler)

.astro ファイルをコンパイルする部分が、なんと Rust 製のコンパイラに移行中なんです!
experimental.rustCompiler: true を有効にすることで、この新しいコンパイラを試すことができます。

Queued Rendering (queuedRendering)

コンポーネントのレンダリング方法を変更する、これまた実験的なフラグ。
最大で2倍の速度向上が見込めるというから、期待大!将来的に Astro v7 ではデフォルトになる予定らしいので、今のうちに慣れておきたいところです。

experimental: {
  queuedRendering: { enabled: true },
  rustCompiler: true,
},

どちらのフラグも、今のところ大きな問題なく動いています。新しい技術に触れるのは、やっぱりワクワクしますね!

アップデートして、ここが良かった!

大変だった話ばかりだと、ちょっと疲れちゃいますよね。
でも、今回のアップデートには、素直に「これは良い!」と思える点もたくさんあったんです。

Fonts API で、フォント管理がスマートに

以前は、Google Fonts を使うために <link> タグを直接記述していました。
でも、Fonts API を使うようになってからは、Astro がフォントのダウンロードやキャッシュ、セルフホストまで全部やってくれるように!
プリロードヒントの自動生成もあるので、設定がシンプルになった上に、フォントの読み込み速度も体感で速くなりました。これは大きな改善点です。

CSP 設定、まさかの「ほぼ自動」!

security: { csp: true } の一行で、ページ内のスクリプトやスタイルのハッシュ計算から CSP ヘッダーの生成まで、Astro が全部やってくれるようになりました。
Astro 5 の頃は、まだ experimental フラグだったので、正直「これで大丈夫かな?」という不安もあったんですが、正式対応になったことで、安心してセキュリティを強化できます。

Rust コンパイラで、開発サーバーがキビキビ動く

experimental.rustCompiler: true を有効にすると、.astro ファイルのコンパイルが Go から Rust に切り替わります。
正直、体感で「起動が速くなったな」「HMR がキビキビするな」と感じています。
まだ実験的ですが、将来的にデフォルトになるのが楽しみで仕方ありません。

Queued Rendering で、ビルドがさらに高速化!

experimental.queuedRendering: { enabled: true } を有効にしました。
コンポーネントツリーのレンダリングが、再帰的な処理からキュー方式に変わることで、最大2倍の速度向上が期待できるとのこと。
このブログくらいの規模だと劇的な差は感じにくいかもしれませんが、ビルドログを見ると、確かに以前より速くなっているのが分かります。
Astro v7 でデフォルトになるのが待ち遠しいですね!

まとめ:アップデートの道のり、そして未来へ

今回の Astro 6.0 へのアップデートで、特に対応が必要だったのは以下の点でした。

  • astro-pagefind が非対応だったため、自作インテグレーションへ移行。
  • Zod の z のインポート元を astro/zod へ変更(astro:content からは非推奨)。
  • experimental.cspsecurity.csp へ、experimental.fontsfonts へ移行。
  • Tailwind CSS v4 と @tailwindcss/vite への移行。
  • Vite 7 の @vite/env バグに対するパッチ適用。

「マイグレーションガイドはちゃんと読んだつもりだったのに…」と反省しているのは、astro:schemaastro:content からの z の deprecation に関する部分を見落としていたことです。npx astro check の警告をちゃんと追えば、もっと早く気づけたはず…。

それでも、今回のアップデートでブログはさらに快適に、そして安全に運用できるようになりました。Astro の進化は止まりませんね!