稼働中のWordPressをGridsomeで構築してみる
背景
WordPress で 10 年以上運用しているブログをどうにかしたいと思い始める。
- パーマリンクを変えたくない
- WordPress つらくなってきている
v5.0.0 の標準エディタGutenbergの具合がよろしくない - フロント実装(WordPress テーマ)を Vue.js で構築している
移行先もスムーズに Vue.js が使えると良い - 完全に静的化する(Hugo など)すると記事データの管理が面倒そう
上記を踏まえて、記事管理のために CMS(WordPress)は残しつつ、移行の手間を掛けずに手軽に試せそうなGridsomeを試してみる。
Gridsome を使ってみる
React 製のGatsbyJSライクな Vue.js 製のGridsomeを使ってみる。
インストール
公式のドキュメントに沿って入れていく。
使用モジュールのバージョン:
@gridsome/source-wordpress
: v0.1.1gridsome
: v0.4.0
まずは「グローバルにインストールしろ」というのでひとまずインストールする。
npm install --global @gridsome/cli
データソースを WordPress にしたい。@gridsome/source-wordpress
が用意されているが、同梱されているみたいですので、下記を実行するだけで良い。
gridsome create my-gridsome-project wordpress
gridsome create
が完了すると、下記のようなファイルが展開される。
.
├── src
├── gridsome.config.js
├── node_modules
├── package.json
└── README.md
gridsome.config.js
まずは取得先の情報を設定する。
module.exports = {
plugins: [
{
use: '@gridsome/source-wordpress',
options: {
baseUrl: 'YOUR_WEBSITE_URL', // required
typeName: 'WordPress', // GraphQL schema name (Optional)
perPage: 100, // How many posts to load from server per request (Optional)
concurrent: 10, // How many requests to run simultaneously (Optional)
routes: {
post: '/:year/:month/:day/:slug', //adds route for "post" post type (Optional)
post_tag: '/tag/:slug', // adds route for "post_tag" post type (Optional)
},
},
},
],
};
plugins.options.baseUrl
の値を対象の WordPress の URL に書き換えてみる。もし、対象がない場合は、demo 用のhttps://demo.wp-api.org/
を指定しても良さそう。
実行
npm run develop // or build
Site running at: http://localhost:8080/
Explore GraphQL data at: http://localhost:8080/___explore
http://localhost:8080/
にアクセスすると Gridsome で構築したページが見られるようになる。
ライブリロードされるので、そのまま Vue SFC を修正して開発に取り掛かることができる。
http://localhost:8080/___explore
の方は、GraphQL のクエリをテストしたいときに使えるプレイグラウンドへアクセスできる。
プロジェクト内で使用可能な GraphQL コレクションの一覧も見ることができる。
GraphQL
ページ固有のデータを取得する
query Page {
wordPressPage(path: "/pages/about") {
title
content
}
}
path
に指定する値が、単純にabout
ではなく/pages/
を挟むことに注意。
カテゴリの記事一覧を取得する
query {
allWordPressCategory {
edges {
node {
count
title
slug
}
}
}
}
perPage
のデフォルト値があるため、この指定だと全件は取得できない。
Vue SFC
<template>
<Layout>
<h1 v-html="$page.wordPressPostTag.title" />
</Layout>
</template>
<page-query>
query PostTag ($path: String!) {
wordPressPostTag (path: $path) {
title
}
}
</page-query>
$page.クエリ名
でデータにアクセスができる。クエリによってデータ構造が違うので注意。
WordPress(WP-API)を調整
私が対象としていた WordPress は下記のようなパーマリンクになっていた。
/%year%%monthnum%%day%%hour%%minute%%second%.html
また、個別記事に関しては slug 設定がない状態だった。
現状、Gridsome で使用できるルートは、:year
, :month
,:day
,:slug
の組み合わせでしか設定できない。(post_tag
も同様)
routes: {
post: '/:year/:month/:day/:slug', //adds route for "post" post type (Optional)
post_tag: '/tag/:slug' // adds route for "post_tag" post type (Optional)
}
WP-API が吐き出すslug
を調整して、既存のパーマリンクに寄せていく。
WP-API の拡張
rest_prepare_post
という hook を使い下記のように API を書き換えてしまう。
add_filter('rest_prepare_post', 'adjusted_api_data');
public function adjusted_api_data($response, $post, $request) {
$link = basename($response->data['link']);
$response->data['link'] = '/' . $link;
$response->data['slug'] = $link;
return $response;
}
補足:
WP-API のlink
は、NodeInterface
内のpath
になる。
edges {
node {
id
title
slug
path
}
}
これで Gridsome が出力した個別記事にも既存パーマリンクと同じ状態でアクセスができるようになった。
最後に
始めは「えっ、こんなに簡単に…!?」という感想だったが、開発中につき機能がまだまだ足りず、かゆいところに手が届かない状態であった。
(GatsbyJS で当たり前にある機能が足りないため、本番稼働させるには厳しいと感じた)
メジャーバージョンアップに期待。