この 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.mjs
に integrations
プロパティが自動的に追加されます。
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.assets
と build.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.astro
で styles.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"
を追加しましょう。
これ、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 pull
→ npm run build
してみたいな不毛な作業をしないといけない状態になっています。なので、時間をみつけて早いところここを自動化したい。