HTMLの書きやすさで動的処理を実現!Astroテンプレート構文の3大拡張機能

#Astro #HTML
HTMLの書きやすさで動的処理を実現!Astroテンプレート構文の3大拡張機能

HTMLとは?

「HTMLはプログラミング言語か?」という論争がある。

個人的な感覚として、ウェブサイトの構造を説明してくれるドキュメントなのでプログラミング言語ではないと思う。HTMLはそもそもHyper Text Markup Languageの略であり、「マークアップ言語」を自称しているのでその認識は間違っていないように思う。

さて、Astroはそんなマークアップ言語であるHTML重視のフレームワークと紹介される。公式サイト「簡単に使える」という章において、下記のように記載されている。

.astro UI言語は、HTMLのスーパーセットです。有効なHTMLはすべて、有効なAstroテンプレート構文です!つまり、HTMLを書けるなら、Astroコンポーネントも書けるということです!

HTMLのスーパーセットというフレーズを噛み砕くと、「標準的なHTMLの書き方を100%そのまま含んだ上で、さらに便利で強力な独自機能をプラスした拡張版」という説明になる。ここで個人的な疑問だが、「HTMLはプログラミング言語ではないと思うが、それに機能が追加されているとは?」と思ってしまった。

結論から言うと、AstroはHTMLの書き方をそのままベースにしつつ、そこに「JavaScriptによる動的な処理能力」をドッキングさせている。具体的にどういった機能が追加されているのか、この点を深掘りしていきたい。

追加された機能

マークアップ言語であるHTMLだけでは、プログラミングのような動的な配置を実現することはできないところに、下記に示す3つの機能が追加されることで、動的な配置を実装することが可能になっている。

以下は「作品一覧」のastroコンポーネントのソースである。このソースコードでは、3つの機能が全て利用されているため、このコードをベースに解説を行いたい。

---  
import (省略)
  
const sections: SectionItem[] = [  
  {  
    title: '本サイト',  
    description: 'ポートフォリオである本サイトの企画や仕様、更新内容をまとめたもの。',  
    href: '/works/portfolio/',  
    icon: 'home' as const,  
    isComingSoon: false,  
  },  
  {  
    title: 'ゲーム',  
    description: '完成品と開発過程をブログ形式で掲載。企画書・仕様書・設計書などは別リポジトリへのリンクで公開しています。',  
    href: '/works/games/',  
    icon: 'gamepad' as const,  
    isComingSoon: false,  
  },  
  {  
    title: 'UI',  
    description: 'ボタン操作で表示が切り替わるインタラクティブな形式で公開しています。',  
    href: '/works/ui/',  
    icon: 'monitor' as const,  
    isComingSoon: false,  
  },  
  {  
    title: 'YouTube',  
    description: 'YouTubeチャンネルの運用状況と、投稿した動画の概要・ふりかえりを紹介しています。',  
    href: '/works/youtube/',  
    icon: 'youtube' as const,  
    isComingSoon: false,  
  },  
  {  
    title: 'デザイン',  
    description: 'サムネイルやアイコンなど、デザイン関連の成果物を紹介しています。',  
    href: '/works/design/',  
    icon: 'design' as const,  
    isComingSoon: false,  
  },  
];  
  
const breadcrumbs = [  
  { label: 'トップ', href: '/' },  
  { label: '作品一覧', href: '/works/' },  
];  
---  
  
<PageLayout  
  title="作品一覧"  
  description="制作したゲーム・UI作品のカテゴリ選択ページです。"  
>  
  <div class="container-narrow py-12">  
    <Breadcrumbs items={breadcrumbs} class="mb-6" />  
  
    <PageHeading title="作品一覧" class="mb-8" />  
  
    <p class="text-main-muted mb-10">  
      以下5カテゴリから作品をご覧いただけます。  
    </p>  
  
    <div class="grid gap-6 sm:grid-cols-2">  
      {sections.map((section) => (  
        <SectionCard {...section} />  
      ))}  
    </div>  
  </div>
</PageLayout>

フロントマター

.md の拡張子のファイルで使われるマークダウン形式に親しみのある方は、聞いたことがあるかもしれない。

マークダウンファイルの先頭部分に、 タイトルや作成日、タグ、公開設定などのメタ情報を記載する--- (ハイフン3つ)で囲われた範囲のことをフロントマターという。.astro の拡張子を持つastroコンポーネントでも、このフロントマターの書き方が利用できるようになっている。

---  
import (省略)
  
const sections: SectionItem[] = [  
  {  
    title: '本サイト',  
    description: 'ポートフォリオである本サイトの企画や仕様、更新内容をまとめたもの。',  
    href: '/works/portfolio/',  
    icon: 'home' as const,  
    isComingSoon: false,  
  },  
  {  
    title: 'ゲーム',  
    description: '完成品と開発過程をブログ形式で掲載。企画書・仕様書・設計書などは別リポジトリへのリンクで公開しています。',  
    href: '/works/games/',  
    icon: 'gamepad' as const,  
    isComingSoon: false,  
  },  
  {  
    title: 'UI',  
    description: 'ボタン操作で表示が切り替わるインタラクティブな形式で公開しています。',  
    href: '/works/ui/',  
    icon: 'monitor' as const,  
    isComingSoon: false,  
  },  
  {  
    title: 'YouTube',  
    description: 'YouTubeチャンネルの運用状況と、投稿した動画の概要・ふりかえりを紹介しています。',  
    href: '/works/youtube/',  
    icon: 'youtube' as const,  
    isComingSoon: false,  
  },  
  {  
    title: 'デザイン',  
    description: 'サムネイルやアイコンなど、デザイン関連の成果物を紹介しています。',  
    href: '/works/design/',  
    icon: 'design' as const,  
    isComingSoon: false,  
  },  
];  
  
const breadcrumbs = [  
  { label: 'トップ', href: '/' },  
  { label: '作品一覧', href: '/works/' },  
];  
---  

上記箇所において、フロントマター内部で画面に表示するデータの宣言を行っており、フロントマター以下ではHTML的にそれらデータの配置を記載している。これはHTMLにはなかったデータの型管理や定義が持ち込まれたということを意味する。

また、コードと実際の配置が分離されていると考えてもらえれば、HTMLのスーパーセットという理屈が分かりやすいのではないだろうか。

JSX的な波括弧による動的埋め込み

通常のHTMLでは、一度書いた文字列は固定された静的なものとなる。しかし、下記に示す箇所でも使われているように、Astroテンプレート内では波括弧 { } を使うことでJavaScriptの変数や処理結果を直接埋め込むことができる。

    <div class="grid gap-6 sm:grid-cols-2">  
      {sections.map((section) => (  
        <SectionCard {...section} />  
      ))}  
    </div>

ここではフロントマターで定義した配列データ(5つのカテゴリ情報)を .map() 関数で繰り返し処理し、カード要素を動的に展開生成している。今後、セクションを追加したくなった場合はフロントマターで定義してあるデータを追加することで対応可能となっている。JavaやC言語でいうところのfor文のような繰り返し処理が、HTMLにも追加されたということである。

コンポーネント化

下記箇所で通常は存在しないHTMLタグを使っていることが確認できる。

    <Breadcrumbs items={breadcrumbs} class="mb-6" />  
    <PageHeading title="作品一覧" class="mb-8" />  

これらは決してカスタムHTMLタグを作って利用しているという訳ではなく、別ファイルに切り出しているコンポーネントをフロントマターでインポートし、HTMLタグのように利用している。また、タグの属性のような使い方で引数を渡して利用することも可能となっている。

これにより複数のページで共通して使いたい部品などを切り出しての再利用が容易になっている。

まとめ

「HTMLはプログラミング言語か?」という最初の問いに戻ると、答えはやはり「HTML単体は構造を記述するマークアップ言語」である。

しかし、Astroが提供する .astro ファイルは、HTMLが持つ「直感的で読みやすい記法」を100%残したまま、フロントマターや波括弧 { } を通してJavaScriptが持つ動的なプログラミング能力を完全に融合させた記法になっている。

  • 基本構造: 慣れ親しんだHTMLの書き方をそのまま使える
  • 追加機能: フロントマターでのデータ処理、波括弧によるループ・条件分岐、コンポーネントによる共通化

HTMLのシンプルな分かりやすさはそのままに、繰り返し処理などのプログラミング的な処理が持ち込まれた。まさしくHTMLのスーパーセットというフレーズが相応しいフレームワークといえる。

関連記事