技術約6分で読めます

記事1558本のブログをAstro 6から7に上げる作業ログ(Sätteri回避とVercelアダプタv11)

いけさん目次

Astro 7が2026年6月22日に出た。Goで書かれていた.astroコンパイラがRustに載せ替わり、Vite 8(Rolldown)に上がって、markdownパイプラインもネイティブのSätteriに置き換わったやつ。 このブログはAstro 6.1.3で動いていて、記事は1558本、数式はKaTeX、YouTube/動画の埋め込みは自作のrehypeプラグイン、デプロイはVercel。 コンテンツ量が多くてmarkdown周りに手を入れているサイトほどSätteriの影響を受けるので、実際に上げられるのか手を動かして確かめた作業ログを残す。

依存を上げて.astroを1か所直すだけで本番ビルドは通った。以下はその手順と、Rustコンパイラに弾かれた箇所の記録。

この環境

  • Astro 6.1.3 / Node 22.22.0 / pnpm / output: 'static' でVercelにデプロイ
  • 記事(.md/.mdx): 1558本
  • .astroコンポーネント: 109ファイル
  • markdownまわりを大きく差し替えている
    • remarkPlugins: remark-math
    • rehypePlugins: rehype-raw / rehype-katex / rehype-external-links / 自作のrehype-youtube-embed / 自作のrehype-video-embed
    • Shikiのカスタムtransformer(コードブロックにファイル名を出す)

つまりデフォルトのmarkdown処理をがっつり差し替えている。Astro 7の変更で一番影響が出るのもここだ。

このブログに影響する破壊的変更

変更点内容
Rust製コンパイラGoからRustに載せ替え。未閉じタグや不正なHTMLネスト(<p>の中に<div>など)を、旧コンパイラのように黙って直さずエラーにする
Sätteri.md/.mdxのデフォルト処理がremark/rehypeからネイティブのSätteriに変更。remark/rehypeプラグインは標準では動かない
Vite 8 + Rolldownesbuild + Rollupが単一のRust製バンドラRolldownに統合
Node v22必須要件が>=22.12.0に。これは22.22.0で満たしているのでクリア

依存の互換性を確認する

レジストリで各パッケージのAstro 7対応版とpeerDependenciesを先に調べた。

パッケージ現在Astro 7対応版対応
astro6.1.37.0.4メジャーアップ
@astrojs/vercel10.0.411.0.0メジャー必須(v11がastro ^7をpeer要求)
@astrojs/markdown-remarkなし7.2.0新規導入(後述)
@astrojs/sitemap3.7.23.7.3軽微
@astrojs/rss4.0.184.0.19軽微
@astrojs/partytown2.1.62.1.7軽微
@tailwindcss/vite4.1.184.3.2要更新(Vite 8対応済み)
tailwindcss4.1.184.3.2同上

要点は2つ。

  • @astrojs/vercelはv11のpeerDependenciesがastro ^7。v10のままだと入らないのでメジャーで上げる
  • @tailwindcss/vite 4.3.2はvite: ^5 || ^6 || ^7 || ^8をサポートしていて、Vite 8で問題ない

最大の関門はSätteriとremark/rehype

Astro 7は.md/.mdxをSätteriで処理する。remark/rehypeパイプラインはデフォルトから外れた。 このブログは数式・生HTML・自作埋め込みをすべてrehypeで処理しているので、素のSätteriに移ると全部止まる。

対応は2つある。 1つはプラグインをSätteriに移植する道。既存のremark/rehypeプラグインをSätteriのMDAST/HASTプラグインとして書き直す。挙動を作り込んでいる分、工数が大きい。 もう1つは@astrojs/markdown-remark@7.2.0を入れてunifiedパイプラインに留まる道。これまでのremarkPlugins/rehypePlugins設定をそのまま使い続けられる。非推奨警告は出るが動く。

今回は後者にした。1558本の記事の数式・埋め込み・生HTMLの挙動を維持するのが最優先で、移植でレンダリング差分が出るリスクを避けたい。移植は別の作業として切り分ける。

実際の作業

1. ブランチを切る

git checkout -b upgrade-astro-7

2. package.jsonを更新する

依存を書き換える。@astrojs/markdown-remarkは新規追加。

-    "@astrojs/partytown": "^2.1.6",
-    "@astrojs/rss": "^4.0.18",
-    "@astrojs/sitemap": "^3.7.2",
-    "@astrojs/vercel": "^10.0.4",
+    "@astrojs/markdown-remark": "^7.2.0",
+    "@astrojs/partytown": "^2.1.7",
+    "@astrojs/rss": "^4.0.19",
+    "@astrojs/sitemap": "^3.7.3",
+    "@astrojs/vercel": "^11.0.0",
-    "astro": "^6.1.3",
+    "astro": "^7.0.4",

devDependencies側も上げる。

-    "@tailwindcss/vite": "^4.1.18",
+    "@tailwindcss/vite": "^4.3.2",
-    "tailwindcss": "^4.1.18",
+    "tailwindcss": "^4.3.2",

3. インストールする

pnpm install

差し替えは想定どおり通った。

dependencies:
+ @astrojs/markdown-remark 7.2.0
+ @astrojs/partytown 2.1.7
+ @astrojs/rss 4.0.19
+ @astrojs/sitemap 3.7.3
+ @astrojs/vercel 11.0.0
+ astro 7.0.4

devDependencies:
+ @tailwindcss/vite 4.3.2
+ tailwindcss 4.3.2

peer依存の警告も出ずにインストールできた。@astrojs/markdown-remarkを先に入れているので、markdown.remarkPlugins/markdown.rehypePluginsはそのまま解決される想定。

ビルド検証

このブログはdevサーバをTailscale経由でリモート公開しているので、ビルドするとdevが落ちてリモートアクセスが切れる。devを一時停止してからpnpm buildを回した。

Rustコンパイラに弾かれたのは1か所だけ。

[CompilerError] Closing tag '</a>' has no matching opening tag.
  Location: src/pages/harahe.astro:243:32

原因はこれ。開始タグのない</a>が紛れていた。旧Goコンパイラは黙って捨てていたが、Rustコンパイラはエラーにする。

-                  <li>表紙イラスト各位</a></li>
+                  <li>表紙イラスト各位</li>

1行消して再ビルドしたら通った。

[build] 5316 page(s) built in 21.26s
[pagefind-articles] Pagefind indexed 1552 article pages
[@astrojs/vercel] Copying static files to .vercel/output/static
[build] Complete!

.astroは109ファイルあったが、引っかかったのは1つだけ。事前に心配していた空白処理やCSSシリアライズ差も、目視した範囲では表示崩れは出ていない。数式・埋め込み・生HTMLも、Sätteri回避(@astrojs/markdown-remark)でunifiedパイプラインを維持しているためか、レンダリング差分は今のところ見当たらない。

ビルド中に出た警告はこれ。

markdown.remarkPlugins, markdown.rehypePlugins, and markdown.remarkRehype are deprecated.
Pass them to unified({...}) from @astrojs/markdown-remark directly instead.

unifiedパイプラインに留めている以上は出る警告で、動作には影響しない。将来的には@astrojs/markdown-remarkunified()に直接渡す書き方へ移すのが本筋。

もう一つ、Vite/Rolldownが「500kB超のチャンクがある」と警告した。中身を見ると、原因は画像変換Labツールで使うheic2any(HEIC変換ライブラリ)1つだけで1.3MBある。記事ページには乗らない独立チャンクで、Astro 7固有でもない(Viteのデフォルト閾値は前から500kBで同じ)。実害はないので放置した。

dev側の確認

devを立て直して主要ルートを叩いた。trailingSlash: 'never'なので末尾スラッシュ付きは404で正しく、スラッシュなしは全部200。

200  /
200  /en
200  /en/articles
200  /en/articles/10secondsdash-release
200  /en/tech
200  /articles

日本語トップ、英語トップ、記事、一覧、タグとも表示に問題なし。

Astro 7にはエージェント検知が入った。astro devをコーディングエージェント配下で起動すると自動でバックグラウンド常駐し、2回目以降の起動は構造化JSONでalready runningを返す。今回のdev立て直しはこれでスムーズだった。

Vercelのプレビューで確認する

mainに入れる前に、ブランチをpushしてVercelのプレビューデプロイで見る。Gitのブランチをpushすると、本番とは別にプレビューURLが自動で作られる。本番と同じ経路のビルドをここで1回通せる。

プレビューのビルド自体は通ったが、ローカルでは出なかった指摘がVercelのログに出た。

middlewareのTS1543とesbuildの板挟み

Vercelのビルドログにこれが出ていた。

middleware.ts(6,20): error TS1543: Importing a JSON file into an ECMAScript module
requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.

このブログはルート直下にmiddleware.ts(Vercelのルーティングミドルウェア)を置いていて、そこでtag-map.jsonをimportしている。VercelはこれをNodeNextで型チェックするので、JSON importにimport属性を求める。

まずは指示どおりimport属性を付けた。

-import tagMap from './tag-map.json';
+import tagMap from './tag-map.json' with { type: 'json' };

型チェックは満たしたが、今度はデプロイの最終段でesbuildが落ちた。

Build failed with 1 error:
vc-file-system:__vc__ns__/0/middleware.js:5:36: ERROR: Expected ";" but found "with"

Vercelがmiddlewareをバンドルするesbuildは、このJSON import属性の構文をまだ解釈できず、withで構文エラーになる。TypeScriptは要求するのに、バンドラは受け付けない。

元のTS1543はデプロイを止めない型診断で、import属性を付けたことでかえってデプロイが壊れた。プレーンなimportに戻して、型診断だけ@ts-ignoreで抑える形にした。

// @ts-ignore
import tagMap from './tag-map.json';

これでVercelのログからTS1543が消え、esbuildのバンドルも通る。