Javascriptフレームワーク(Astro)で効率的なUI開発を実現する方法

2025.04.012025.08.08

近年のWeb制作では、UI/UXデザインやアクセシビリティへの意識がますます高まっています。企業やサービスの独自性を表現しながら、ユーザーにとって「使いやすいWebサイト」を実現するためには、JavaScriptフレームワークやUIフレームワークの活用が不可欠です。特に、高度なUIを効率的に構築し、運用コストも抑えたいというニーズが増えています。

実際のWebサイト制作プロジェクトでは、デザインコンセプトやブランドカラー、サービスの特徴に合わせたカスタマイズ性が求められることが多くなっています。こうした課題に対応するには、再利用可能なコンポーネント設計がポイントとなります。

本記事では、実際のプロジェクト事例をもとに、AstroとPrelineを活用した効率的なUI開発手法についてご紹介します。 AstroやPrelineの導入や、アクセシビリティを考慮したWebサイト構築に関心のある方の参考になれば幸いです。

Astroとは?

Astroは、高速なWebサイト構築に特化したモダンなJavaScriptフレームワークです。

ReactやVue.jsなど、様々なフレームワークで書かれたコンポーネントを統合できる柔軟性を持ち合わせています。また、Jamstack構成やヘッドレスCMS、API連携を容易にし、コンテンツ重視のWebサイト制作に最適です。

画面表示速度が速くSEOにも強い

Astroは、画面の表示速度向上とSEO強化に優れたフレームワークです。これは、最小限の.jsファイルしか読み込まないというAstroの独自の「アイランドアーキテクチャ」が大きく貢献しています。

このアーキテクチャでは、ページの読み込み時に必要な部分だけをインタラクティブにし、残りの部分は静的なHTMLとして生成します。これにより、クライアントサイドでのJavaScriptの実行が最小限に抑えられ、ページ全体の読み込みが非常に高速になります。例えば、ブログやコーポレートサイト、キャンペーンサイトなどコンテンツが中心のサイトでは、この特性が特に強みとなります。

また、GoogleはCore Web Vitalsで測定される読み込み速度やインタラクティブ性を重視しており、ページの表示速度はSEOランキングに直接影響します。高速なサイトはユーザーエクスペリエンスを向上させ、検索エンジンの評価を高めるため、AstroのパフォーマンスはSEO対策において非常に有効な選択肢といえます。

なぜAstroを選んだのか?

Astroは静的サイトジェネレーターでありながら、部分的にJavaScriptフレームワーク(ReactやVueなど)を組み込むことができます。 しかし、プロジェクトでの弊社のスコープはHTML、CSS、JavaScriptの開発であり、サーバーサイドはスコープ外のパターンです。

簡単にいうと、静的なUIと画面のHTMLを作成するという内容です。 その場合にはAstroは最適だと思います。

※Reactなどをベースとする動的なUIを開発する場合は、StoryBookを活用する方法があります。

静的なHTMLでUI開発をする場合のポイント

  • 再利用性を高めるため各UIはコンポーネントとして開発したい。 →レイアウト用のコンポーネント、UIコンポーネントを、共通のもの、フロント画面、管理画面などに分けて管理ができる。

  • 開発自体は高度であっても最終的なソースコードのJavaScriptは必要最低限にしたい。 →Astroの機能は画面を組み上げるためだけにすることができ、必要なJavaScriptは外部化して読み込むようにできる。

  • ファイルの読み込みや状態による分岐を柔軟に行いたい。 →Slot機能やページファイル自体をコンポーネントとして扱うことでPropsで必要な状態を静的に表現できる。

静的なHTMLでUI開発をする場合、上記のようなポイントが重要になりますが、AstroでTailwindCSSベースのPrelineを使用することで効率的に行うことができます。

AstroとNext.jsの違いは?

AstroとNext.jsは、どちらも.jsファイルを用いてWebアプリケーションを構築するフレームワークですが、それぞれ異なる特性を持っています。

Astroは、デフォルトでJavaScriptの読み込み量を最小限に抑えることで、高いパフォーマンスを実現しています。これにより、Core Web Vitalsの改善やSEO効果が期待でき、コンテンツが中心の静的なWebサイト構築に適しています。

一方、Next.jsはReactをベースとしており、クライアントサイドレンダリング(CSR)やサーバーサイドレンダリング(SSR)、静的サイト生成(SSG)、インクリメンタル静的再生成(ISR)といった多様なレンダリング戦略をサポートしているのが特徴です。そのため、動的でインタラクティブなWebアプリケーションの構築に優れた柔軟性を提供します。

比較すると、Astroは静的コンテンツの高速表示、Next.jsは高機能で動的なWebアプリケーション開発に強みがあります。

UI開発の方針

今回のプロジェクトでは、コンポーネントとして開発することで、保守性と再利用性の高いUIを構築する方針を採用しました。

  • Prelineを活用し、ベースのUIコンポーネントを統一

  • TailwindCSSをベースにスタイルを柔軟に調整しつつ、影響を最小限に

  • Monorepo構成を採用し、複数の画面でコンポーネントを共有

  • UIガイドページを作成し、エンジニアの認識を統一

それぞれ具体的なポイントや工夫した点を交えながら、順に詳しく解説していきます。

1. Prelineを活用してUIの統一感を確保

Preline?UIフレームワークとは?

参考・出典:

Prelineは、TailwindCSSをベースに構築されたUIフレームワークです。Webサイトの見た目を統一し、効率的なUI開発を実現するための機能を提供しています。

具体的には、ボタンやフォームといったWebサイトを構成する基本的なUIコンポーネントが事前に用意されており、これらのコンポーネントを組み合わせることで、一貫性のあるデザインを素早く実装できます。

また、Figmaのデザインキットが提供されているため、デザイナーと開発者の連携もスムーズに進めることが可能です。

Prelineの実例をご紹介

実際にPrelineを使用した具体的な事例をご紹介します。

たとえばPrelineには、あらかじめ「Solid」「Outline」「Ghost」「Soft」「White」「Link」など多様なスタイルのボタンコンポーネントが用意されています。

下記のように、用途やデザインに応じて様々なバリエーションを選択できる点が大きな魅力です。

<button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none">
  Solid
</button>

<button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-gray-200 text-gray-500 hover:border-blue-600 hover:text-blue-600 focus:outline-none focus:border-blue-600 focus:text-blue-600 disabled:opacity-50 disabled:pointer-events-none dark:border-neutral-700 dark:text-neutral-400 dark:hover:text-blue-500 dark:hover:border-blue-600 dark:focus:text-blue-500 dark:focus:border-blue-600">
  Outline
</button>

<button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent text-blue-600 hover:bg-blue-100 hover:text-blue-800 focus:outline-none focus:bg-blue-100 focus:text-blue-800 disabled:opacity-50 disabled:pointer-events-none dark:text-blue-500 dark:hover:bg-blue-800/30 dark:hover:text-blue-400 dark:focus:bg-blue-800/30 dark:focus:text-blue-400">
  Ghost
</button>

<button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-100 text-blue-800 hover:bg-blue-200 focus:outline-none focus:bg-blue-200 disabled:opacity-50 disabled:pointer-events-none dark:text-blue-400 dark:hover:bg-blue-900 dark:focus:bg-blue-900">
  Soft
</button>

<button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700">
  White
</button>

<button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent text-blue-600 hover:text-blue-800 focus:outline-none focus:text-blue-800 disabled:opacity-50 disabled:pointer-events-none dark:text-blue-500 dark:hover:text-blue-400 dark:focus:text-blue-400">
  Link
</button>

しかし、プロジェクトごとにブランドカラーやUIガイドラインが異なる場合、既存のままでは細かな要件に合わないことも少なくありません。 そこで、Prelineのベースとなるボタンコンポーネントをカスタマイズし、プロジェクトに最適なスタイルへ拡張していくことが重要となります。

今回は、Astroのコンポーネントとして汎用的なボタンUIを作成し、プロパティでバリエーションや状態を柔軟に制御できるようにしています。
下記はその一例です。

---
const { type, color, disabled, className, ...props } = Astro.props;

const classBase =
  'px-4 py-1.5 rounded-lg inline-flex items-center justify-center text-admin-h5 tracking-normal font-semibold transition-opacity ease-in-out duration-200 hover:opacity-60';
const classColor = color === 'primary' ? 'bg-admin-primary text-white' : 'bg-admin-secondary text-admin-primary';
const classDisabled = disabled ? 'opacity-50 pointer-events-none' : '';
---
<button
  {...props}
  type={type === 'submit' ? `button` : type}
  class={`${classBase} ${classColor} ${classDisabled}`}
  class:list={[className]}
  disabled={disabled}
  aria-disabled={disabled}>
  <span>
    <slot />
  </span>
</button>

これを活用すれば、どの画面でも統一感のあるボタンを使用できますし、画面として微調整が必要な場合もCSSを追加することができます。

このようにすることで、

  • どの画面でも統一感のあるボタンUIを再利用できる

  • 個別の画面で追加のカスタマイズやスタイル調整が必要な場合も、柔軟に対応できる

  • ボタンに限らず他のUIパーツでも同様の手法を適用しやすく、全体の保守性や品質が向上する

といった多くのメリットがあります。

また、共通のコンポーネント設計により、チームでの開発時にも認識合わせやレビューがスムーズになるため、実際の開発現場でも非常に有効なアプローチです。 このようにPrelineをベースにしつつ、Astroと組み合わせてプロジェクトの特色に合わせたUIコンポーネントを開発することで、より効率的かつ品質の高いWeb制作を実現できます。

2. TailwindCSSをベースにしたスタイリングの柔軟性

TailwindCSSがベースになっていることで、UIのスタイルを統一しつつ、カスタムCSSの影響を最小限に抑えることができます。 コンポーネント単位で適用されるため、特定の要素だけにデザインを適用するのが容易になり、不要なCSSの肥大化をある程度防ぐことが可能です。

TailwindCSSとは?

TailwindCSSは、ユーティリティファーストのCSSフレームワークです。

これは、あらかじめ定義された小さなクラス群(ユーティリティクラス)をHTML要素に直接適用することで、スタイリングを行うというアプローチを取ります。

例えば、テキストの色やサイズ、余白などを設定するためのクラスが多数用意されており、これらを組み合わせることで、CSSを直接記述することなく多様なデザインを実現できます。

TailwindCSSの大きな特徴は、カスタマイズ性が高い点です。設定ファイルを通じて、プロジェクトの要件に合わせて色、フォント、間隔などのデザイン要素を自由に定義できます。これにより、独自のブランドガイドラインに沿ったUIを効率的に構築することが可能です。

また、コンポーネント指向の開発と相性が良く、再利用可能なUIパーツを素早く作成できるため、大規模なプロジェクトにおいても一貫性のあるデザインを維持しやすくなります。

TailwindCSSでのカスタマイズ例をご紹介

実際のプロジェクトでは、tailwind.config.jsをカスタマイズして、ブランドや管理画面など用途ごとに独自のデザインシステムを作ることが一般的です。 たとえば管理画面専用のテキストサイズ(admin-h1~admin-h6など)をtailwind.configに追加しておけば、どのコンポーネントからも簡単に一貫したフォントサイズを適用でき、UIの統一感やデザインガイドラインの徹底が図れます。

TailwindCSSをカスタマイズして使用する際には、TailwindCSSのクラスとして追加を行いデザインを調整することができます。

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontSize: {
        'admin-h1': '2.5rem',
        'admin-h2': '2rem',
        'admin-h3': '1.75rem',
        'admin-h4': '1.5rem',
        'admin-h5': '1.25rem',
        'admin-h6': '1rem',
      },
    },
  },
};
<h1 class="text-admin-h1">Heading 1</h1>
<h2 class="text-admin-h2">Heading 2</h2>
<h3 class="text-admin-h3">Heading 3</h3>
<h4 class="text-admin-h4">Heading 4</h4>
<h5 class="text-admin-h5">Heading 5</h5>
<h6 class="text-admin-h6">Heading 6</h6>

こうして定義したテキストサイズは、class="text-admin-h1"のようにHTML上で直感的に利用できるため、複数人で開発する場合もスタイルのブレが起こりにくくなります。 また、UIガイドラインの修正や追加要望があった場合にも、tailwind.configを編集するだけで全体に反映でき、保守性・拡張性にも優れています。

さらに、TailwindCSSのカスタマイズ性を活かして、CSSのカスタムプロパティ(変数)を組み合わせることも可能です。たとえば、プロジェクトごとに色や余白、角丸の値などを--color-admin-primaryのような変数で管理し、デザインのバリエーションを容易に切り替えることができます。

このようにTailwindCSSをベースに、プロジェクト独自の設定やカスタムプロパティを活用することで、効率的かつ統一感のあるUI開発が実現できる点は、現代のWeb制作において大きなアドバンテージとなります。

3. Monorepo構成で複数の画面に対応

複数の属性の画面にまたがって共通のロジックやコンポーネントを利用するため、Monorepo構成を採用しています。 このアプローチにより、たとえば管理画面とフロントサイトといった異なる画面間でも、同じUIパーツやロジックをシームレスに活用できるようになりました。 コンポーネントのバージョン管理や変更履歴も一元的に管理できるため、プロジェクト全体の開発体制をより柔軟に運用する土台となっています。

Monorepoのメリット

  • 開発効率の向上 共通のUIコンポーネントやロジックを一つのリポジトリ(Monorepo)で管理することで、修正やアップデートを素早く全体に反映できます。たとえばボタンやフォーム、アラートなどのコンポーネントを一箇所で保守できるため、同じ修正を複数のプロジェクトに何度も適用する必要がなくなります。

  • 依存関係の管理が容易 npm workspacesなどを活用することで、各パッケージ(admin、front、uiなど)の依存関係を効率よく管理できます。パッケージ間での参照やアップデートもスムーズになり、バージョン管理の煩雑さを軽減できます。

  • CI/CDの最適化 Monorepo構成では、変更があったパッケージのみを検知してビルド・デプロイする仕組みを導入しやすくなります。これによりCI/CDの処理時間が短縮され、デリバリーのスピードも向上します。

ディレクトリ構成例

このような構成にすることで、管理画面(admin)とフロントサイト(front)で同じUIコンポーネント(ui)を簡単に共有できます。

project-root/
  ├── admin/
  ├── front/
  └── ui/

さらに、TypeScriptのtsconfig.jsonで以下のようにパスエイリアスを設定すれば、@ui/*で共通UIパーツを簡単に参照できます。

"paths": {
  "@/*": ["src/*"],
  "@ui/*": ["../ui/src/*"]
}

Monorepo構成の有用性

このMonorepo構成を採用したことで、複数の画面でUIコンポーネントを共通管理できる仕組みが実現しました。もしMonorepoでなければ、同じようなUIの修正が必要な時に、それぞれのリポジトリで別々に変更作業が発生し、手間もミスも増えやすくなります。

また、管理画面とフロントサイトでUIの仕様や設計に違いが生じやすく、プロジェクト全体の統一感を保つのも難しくなりがちです。

Monorepoによって、UIの一元管理・再利用性の向上・保守コストの削減といったメリットが得られるため、画面数やプロジェクト数が増えても開発効率や品質を落とさずに運用できる体制を実現できました。

4. UIガイドページの作成

UIガイドページは、uiディレクトリに格納し、各UIコンポーネントを読み込むことで、そのバリエーションを一覧表示する画面を構築しました。 このページを整備することで、開発者はコンポーネントを容易に発見し再利用でき、UIの統一感を保ちながら効率的な開発を進めることが可能です。 また、サーバーサイドへの組み込み時には、HTML構造やコンポーネントの使われ方を確認するドキュメントとしても機能します。

ガイドページの目的

  • コンポーネントの再利用を促進 開発者が必要なコンポーネントをすぐに見つけて活用できるよう、一覧性と分かりやすさを重視しています。

  • デザインの統一を確保 UIの仕様や使い方を明確に示すことで、デザイナーとエンジニアの間で認識の齟齬を減らし、プロジェクト全体の統一感を保てるようにしています。

  • 組み込み時のドキュメントとして活用 サーバーサイド側で実装する際も、実際のコンポーネントの使い方やHTML構造をすぐに確認できるよう、開発ドキュメントの役割も持たせています。

ソースコード表示コンポーネントの設計

ガイドページでは単にUIコンポーネントを並べるだけでなく、各コンポーネントが出力するHTMLをサンプルとして分かりやすく表示する必要がありました。そのため、UIコンポーネントを展開後のHTMLとして抽出し、整形したうえで表示できる専用のコンポーネントを用意しています。

これにより、見た目とコードの両方をひと目で確認できるガイドページが実現できました。

実際のものに近い例をご紹介します

---
const html = await Astro.slots.render('default');
import { Code } from 'astro/components';
import prettier from 'prettier';

// data-astro属性を排除
const rawHtml = html.replace(/ data-astro-[^=]+="[^"]*"/g, '');
const formatHTML = async (html: string) =>
  await prettier.format(html, {
    parser: 'html',
    singleAttributePerLine: true,
    htmlWhitespaceSensitivity: 'ignore'
  });

// コピー用CSSクラスで使えるユニークな文字列を生成
const generateRandomString = () => {
  return Math.random().toString(36).substring(2, 15);
};
const preId = generateRandomString();
---

<div class="w-full mx-auto">
  <Fragment set:html={html} />
</div>

<div class="relative w-full mx-auto mt-5">
  <div class="bg-gray-900 text-white p-4 rounded-md">
    <div class="flex justify-between items-center mb-2">
      <span class="text-gray-400">Code:</span>
      <button
        class="code bg-gray-800 hover:bg-gray-700 text-gray-300 px-3 py-1 rounded-md"
        data-clipboard-target=`.pre-${preId} code`
      >
        Copy
      </button>
    </div>
    <div class="overflow-x-auto">
      <Code
        code={await formatHTML(rawHtml)}
        lang="html"
        class=`rounded p-4 pre-${preId}`
      />
    </div>
  </div>
</div>

<script
  is:inline
  src="<https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.8/clipboard.min.js>"
></script>
<script is:inline>
  window.addEventListener('DOMContentLoaded', () => {
    new ClipboardJS('.code');
  });
</script>

ポイントは、Astroが標準で提供しているCodeコンポーネントを使い、ソースコード表示部分の整形にPrettierを活用していることです。これにより、UIコンポーネントを実際に表示したHTMLをきれいな形でそのまま掲載でき、見た目にも分かりやすいガイドページを実現しています。

Prettierは通常、開発時にコードの整形で使うものですが、こうしたガイドページでサンプルHTMLを自動で整える用途にも便利です。

また、「Storybookを使えば良いのでは?」と思う方もいるかもしれませんが、Astroでは現時点でStorybookの公式サポートがなく、Astroコンポーネントのまま活用するには難しい部分があります。 今回はAstro本来の機能を活かしてガイドページを作成したことで、生成後のHTMLをサンプルとして載せたいという要件にもぴったりな方法となりました。

この仕組みのおかげで、最低限のソースコードだけで実践的なUIガイドを作成できるのも、大きなメリットです。

まとめ

今回、AstroとPrelineを活用したことで、UI開発の効率化を図ることができました。UI全体の統一感を保ちながらも、TailwindCSSを利用した柔軟なスタイリングが可能になり、さらにMonorepo構成でコンポーネントを共有することで、さまざまな画面やプロジェクトにおいて無駄のない開発が実現しやすくなりました。また、UIガイドページの作成によって、コンポーネントの再利用やデザインの統一を意識した開発フローも取り入れることができました。

これまで静的なHTMLの管理や個別実装の中で苦労していた点も、Astroを活用したことで、よりシンプルかつ効率的にUI開発を進められるようになったと感じています。

Contact

制作のご依頼やサービスに関するお問い合わせ、
まだ案件化していないご相談など、
お気軽にお問い合わせください。

お問い合わせはこちら

関連ブログ