Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AstroとRustで考えるフロントエンドツールチェーンの今

Avatar for Kenji Kenji
October 23, 2026
310

 AstroとRustで考えるフロントエンドツールチェーンの今

Avatar for Kenji

Kenji

October 23, 2026

Transcript

  1. Vue Fes 2025 から Astro Japan Community へ pilcrow @pilcrowonpaper

    Why isn’t anyone from @astrodotbuild here at @vuefes :( Astro @astrodotbuild @jp_knj was there! pilcrow @pilcrowonpaper We need more people! Astro @astrodotbuild Who is organizing Astro meetups in Japan?
  2. 話すこと 1. 当時の判断 なぜ最初に Go を選んだのか 2. 発見した問題 使い続けるなかで何が見えたのか 3.

    前提の変化 2026年までに周囲はどう変わったのか 4. 新しい判断 その結果、責務をどう分け直したのか
  3. Astro 0.x の出発点 .astro Svelte Compiler fork を拡張 Astro の構文を変換し、ビルド基盤へ渡す

    VITE: The Documentary(Snowpack の話は 7:40 から) Snowpack ビルドと配信 Browser
  4. 2021 年、Go と Rust が選ばれていた Feb Sep Oct Oct Nov

    Dec Vite 2.0 Rome Parcel 2 Next.js 12 Astro 0.21 Turborepo esbuild を利用
  5. Astro v1 の構成 2022 年 ビルドのためのコンパイラだった。 Go Compiler .astro HTML5

    Parser esbuild(CSS) Nate Moore が挙げた Go の選定理由 esbuild が Go だった。Go は学びやすかった。 Nate Moore: Hello from the other side VITE: The Documentary(Astro の Vite 採用は 20:21 から) Vite Rollup esbuild Browser
  6. Astro Template Syntax --const products = await getProducts(); --Component script

    --- で囲む。ビルド時とサーバーで実行する JavaScript と TypeScript Astro Template Syntax
  7. Astro Template Syntax --const products = await getProducts(); --<ul> <!--

    template --> </ul> Template HTML を基礎に、コンポーネントを書ける。 Astro Template Syntax
  8. Astro Template Syntax --const products = await getProducts(); --<ul> {products.map((product)

    => ( <li>{product.name}: {product.price}</li> ))} </ul> JavaScript expression Astro の書き方って、JSX っぽい Astro Template Syntax
  9. Astro Template Syntax --const products = await getProducts(); const props

    = { title: "second" }; --<ul> {products.map((product) => ( <li title="first" { ... props}>{product.name}</li> ))} </ul> Q. この title は、どちらの値になる? first か、 second か
  10. Astro Template Syntax --const products = await getProducts(); const props

    = { title: "second" }; --<ul> {products.map((product) => ( <li title="first" { ... props}>{product.name}</li> ))} </ul> A. first astro#5558 の説明
  11. Astro Template Syntax --const products = await getProducts(); constの規則で扱ったため props

    = { title: "second" }; HTML --同じタグに同じ名前の属性が複数あると、ブラウザは先に書かれた属性の値を使う。 <ul> {products.map((product) => ( HTML Standard の重複属性の扱い <li title="first" { ... props}>{product.name}</li> ))} </ul>
  12. Astro Template Syntax HTML .astro の規則による補正 生成された HTML Go Compiler

    <table> は HTML5 Parser を拡張し、 <table> <tr><td>{'foo'}</td></tr> <tr><td>foo</td></tr> ビルド時にもタグの補完と入れ子の補正を担っていた。 </table> 表のパースの不具合報告 <h2>Chats</h2> HTML Standard のパース規則 <h2>Chats</h2> </table>
  13. Linter が検査を始めるまで Go Compiler が返す Astro AST { } ※1

    type: "expression", children: [{ type: "text", value: "price * amount" }] TextNode.value ※2 .astro の構文は Espree ※3 へ直接渡せない --const price = 10; const amount = 3; --<p>{price * amount}</p> は文字列 JavaScript expression の識別子と演算子が必要 ※1 AST は、コードの文法上のまとまりを木で表したデータ。 ※2 TextNode は、文字列を値として持つ node。 ※3 Espree は、JavaScript と JSX をパースして AST を返すライブラリ。
  14. Linter が検査を始めるまで JavaScript と JSX const price = 10; const

    amount = 3; <> <p>{price * amount}</p> </>; .astro を JavaScript と JSX に変換する Espree ※3 JavaScript expression の AST BinaryExpression ├─ operator: "*" ├─ left: Identifier │ └─ name: "price" └─ right: Identifier └─ name: "amount" BinaryExpression は二項演算 Identifier は識別子 でパースし、変数名と演算子を AST の項目として取得する ※1 AST は、コードの文法上のまとまりを木で表したデータ。 ※2 TextNode は、文字列を値として持つ node。 ※3 Espree は、JavaScript と JSX をパースして AST を返すライブラリ。 ※1
  15. 位置の対応と位置情報の不具合 変換後の JavaScript と JSX .astro <><p>{price * amount}</p> <p>{price

    * amount}</p> [46, 51) [49, 54) Go Compiler position: { start: { offset: 47 }, end: { offset: 80 } } 波かっこの範囲と一致しない 波かっこを含む正しい範囲 position: { start: { offset: 48 }, end: { offset: 64 } } {price * amount}
  16. Formatter が整形を始めるまで .astro {true ? <p>OK</p> : null} Go Compiler

    が返す Astro AST expression ├─ TextNode.value "true ? " ├─ p │ └─ TextNode.value "OK" └─ TextNode.value " : null" JavaScript expression 全体の AST はない
  17. Formatter が整形を始めるまで Astro plugin で連結中のコード "true ? " + "<p>OK</p>"

    + " : null" TextNode.value をそのまま使う p 要素を文字列に戻す TextNode.value をそのまま使う 文字列を組み立てる工程でも、エッジケースへの対応が必要 連結結果 true ? <p>OK</p> : null Babel に渡す前 <>{true ? <p>OK</p> : null}</> expression の AST を得るため、JSX で囲んで再パースする
  18. Go Compiler と Language Tool の分担 .astro Go Compiler TSX

    ※ Source map Language Tool Go Compiler では、JavaScript の構文の判別を独自の Scanner で実装していました。 書きかけの JavaScript にも対応しながら、TSX を生成する必要があった。 ※ Source map は、変換前後のコードの位置対応を記録したデータ。 Go Compiler と Language Tool の連携 TSX 生成を見直した背景
  19. Compiler はどうあるべきか Compiler に求めること Astro のタグに加えて、JavaScript expression の AST も返す

    正確な位置情報を返し、TSX への変換でも型の情報と位置の対応を保つ 開発チームが修正を続けられる実装にする 新 Compiler と Prettier plugin の検討 Compiler の保守範囲を見直す公開提案
  20. Rust とフロントエンドツールチェーン SWC Oxc Biome Lightning CSS JavaScript と TypeScript

    の Compiler Parser と Compiler Linter と Formatter 検査と整形と LSP CSS の変換と最適化 Rolldown Rspack Turbopack Turborepo バンドル バンドル Next.js のバンドル タスク実行
  21. Oxc を Parser として利用する .astro <p>{price * amount}</p> Oxc Parser

    expression を Oxc へ import { parseSync } from "oxc-parser"; const { program } = parseSync( "example.js", "price * amount", ); Oxc Parser AST 識別子と演算子
  22. Lossless CST のよさ ※1 price * amount; // 税込 Prettier

    と Babel // AST { type: "BinaryExpression", operator: "*", left: { name: "price" }, right: { name: "amount" } } // コメント [{ type: "CommentLine", value: " 税込" }] Biome の Lossless CST // CST の模式図 ExpressionStatement ├─ BinaryExpression │ ├─ "price" [空白 2] │ ├─ "*" [空白 1] │ └─ "amount" └─ ";" [空白 1 と "// 税込"] ※1 Lossless CST は、空白とコメントと改行も保持する構文の木。 ※2 rowan は rust-analyzer でも使われる構文木ライブラリ。Biome は fork して利用。 ※2
  23. Biome の Lossless CST で書式を保つ この 1 か所の price を

    unitPrice に変えたい 変更前 price * amount; // 税込 CST の名前の部分だけを変更 変更後 unitPrice * amount; // 税込 空白 2 文字とコメントと末尾の改行は、そのまま 変更しない部分の書式を保ったまま、修正できる ※ rust-analyzer でも使われている rowan を基に実装 Biome の Parser と CST
  24. TypeScript との連携 TypeScript は Go へ .astro .vue .svelte Content

    Mapper .mdx TypeScript のネイティブ移行 Astro の Content Mapper の実装 Content Mapper の仕様と実装 TypeScript 7.1
  25. Astro が実装して保守する範囲 .astro <style> Compiler の実装と依存関係 AST Astro の Oxc

    Parser Astro Codegen JavaScript Lightning CSS Astro の CSS スコープ CSS
  26. Astro Template Syntax の振る舞い 書かれた親子関係を保つ .astro 生成された HTML <table> <tr><td>{'foo'}</td></tr>

    </table> <h2>Chats</h2> <table> <tr><td>foo</td></tr> </table> <h2>Chats</h2> Compiler は HTML 補正を行わない。 HTML 補正を行わない方針 Astro Template Syntax の仕様ドラフト
  27. Astro Template Syntax の振る舞い 空白を JSX の規則で扱う .astro <span>Hello</span> <span>World</span>

    Astro v7 は標準で compressHTML: 'jsx' Astro v7 の空白規則 Astro Template Syntax の仕様ドラフト ブラウザでの表示 HelloWorld
  28. Oxfmt と Astro Oxfmt Biome Formatter Oxfmt の Astro 対応計画

    Biome Formatter の再利用 Astro plugin の実装 Prettier plugin Rust Compiler
  29. TSX と位置対応 @astrojs/astro2tsx .astro Astro Language Tool TypeScript Language Tool

    と Volar の連携 Content Mapper が返すデータ Editor TSX と位置対応 Content Mapper @astrojs/ts-content-mapper TypeScript 7.1
  30. MDX の試作とライブラリへの貢献 2025 年 7 月 2025 年 8 月

    Astro への統合を提案 🦀 Rust Compiler MDX を速くしたい 🤝 🚀 Astro AST Bridge 🌳 2025 年 8 月 ※1 を提案 🧩 JavaScript plugin Rust の AST remark と rehype も使いたい ※2 markdown-rs に提案 🌳 🧩 🌳 AST plugin AST Rust の中で AST を変更 JavaScript との往復を減らす 試作をきっかけに、交流がはじまった。 ※1 AST Bridge は、Rust でパースした AST を JavaScript のプラグインへ渡す提案。 ※2 remark は Markdown、rehype は HTML の変換をプラグインで拡張する仕組み。
  31. Processor を自作して Astro に組み込む Starlight のサイトが利用 Astro 利用 導入 Astro

    integration Vite hook を実行 登録 Vite plugin Astro の モジュールに変換 呼び出し Node-API bindings ※ 呼び出し JavaScript から Rust を呼ぶ ※ Node-API bindings は、Node.js とネイティブコードの間で関数と値を受け渡す部分。 xmdx と Astro integration Compiler Rust でパースと変換 MDX のコードを生成
  32. Processor を自作して Astro に組み込む Starlight のサイトが利用 Astro 利用 導入 Astro

    integration Vite hook を実行 登録 Vite plugin Astro の モジュールに変換 呼び出し Node-API bindings ※ 呼び出し JavaScript から Rust を呼ぶ ※ Node-API bindings は、Node.js とネイティブコードの間で関数と値を受け渡す部分。 xmdx と Astro integration Compiler Rust でパースと変換 MDX のコードを生成
  33. Sätteri とは ドイツの Seibert で Louis Escher が紹介 Astro Together

    FRA × Seibert(11:40 から) Erika の Sätteri 紹介 Sätteri のドキュメント Astro 公式のイベント案内
  34. 最初の問いへの答え 当時の判断 発見した問題 Go は学びやすい expression の AST を取得できない HTML5

    Parser の拡張 位置の対応と位置情報の修正 esbuild の CSS Parser の利用 HTML 補正と TSX 生成の保守 前提の変化 新しい判断 Oxc と Lightning CSS Astro が実装して保守する範囲を絞る Biome の Lossless CST AST と位置情報をツールへ返す TypeScript と Content Mapper Astro Template Syntax の規則を共有
  35. ロゴのクレジット Go Gopher Biome Renee French 配布元 と CC BY

    4.0 背景を除去し、透過画像に編集 Alexandru-Ștefan Gârleanu Biome Core Contributors and Maintainers 配布元 と CC BY-SA 4.0 Oxc Vue Oxc project 配布元 と CC BY-NC-SA 4.0 Evan You 配布元と追加条件 CC BY-NC-SA 4.0 HTML5 W3C 配布元 と CC BY 3.0 Biome と Oxc と Vue と HTML5 は Iconify の SVG も利用(SVG の最適化あり)