🧊

Astro のコードを読む Part.1

GitHub - withastro/astro: Build fast websites, faster. 🚀🧑‍🚀✨

読みはじめた時点でのコミットは`21926278ba664d8362694efe51943968dfcb4b26`で、バージョンでいうと`1.0.0-beta.9`です。(めちゃめちゃ頻繁に更新されるので、今はもう最新ではないはず)

はじめに

最近のAstroですが、順調にメジャーリリースを目指して開発中です。

the official Astro v1.0.0 release will be available on June 8, 2022.
https://astro.build/blog/astro-1-beta-release/

という感じなので、コードを読むのにも丁度いいかなと。

もちろんバグやら挙動不審なところは散見されるものの、Partial HydrationできるSSGとしてのアイデンティティを確立しつつ、SSRもできるようになったりと、なかなか筋がいいなと思ってる今日この頃。

では本題へ。

リポジトリ構造

モノレポ。開発するには`pnpm`を使ってねって書いてあった。

❯ tree -d -L 2
.
├── assets
│   ├── brand
│   └── social
├── examples
│   ├── blog
│   ├── blog-multiple-authors
│   ├── component
│   ├── docs
│   ├── env-vars
│   ├── framework-alpine
│   ├── framework-lit
│   ├── framework-multiple
│   ├── framework-preact
│   ├── framework-react
│   ├── framework-solid
│   ├── framework-svelte
│   ├── framework-vue
│   ├── integrations-playground
│   ├── minimal
│   ├── non-html-pages
│   ├── portfolio
│   ├── ssr
│   ├── starter
│   ├── subpath
│   ├── with-markdown
│   ├── with-markdown-plugins
│   ├── with-markdown-shiki
│   ├── with-nanostores
│   ├── with-tailwindcss
│   └── with-vite-plugin-pwa
├── packages
│   ├── astro
│   ├── astro-prism
│   ├── create-astro
│   ├── integrations
│   ├── markdown
│   └── webapi
├── patches
└── scripts
    ├── cmd
    ├── memory
    ├── notify
    ├── smoke
    ├── stats
    └── utils

Exampleが豊富に用意されてることが伺える!

今回の主旨としての読みたいコードは、`packages`配下にあるものたち。

❯ tree -d -L 2 packages
packages
├── astro
│   ├── components
│   ├── src
│   └── test
├── astro-prism
├── create-astro
│   ├── src
│   └── test
├── integrations
│   ├── deno
│   ├── lit
│   ├── netlify
│   ├── node
│   ├── partytown
│   ├── preact
│   ├── react
│   ├── sitemap
│   ├── solid
│   ├── svelte
│   ├── tailwind
│   ├── turbolinks
│   ├── vercel
│   └── vue
├── markdown
│   └── remark
└── webapi
    ├── run
    ├── src
    └── test

ざっくり見てみる。

  • `astro`
    • Astroの実装の本体
  • `astro-prism`
    • `import { Prism } from "@astrojs/prism";`して使う
    • PrismでシンタックスハイライトできるAstroコンポーネント
    • 今のところ、別途でインストールしなくても使える
  • `create-astro`
    • いわゆるスターター
    • `npm init astro`するやつ
  • `integrations/xxx`
    • Astroと組み合わせて使うもの
    • レンダラとしてコンポーネント利用できるものや
    • ライブラリとして利用するもの、Astroを拡張するものなど
  • `markdown`
    • `@astrojs/markdown-remark`
    • Astro用に拡張された`remark`で、Markdownを扱う各所で使われる
    • `import { Markdown } from "astro/components";`でも使われてる
  • `webapi`
    • Nodeのランタイムでも、いわゆるWebのAPIを使えるようにする自作ポリフィル集
    • これだけでお腹いっぱいになるレベルのやつ
    • Fetch APIまわりや、SSR時に困らないようにDOM系も

というわけで、

  • `astro`
  • `integrations/xxx`のレンダラ系

この2つを重点的に読んでいきたい。

astroパッケージ

まずはディレクトリ構造から。

❯ tree -d -L 2
.
├── components
├── src
│   ├── @types
│   ├── adapter-ssg
│   ├── cli
│   ├── core
│   ├── integrations
│   ├── runtime
│   ├── template
│   ├── vite-plugin-astro
│   ├── vite-plugin-astro-postprocess
│   ├── vite-plugin-astro-server
│   ├── vite-plugin-build-css
│   ├── vite-plugin-build-html
│   ├── vite-plugin-config-alias
│   ├── vite-plugin-env
│   ├── vite-plugin-integrations-container
│   ├── vite-plugin-jsx
│   ├── vite-plugin-markdown
│   └── vite-plugin-scripts
└── test
    ├── benchmark
    └── fixtures

Astroは、基本的にはSSGのためのCLIでありつつ、Partial HydrationするためのCSR用、SSR用など一部ランタイムを提供してる。

ビルドや開発用にはヘビーにViteを使ってて、そのためのプラグインがいっぱいある感じ。

`core`はさておき、他の枝を見ておく。

components

これは、`import {} from "astro/components";`して使えるコンポーネントたちで、現状は3つある。

さっきチラ見した`Prism`は、ココにコードがないだけでこの仲間。

https://docs.astro.build/en/reference/api-reference/#built-in-components

cli

そのまんま、CLIとしてのコード。

CLIで利用できるサブコマンドは次のとおり。

  • `add`
    • 各integrationsを利用する設定を、`astro.config.mjs`に追加してくれるやつ
  • `docs`
    • ドキュメントのサイトをブラウザで開くだけ(いる?!)
  • `dev`
    • 開発用のサーバーを起動する
  • `build`
    • 本番用のビルドの実行
  • `preview`
    • SSGビルド済のファイルを、ローカルでプレビューするサーバーを建てる
  • `check`
    • ビルドできるかチェックする

runtime

`client`と`server`の2つがあった。

`client`は、Partial Hydrationを実現するために実際にクライアントサイドで実行されるものたち。Qwikのそれみたいに、`querySelector`で対象を探してイベントを貼りその時を待つ。

Qwikというフレームワークについて - console.lealog();

`server`は、ViteでのSSRで利用されるものたち。各フレームワークの判別や、`client:xxx`のハンドリングなど。

詳細は追々でよさそう。

integrations

この後で紹介する、Astroとあわせて使うフレームワークなどのための仕組み。

  • `astro:config:setup`
  • `astro:config:done`
  • `astro:server:setup`
  • `astro:server:start`
  • `astro:server:done`
  • `astro:build:setup`
  • `astro:build:start`
  • `astro:build:done`

これらのタイミングにフックできるようになってる。

vite-plugin-xxx

すごいいっぱいあるので、まずはざっくり。

  • `vite-plugin-astro`
  • `vite-plugin-astro-postprocess`
    • `.astro`ファイルのサポート用
  • `vite-plugin-astro-server`
    • `dev`コマンドで利用するローカルサーバー
  • `vite-plugin-build-css`
  • `vite-plugin-build-html`
    • `build`コマンドで利用する
    • ViteのビルドはRollupなので、実質Rollupプラグイン
  • `vite-plugin-config-alias`
  • `vite-plugin-env`
    • Viteの`.env`サポートの拡張ver
  • `vite-plugin-integrations-container`
    • 各integrationsをViteから参照できるようにする箱
  • `vite-plugin-jsx`
    • ViteのJSXサポートの拡張ver
    • ReactとPreactとSolidを一様に扱うためのもの
  • `vite-plugin-markdown`
    • `.md`ファイルのサポート用
  • `vite-plugin-scripts`
    • 記述されたJSがそれぞれどんなコンテキストで書かれたかを判別してる風
    • まだよくわからない

`vite-plugin-astro-server`は`dev`コマンドでだけ利用される。

この他にも、

  • `core/build/vite-plugin-hoisted-scripts.ts`
  • `core/build/vite-plugin-internals.ts`
  • `core/build/vite-plugin-pages.ts`
  • `core/build/vite-plugin-ssr.ts`

という4つがあって、これは`build`コマンドのみ利用されてる。どれもビルド時に生成するファイルをよしなにするための一手間っぽい感じだった。固定のテンプレ部をくっつけて吐き出すとかそういう。

integrations/xxxパッケージ

Astro本体と組み合わせて使える公式パッケージ群。

npmから別途でインストールして、設定ファイルである`astro.config.mjs`でその指定をする。

ジャンルごとに大別すると、4つある。

  • レンダラー
  • ライブラリ
  • アダプター
  • その他

integrationsの仕組みとしては、Astroの各プロセスごとにフックが呼ばれるようになっていて、そのタイミングで実行コンテキストに介入したり、Viteの設定を更新したり、成果物をいじったりできる。

それぞれ見ていく。

レンダラー

いわゆるコンポーネントに利用できるUIフレームワークたち。

単にSSGするためのテンプレートエンジンという意味では、`.astro`ファイルでコンポーネントが作れるので、絶対に必要なものではない。

クライアントでJSを使って動作させたいUIがあったりしたときに、はじめて必要になる。

  • `lit`
  • `preact`
  • `react`
  • `solid`
  • `svelte`
  • `vue`

現状はこの6種がサポートされていて、それぞれの方法でSSRした結果が、SSGで生成されて使われる。

コンセプト的には、この中の複数を一緒に使うこともできる(それぞれネストできるわけではないけど)という!
基本的にはSvelteを使うけど、あのReact製のUIライブラリが使いたくて・・みたいなのも叶うってこと。

コードも眺めてみたけど、SSRして静的なマークアップを出力するコードは6者6様なので、だいたいの雰囲気は似てるにしても、これメンテするの大変やろうな〜って感想。

ライブラリ

場合によっては利用したくなるかもしれないものたち。

  • `partytown`
  • `tailwind`
  • `turbolinks`

`astro.config.mjs`でViteの設定は追加できるけど、それだけで済まない場合や、もっと踏み込んで最適化されるべきな場合に、用意されるものかなーと。

アダプター

いわゆるSSR用のレイヤー。

  • `deno`
  • `netlify`
  • `node`
  • `vercel`

現状はこれだけしかないけど、他にも増やしていくという話だった。

これらを追加すると、SSGで静的なHTMLやらが出力される代わりに、各環境で動作するコード一式が出力されるようになる。

SSR用のアダプターを指定しない場合、デフォルトのSSG用のものが使われるようになってる。今の時点では、SSRとSSGを併用することはできない。(残念無念)

https://docs.astro.build/en/reference/adapter-reference/#building-an-adapter

Cloudflare Workers用のものはまだない。そしてざっとコードを見た感じだと、`miniflare`を使って動かすの無理では・・?という一抹の不安を感じている・・・!

その他

その他。

  • `sitemap`

ライブラリっぽいけど、まあAstro拡張みたいなイメージかと。

次回へ続く

という感じで、概観はわかったかなーと。めちゃめちゃ外枠だけやけど。

ただまぁAstroといえば、やっぱりCLIの`dev`と`build`コマンドがメインなので、続きは暇を見てそこを追っていこうかと。