最近流行りのAstroフレームワークで、WordPressの静的Headless化がかなりお手軽にできたのでまとめてみました。
開発環境
- Astro 2.0
- WordPress 6.1.1
- Local
- node 18.12.1
- Mac OS 13.2(Ventura)
- Visual Studio Code(Astroプラグイン入り)
Astroとは?
Astroは、コンテンツにフォーカスした高速なWebサイトを構築するためのオールインワンWebフレームワークです。
(公式ドキュメントより)
LocalでWordPressを構築
まずLocalを使って、ローカル環境にWordPressを構築します。
- サイト名
- Astro Blog(お好みで)
- サイトドメイン
- astro-blog.local
WordPressの設定
WP AdminでWordPressのダッシュボードを立ち上げ、いくつかの設定を行います。
サイトアドレスを、Astro上の構造に合わせてサブディレクトリを足します(Astroでもサイト直下に展開する場合は、WordPressアドレスと同じでかまいません)。
ここでは、/blog
を追加しました。
その他の設定は、通常のWordPressと同じくお好みで。
WordPressテーマを適用
最終的にフロントエンド側はAstroで構築するので、テーマはなんでも良いのですが、スタイリングしやすい文書構造だったり、機能的なブロックエディタを持つテーマを選択すると良いと思います。
ここでは、シンプルで使いやすい「Arkhe」テーマをインストールして適用しました。
テーマをインストールしたら、テスト用にいくつか記事を作成して公開しておきます。
公開するときのURLパーマリンクが、AstroでHeadless化したときのファイル名になるため、英数字で構成しておきましょう。
ひとまずWordPress側は一旦完了です。Localを起動したまま、Astroの構築に移ります。
Astroをインストールする
Astroは日本語のドキュメントが充実しているので、迷ったらドキュメントを見ましょう。
まず、Localで構築したWordPressブログのフォルダー(以下astro-blog)にアクセスできるようにします。
(Localのメニュー[Go to site folder]でフォルダーが開きます)
Macの場合、
[ユーザー] > Local Sites > [構築したWordPressのフォルダー]
にあります。
次に、ターミナルを開き、「astro-blog」に移動し、以下のコマンドでAstroをインストールします。
npm create astro@latest
いくつか質問されるので、以下を参考に入力・選択してください。
Where should we create your new project?
Astroがインストールされるフォルダ名を入力します(後述しますが、最終的にフォルダから外に出すのでなんでも良いです)。astro
と入力します。
How would you like to start your new project?
Astroに慣れている人ならどれでも良いですが、ここではInclude sample files
を選択します。
Install dependencies?
お好みで。
Initialize a new git repository?
gitを使うかどうか。お好みで。
Do you plan to write TypeScript?
TypeScriptを使うかどうか。お好みで。
How strict should TypeScript be?
お好みで。
問題なければ、「astro」フォルダーの中にAstro一式が展開されていると思います。
astro-blog/
├── app
├── astro
│ ├── astro.config.mjs
│ ├── node_modules
│ ├── package.json
│ ├── public
│ ├── README.md
│ ├── src
│ └── tsconfig.json
├── conf
└── logs
次に、せっかく「astro」フォルダーにまとまっていますが、中のファイルを全て選択し、「astro-blog」直下に移動して、「astro」フォルダーは削除します。
(AstroからWordPress関連のファイルにアクセスするため)
astro-blog/
├── app
├── astro.config.mjs
├── conf
├── logs
├── node_modules
├── package.json
├── public
├── README.md
├── src
└── tsconfig.json
ここからVisual Studio Codeでコーディングしていきます。
事前にAstroプラグインをインストールしておきましょう。
エディタを立ち上げて、「astro-blog」を開き、
npm run dev
を実行して、Astroのサンプルページが立ち上がることを確認しましょう。
AstroとWordPressをつなげる
一旦npm run dev
を停止し、「astro-blog」直下に.envファイルを作成し、以下のようにWordPress Rest APIのURLを記述しておきます。
PUBLIC_API_URL = http://astro-blog.local/wp-json/wp/v2/
(http://astro-blog.local
の部分は、Localで作成したWordPressのURLになります)
次に、src/pages/index.astro
を開き、コードをいくつか追加します。
---
import Layout from '../layouts/Layout.astro'
import Card from '../components/Card.astro'
+ const res = await fetch(`${import.meta.env.PUBLIC_API_URL}posts`);
+ const posts = await res.json();
---
<Layout title="Welcome to Astro.">
<main>
<h1>Welcome to <span class="text-gradient">Astro</span></h1>
+ {
+ posts.map((post:any) => (
+ <p><a href={`/blog/${post.slug}`} set:html={post.title.rendered} /></p>
+ ))
+ }
<p class="instructions">
To get started, open the directory <code>src/pages</code> in your project.<br />
<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
</p>
// 以下略
再びnpm run devを実行すると、先ほどのAstroのサンプルページにWordPressで作成したページのタイトルがリンクとして追加されていると思います。
このままだとまだリンク先が存在しないので、各ページを構築していきます。
src/pages/blog/[slug].astro
ファイルを作成します。
src/
├─ pages
│ ├── blog
│ │ └─ [slug].astro
│ └─ index.astro
[slug].astro
ファイルに以下の記述をします。
---
import Layout from '../../layouts/Layout.astro'
const { slug } = Astro.params;
const res = await fetch(`${import.meta.env.PUBLIC_API_URL}posts?_embed&slug=${slug}`);
const [post] = await res.json();
const renderedContent = post.content.rendered;
export async function getStaticPaths() {
const data = await fetch(`${import.meta.env.PUBLIC_API_URL}posts`);
const posts = await data.json();
return posts.map((post:any) => ({
params: { slug: post.slug },
props: { post: post },
}));
}
---
<Layout title={post.title.rendered}>
<a href="/">Astro Blog</a>
<h1 set:html={post.title.rendered} />
<Fragment set:html={renderedContent} />
</Layout>
ちなみにこのへんの情報もすべて公式ドキュメントにも載っています。
[slug].astro
のコードを記述したら、先ほどのトップページのリンクから各ページにアクセスしてみましょう。
WordPressで作成したページがAstroの静的HTMLとして構築されています。
しかし、WordPressから持ってきたのはHTML構造だけなので、Astroで少しスタイリングを行います。
Astroでページをスタイリングする
今回WordPressには、「Arkhe」テーマを適用しているので、このテーマを活かしたスタイリングを行います。
---
import Layout from '../../layouts/Layout.astro'
+ import '../../../app/public/wp-includes/css/dist/block-library/style.min.css'
+ import '../../../app/public/wp-content/themes/arkhe/dist/css/main.css'
const { slug } = Astro.params;
const res = await fetch(`${import.meta.env.PUBLIC_API_URL}posts?_embed&slug=${slug}`);
const [post] = await res.json();
const renderedContent = post.content.rendered;
export async function getStaticPaths() {
const data = await fetch(`${import.meta.env.PUBLIC_API_URL}posts`)
const posts = await data.json();
return posts.map((post:any) => ({
params: { slug: post.slug },
props: { post: post },
}));
}
---
<Layout title={post.title.rendered}>
+ <div class="l-content__body l-container">
+ <a href="/">Astro Blog</a>
+
+ <main class="l-main">
+ <article class="l-main__body">
+ <h1 class="c-pageTitle__main" set:html={post.title.rendered} />
+ <div class="c-postContent">
+ <Fragment set:html={renderedContent} />
+ </div>
+ </article>
+ </main>
+ </div>
</Layout>
Local内にあるWordPressのblock-libraryのCSSと、「Arkhe」テーマのメインCSSを直接importしています。
これによって、WordPress側でテーマのアップデートによってCSSの変更があった場合も、Astro側に自動的に適用されます。
そして、<Layout title={post.title.rendered}>
内の文書構造を、「Arkhe」テーマで生成される文書構造と合わせます(最小限のclassのみ)。
ここまで変更したら、もう一度devでビルドされたページを見ると、
ほぼWordPress上と同じような見た目にスタイリングできました。
(実際はインラインで生成されるstyleなどもあるため、WordPress上とは異なる場合もあります)
Localのリンクを修正する
あともう少しだけ修正です。
見た目はほぼ再現できているように見えますが、ページ上の画像はLocalで生成された絶対パスのままになっています。
(例:http://astro-blog.local/wp-content/uploads/2023/02/hoge.png)
このままだとHeadless化で公開できないので、すべての画像をWordPressからAstro側にコピーすることにします。
手動でやるととても面倒なので、NPMスクリプトに任せましょう。
事前準備として、fs-extra
をインストールしておきます。
npm install fs-extra
fs-extra
をインストールしたら、package.jsonに、WordPressでアップロードした画像が入っているフォルダーを、Astroのpublicフォルダーにコピーするスクリプトを追加します。
"scripts": {
+ "copy": "node -e \"require('fs-extra').copySync('./app/public/wp-content/uploads', './public/wp-content/uploads')\"",
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
これで、
npm run copy
を実行すると、WordPressの画像フォルダーがAstro用にコピーされます。
ついでに、devとbuildしたときに最初にcopyが実行されるようにしておきます。
"scripts": {
"copy": "node -e \"require('fs-extra').copySync('./app/public/wp-content/uploads', './public/wp-content/uploads')\"",
"dev": "npm run copy && astro dev",
"build": "npm run copy && astro build",
"preview": "astro preview",
"astro": "astro"
},
最後に、[slug].astro
ファイルで、WordPressのコンテンツを流し込むときに、正規表現ですべてのhttp://astro-blog.local
を置換(削除)して、絶対パスをルートパスに変更します。
const renderedContent = post.content.rendered.replace(/http:\/\/astro-blog.local/g, '');
これにより、
src="http://astro-blog.local/wp-content/uploads/2023/02/hoge.jpeg"
みたいなコードが
src="/wp-content/uploads/2023/02/hoge.jpeg"
に置き換わります。
(サイト内リンクのhrefなども同様)
最後に、
npm run build
をすると、distフォルダーに静的HTMLファイル一式が出力されるので、サーバーにアップロードすれば完成です。
最終的にはCSSやJSに諸々の調整が必要だと思いますが、このように、Astroフレームワークを使うことで、ローカル環境だけでWordPressの静的Headless化がお手軽に行えるので、試してみてください。
おしまい。