Astro と Tailwind CSS でこの Blog をリニューアルしました

Blog をリニューアルするにあたり、今までの Movable Type でテンプレート作って、という手法から、Movable Type は JSON データの書き出しだけ担当させて、フロントエンドは Astro と Tailwind CSS で開発する形に切り替えたので、その概要を簡単にメモ。

この Blog は立ち上げ当初から Movable Type で運用していますが、MT タグを書いて、テンプレートを作って、という一般的な運用っていうんですかね? それをやめて、Movable Type は記事データの管理と JSON を書き出す役割だけにして、フロントエンドは Astro + Tailwind CSS でリニューアルしました。

面倒だったのでデザインは大きく変えず、ぱっと見はリニューアルしたのがわかりにくい感じになっていますが、Movable Type とフロントエンドを完全に分離することで、フロントエンド側の開発やメンテナンスは Git ワークフローに組み込めるようになり、私的にはとても快適になりました。

で、『リニューアルしました』 のご報告だけだと、冒頭の数行で終わってしまうので、下記に今回どんな感じで Astro や Tailwind CSS を使ったのかについて、備忘録として書いておこうと思います。

環境構築メモ

まず最初に、Astro をインストールします。

npm create astro@latest

sitemap.xml の生成に @astrojs/sitemap と RSS フィードの生成に @astrojs/rss をそれぞれ使用したいので、インストールしておきます。

@astrojs/sitemap については、npx コマンドを使用することで、astro.config.mjsintegrations プロパティが自動的に追加されます。

npx astro add sitemap
npm install @astrojs/rss

Tailwind CSS と PostCSS とか

astro.config の修正は後でまとめてやることにして、次に @astrojs/tailwind をインストールします。これも質問に答えていくだけで終わり。

npx astro add tailwind

今回は、postcss を併用したいのと、Blog 記事の本文のスタイルのうち、基本的な部分は、@tailwindcss/typography にお任せしたいので、それらをまとめてインストール。

npm install -D @tailwindcss/typography postcss postcss-import autoprefixer cssnano prettier prettier-plugin-tailwindcss

tailwind.config.cjs をエディタで開いて、下記のように設定を追加し、@tailwindcss/typography を使えるようにしておきます。

/** @type {import('tailwindcss').Config} */
export default {
  content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
  theme: {},
  plugins: [require('@tailwindcss/typography'),],
}

PostCSS 関連の設定

続けて postcss.config.cjs を下記のように設定します。

CSS を書いていく際に、ネスト記法を使いたいので、Tailwind CSS 標準の、tailwindcss/nesting を有効にしますが、この設定は必ず tailwindcss の前に書く必要があるので注意しましょう。

// postcss.config.cjs
module.exports = {
  plugins: {
    'postcss-import': {},
    'tailwindcss/nesting': {},
    tailwindcss: {},
    autoprefixer: {},
    cssnano: {
        preset: [
            'default',
            {
                minifyFontValues: {
                    removeQuotes: false,
                },
            },
        ],
    },
  }
}

Web フォントを使いたい場合

もし Web フォントを使用したい場合は、Fontsource を使用すると、Astro があとはよしなにやってくれますのでとても便利。

例えば、Noto Sans JP が使いたい場合は、Fontsource からインストールします。

npm install @fontsource-variable/noto-sans-jp

その後、layouts/Layout.astro でフォントを読み込みます。

import '@fontsource-variable/noto-sans-jp';

あとは、Tailwind CSS から使いやすいように、ユーティリティクラスの設定をしておきます。下記の例だと、font-body という class を指定すれば、そこに設定した font-family が適用されます。

/** @type {import('tailwindcss').Config} */
export default {
  content: [...],
  theme: {
    extend: {
      fontFamily: {
        'body': ['"Noto Sans JP Variable"', 'sans-serif'],
      },
    },
  },
  plugins: [...],
}

Prettier の設定

prettier.config.mjs は下記のように。

// prettier.config.mjs
export default {
  plugins: ['prettier-plugin-tailwindcss'],
}

astro.config の内容

最後に、astro.config.mjs を仕上げます。

// astro.config.mjs
import { defineConfig } from 'astro/config';
import tailwind from "@astrojs/tailwind";
import sitemap from "@astrojs/sitemap";

export default defineConfig({
  site: 'https://hyper-text.org',
  outDir: '../htdocs',
  build: {
    assets: 'static/css',
    inlineStylesheets: 'never',
  },
  compressHTML: true,
  vite: {
    build: {
      minify: false,
    },
  },
  integrations: [
    tailwind(),
    sitemap(
      {
        filter: (page) =>
          page !== 'https://hyper-text.org/err/403/' &&
          page !== 'https://hyper-text.org/err/404/' &&
          page !== 'https://hyper-text.org/err/500/',
      }
    )
  ],
});

defineConfig で設定している、site は、@astrojs/sitemap を使用する際は必須なので注意しましょう。

outDir の設定は任意です。デフォルトだとプロジェクトのルートディレクトリに dist ディレクトリが作られ、ここにビルド済みファイルが出力されます。

ちなみに、outDir をデフォルトから変更したとき、このディレクトリに manifest_****.mjs みたいな、恐らくビルドプロセス中に必要な情報をまとめた JavaScript ファイルが生成されるようです (デフォルトの dist ディレクトリだと作られない・・・謎)。

少なくとも Static にファイルを書き出している場合、このファイルはサーバにアップロード不要だと思いますので、その辺は注意が必要かも。このファイルに関する情報が公式ドキュメントを見てもどこにも書いていなくてよくわからないんですが、知ってる人がいたら教えてほしい。

話を戻して、ビルド時のオプションは、build 内に記述しますが、今回は、build.assetsbuild.inlineStylesheets を設定しています。

build.assets は、バンドルされた JavaScript や CSS など、Astro が生成したアセットを書き出すディレクトリを指定します。要するに、デフォルトだと _astro ディレクトリにまとめられているものをどこに書き出すかという設定です。

今回は Astro が書き出すアセットは CSS のみになる前提だったので、static/css として、CSS ファイルがここに書き出されるようにしました。

build.inlineStylesheets は、CSS を外部ファイルにするか、style 要素でインライン記述するかをコントロールします。

デフォルトの auto だと、4kB 以下 (この値は build.assetsInlineLimit で変更可能) の場合はインラインで、それ以上だと外部ファイルで、といった具合に自動でうまいことやってくれますが、今回は never を指定してインライン記述をしない、つまり常に外部ファイルとして書き出すようにします。

@astrojs/sitemap の設定

今回は、所謂、カスタムエラーページも Astro で作ったので、そのままだと、@astrojs/sitemap で生成される sitemap.xml に、これらエラーページも含まれてしまいます。

そこで、sitemap() の設定内に filter 関数を追加し、sitemap.xml に入って欲しくない URL をフィルターしています。

CSS の記述

Tailwind CSS を最も簡単に使用するなら、HTML にユーティリティクラスをガンガン書いていけばいいだけですが、今回はそうせずに、外部スタイルシートを記述していきます。

これは、当 Blog が長いこと運用されているということもあって、記事内で使っているスタイルとか、色々と過去に書かれた CSS ファイルがすでに存在していたので、それらをなるべく簡単に再利用しながら書きたかったというのが理由としてはあります。

また、Astro で CSS を書く場合、各ページやコンポーネントに style 要素を使用して直接書いてしまうケースが多いと思いますが、これも今回は避けたかったので、外部スタイルシートにまとめることにしました。

まず src ディレクトリ内に styles ディレクトリを作り、styles.css を作成して、Tailwind CSS ディレクティブを追加します。

@tailwind base;
@tailwind components;
@tailwind utilities;

そうしたら、layouts/Layout.astrostyles.css を読み込んであげれば準備完了。

---
import "../styles/styles.css";
...略...
---

あとは、@apply を使用して、下記のように書いていけば楽です。

@layer components {
  header {
    @apply bg-neutral-800 text-neutral-50;

    .block-header {
      @apply relative max-w-7xl mx-auto flex justify-between items-center gap-0 h-14 px-4;
    }
    ...略...
  }
}

@tailwindcss/typography を入れているので、記事本文については、例えば下記のように指定するだけでスタイルが当たります。

.entry-body {
  @apply prose prose-a:underline hover:prose-a:text-red-700 max-w-5xl mx-auto px-4 transition-colors;
}

新規の Blog とかなら、これだけで終わっちゃいますね。この Blog の場合は、前述の通り、過去の遺産が多いので、ベースのスタイルは @tailwindcss/typography にお任せしつつも、記事内で使っている class に対応するスタイルは別途書きましたけども。

ちなみに、メディアクエリも、Tailwind CSS の theme から取得できます。

@media (min-width: theme('screens.sm')) {
...略...
}

また、環境構築時に postcss-import を入れていますので、下記のように、別の CSS ファイルを読み込んでまとめることもできます。

@tailwind base;
@tailwind components;
@tailwind utilities;
@import "./article-body.css";

.css ファイルで Tailwind CSS ディレクティブを記述した場合の警告

余談ですが、VS Code (Visual Studio Code) を使用している場合、特に何も設定しないと、.css ファイル内で、Tailwind CSS ディレクティブ、例えば @tailwind base; とか @apply とか書いたりしたとき、警告表示 (CSS の文法が間違ってますよって親切に教えてくれるやつですね) が邪魔くさいことがあると思います。

警告を消す方法はいくつかありますが、VS Code で Tailwind CSS をよく使う人は、恐らく Tailwind CSS IntelliSense を入れていると思いますので、その場合は、VS Code の設定から、files.associations を探して、"*.css": "tailwindcss" を追加しましょう。

VS Code の設定例

これ、Tailwind CSS IntelliSense の説明にきちんと書いてあるんですが、結構忘れがち。

Movable Type 側で、JSON を用途に合わせて出力する

記事データは Movable Type から JSON で取得しますが、Data API を使うと細かい部分で融通が利かなかったりするので、普通にテンプレートを書いて、必要な形式の JSON を吐き出します。

結局 MT タグとかテンプレート書いてるじゃねーか、と言われてしまえばそうなんですけども、JSON データは今後リニューアルするときでもほぼそのまま使い回しができるので、面倒なのは初回だけです。

JSON が準備できたらあとは開発していくだけ。


ということで、簡単にですがまとめてみました。

この Astro と Tailwind CSS の組み合わせについては、ここ最近、お仕事で HTML や CSS を書くときも採用している組み合わせですが、特に CSS を書くのがめちゃくちゃ楽なので重宝しています。

あと、課題はデプロイの自動化ってところで、Vercel とか、Netlify を使うなら、自動化は簡単なんですけども、自前のサーバでやろうとすると結構面倒。

結果、今のところ、記事を公開したら、サーバに SSH して、git pullnpm run build してみたいな不毛な作業をしないといけない状態になっています。なので、時間をみつけて早いところここを自動化したい。

記事をここまで御覧頂きありがとうございます。
この記事が気に入ったらサポートしてみませんか?