最近、大規模なサイトをリリースしたので、 備忘録として記録を残しておく
背景
今回、会社で大規模なWebサイトのリリースを担当しました。本記事では、開発を通じて得た知見を言語化し、次のアウトプットにつなげることを目的としています。
実装環境
用途 | 技術スタック |
|---|---|
静的ローカル環境 | Astro / TailwindCSS / JavaScript / Node.js |
動的ローカル環境 | Docker(WordPress環境) |
ステージング・本番環境 | サーバー一体型WordPress |
Astro
AstroはコンテンツファーストなWebサイト構築に特化したフレームワークです。デフォルトでJavaScriptを最小限に抑えた静的HTMLを出力するため、表示速度を重視するWebサイト開発に適しています。ReactやVue、Svelteなど複数のUIフレームワークをプロジェクト内で併用できる点も特徴のひとつです。また、必要なコンポーネントだけをクライアントサイドで動作させる「アイランドアーキテクチャ」を採用しており、パフォーマンスと開発体験を両立しています。
コンポーネント設計にはslotを活用する
アトミックデザインの考え方に基づいてコンポーネントを設計していると、「このUIはコンポーネント化すべきか」「moduleとorganismのどちらの粒度で管理すべきか」という判断に迷う場面があります。大規模なWebサイトでは、全ページを把握した上でコンポーネントを設計することが困難になるケースも少なくありません。
そのような場合、無理に粒度を大きくしようとせず、slotを活用して柔軟に管理しておくことがコンポーネント設計の破綻を防ぐ有効な手段になります。複数ページで多用する、または複数の作業者が同じコンポーネントを使うことが明確になった段階で、改めて適切な粒度のコンポーネントに整理するという進め方が現実的です。
---
// organisms/Card.astro
---
<div class="rounded-lg border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-200">
<slot name="header" />
</div>
<div class="px-6 py-4">
<slot />
</div>
<div class="px-6 py-4 border-t border-gray-200">
<slot name="footer" />
</div>
</div>---
// 呼び出し側
import Card from '@/components/organisms/Card.astro';
---
<Card>
<h2 slot="header" class="text-lg font-semibold text-gray-900">タイトル</h2>
<p class="text-sm text-gray-600">本文コンテンツ</p>
<a slot="footer" href="/detail" class="text-sm text-blue-600 hover:underline">詳細を見る</a>
</Card>チームでの共有にはAstroBookを
複数人で開発を進める場合、同じUIが別々のコンポーネントとして重複して実装されてしまうことがあります。ReactでStorybookを活用するのと同様に、AstroにはAstroBookというUIカタログツールが用意されています。コンポーネントの重複や認識のズレを防ぐために、プロジェクトの規模や体制に応じて導入を検討してみてください。
CSSの管理(TailwindCSS)
今回はTailwindCSSを採用しました。ある程度の経験はあったものの、不用意にユニークなクラスを生成してしまわないためには、以下の記法を正しく理解しておく必要があると感じました。
任意のバリアント
[&.is-active]のように、任意のセレクタ条件をブラケット内に記述する記法です。JavaScriptで付与するクラスと組み合わせて使うことが多いです。
<div class="[&.is-active]:bg-blue-500">...</div>groupバリアント
親要素にgroupクラスを付与することで、子要素のスタイルを親の状態に連動させられます。group-[.is-active]のように任意のクラスと組み合わせることもできます。
<div class="group [&.is-active]:bg-gray-100">
<span class="group-[.is-active]:text-white">テキスト</span>
</div>カスタムバリアント
tailwind.config.jsでカスタムバリアントを定義しておくことで、プロジェクト固有の状態をバリアントとして扱えるようになります。クラスの統一管理に役立ちます。
// tailwind.config.js
const plugin = require('tailwindcss/plugin');
module.exports = {
plugins: [
plugin(function ({ addVariant }) {
addVariant('active-state', '&.is-active');
}),
],
};<div class="active-state:bg-blue-500">...</div>Data Attributes(データ属性)を利用した記法
data-*属性の値に応じてスタイルを切り替えられます。状態管理をHTMLの属性ベースで行いたい場合に有効です。
<div data-state="open" class="data-[state=open]:block data-[state=closed]:hidden">
コンテンツ
</div>ARIAバリアントを利用した記法
WAI-ARIAのアクセシビリティ属性に連動したスタイリングが可能です。アクセシブルなUIを構築しながらスタイルも管理できます。
<button aria-expanded="true" class="aria-expanded:bg-blue-500">
メニュー
</button>Peerバリアントを利用した記法
兄弟要素の状態に基づいてスタイルを変化させます。フォームのバリデーション表示など、要素間の状態連携に活用できます。
<input type="checkbox" class="peer" />
<span class="peer-checked:text-blue-500">チェック時に色が変わる</span>WordPress
必須プラグイン構成
大規模サイトの運用を見据えて、以下のプラグインを導入しました。
プラグイン | 用途 |
|---|---|
Contact Form 7(CF7) | お問い合わせフォームの作成 |
CF7 Google Sheet Connector | フォーム送信データのスプレッドシート連携 |
CF7 Conditional Fields | フォームの条件分岐表示 |
Contact Form 7 Multi-Step Forms Pro | マルチステップフォームの実装 |
Flamingo | CF7の送信データをWordPress上に保存 |
WP Mail SMTP | メール送信の安定化 |
Custom Post Type UI(CPTUI) | カスタム投稿タイプ・タクソノミーの管理 |
ショートコードとtemplate-partsの有効活用
コンテンツの管理を運用者に委ねる場合、ショートコードを活用することで、PHPの知識がなくてもエディタ上から柔軟にコンテンツを配置できる環境を整えられます。また、template-partsを使ってテンプレートを分割しておくことで、コードの可読性と保守性を高めることができます。運用者が使いやすい環境を設計することも、開発者の重要な責務のひとつです。
課題
今回はNode.jsを使用し、distに書き出された静的ファイルをWordPress用に成形した上で、手動でWordPressへ流し込む手法をとっていました。しかし手動での作業であるためミスが発生しやすく、運用コストの面でも課題が残ります。
この流れをどのように自動化するかが今後の鍵になると感じています。現時点ではWordPress MCPがどの程度有用かは未知数ですが、デプロイフローの自動化は優先度の高い改善項目として引き続き検討していきたいと思います。
まとめ
大規模なWebサイト開発では、実装の技術的な精度だけでなく、チームでの運用を見据えた設計判断が求められます。コンポーネントの粒度管理、TailwindCSSの記法の正確な理解、WordPressプラグインの選定と運用設計、それぞれの領域で「後から整理できる状態を保つ」という意識が、プロジェクトの安定につながると感じました。