heishi1HUMANITY article

wordpress×Nuxt.jsでnpm run generateしたい。その上、ホスティングはオンプレでやりたい。

最終更新 : 2022-08-06

そんなことありますよね?ない?

そもそもフロントエンドの人間として、wordpressって使いたくないじゃないですか。僕だけですか?だから僕はJAMStackを推してるんですけど。本当はmicroCMSとかヘッドレスCMS使いたい、でも「wordpressじゃなきゃヤダッ!」って言われることもままあるかと思われます。あと、ポリシーの関係で外部にデータおけないとかあると思うんですよ。それをうまいことやっていけないかなって考えてみた話です。あ、Docker使っていきます。

今回使うソースコード類はgithub上に載せてあります。

docker-compose.ymlを見ていく

docker-compose.ymlはこんな感じになります。

version'3.1'

services: 
  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - ./wordpress:/var/www/html
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - ./db:/var/lib/mysql
  nuxt:
    image: node:alpine
    restart: always
    volumes:
      - ./nuxt:/home/node
    tty: true
    working_dir: /home/node
    command: [node, webhook.js]
  nginx:
    image: nginx:alpine
    restart: always
    ports: 
      - 8000:80
    volumes: 
      - ./nuxt/dist:/usr/share/nginx/html

volumes:
  wordpress:
  db:
  nuxt:


wordpress,dbはwordpress関係です。docker hubに書いてあるやつそのままです。wordpressにはlocalhost:8080で繋がります。
nuxtはnodeイメージを使って、nuxtファイルを扱うコンテナです。./nuxtがマウントされてます。wordpressから変更のwebhookを受けてビルドする役割もあります。
nginxはサーバです。./nuxt/distをマウントして配信してます。localhost:8000で繋がります。


./nuxtのファイルを見ていく

この中はnuxtのプロジェクトファイルが入ってます。今回はwordpressのREST apiから投稿データを取得して、それぞれの投稿内容を個別のページで表示します。スタイルとか特につけてないです。

index.vue

<template>
  <div id="container">
    <router-link v-for="d in data" :key="d.id" :to="`/p/${d.id}`" class="link">{{ d.title.rendered }}</router-link>
  </div>
</template>

<script>
export default {
  asyncDataasync() => {
    const data = await fetch("http://wordpress/wp-json/wp/v2/posts").then(json => json.json());
    return {data: data};
  }
};
</script>

<style scoped>
  #container {
    display: flex;
    flex-direction: column;
    padding24px;
  }
</style>


/p/_id.vue

<template>
  <div id="container">
    <div v-html="data.content.rendered"></div>
  </div>
</template>

<script>
export default {
  asyncDataasync(c) => {
    const data = await fetch(`http://wordpress/wp-json/wp/v2/posts/${c.params.id}`).then(res => res.json());
    return {data: data};
  }
};
</script>

<style scoped>
  #container {
    padding24px;
  }
</style>


また、この中の「webhook.js」は80番ポートで待ち構えて、postで通知が来たらexecで「npm run generate」を起動します。あんまりしっかり作ってないんで、連続でpostが来るとプロセス乱立します。

webhook.js

const express = require('express');
const app = express();
const { exec } = require('child_process')

app.post('/build'(req, res) => {
  console.log('build start');
  res.end();
  exec('npm run generate'(err, stdout, stderr) => {
    if (err) {
      console.log(`stderr: ${stderr}`);
      return;
    }
    console.log(`stdout: ${stdout}`);
  });
});

app.listen(80() => console.log('server is working at :80'));


wordpressを設定していく

wordpressのインストールは適当にやってください。REST apiを使うので「パーマリンク設定」を「基本」から変えておいてください。重要なのは、webhookを送ることです。どうやらプラグインにwebhook(てか、postでhttpリクエスト送るだけなんすけどね)を設定できるもの(こちら)がありますので、使っていきます。PHPなんて触りたくないので。とりあえずお使いのwordpressにインストール・有効化してください。

したらばセッティングです。プラグインのWP WebhooksからSettingsを押して設定画面に行きます。そこから更にSettingsを選択します。


ここで設定するのは「Activate "Send Data" Triggers」です。まあ、記事の追加・更新・削除あたりでビルドし直すのが良いでしょうから適当に選んで「Save all」してください。

次にWebhookのURLなどを設定していきます。「Send Data」から設定していきます。
「Webhook Name」は適当に、「Webhook URL」は「http://nuxt/build」にしてください。docker-composeで立てたコンテナ間の通信は、コンテナ名で名前解決してくれます。


これで追加したあと、「Refresh for Settings」をして、「Settings」から「Allow unsafe URLs」を有効にしてください。これしないとpostしてくれません。



これで設定は終了です。試しに投稿を一つ追加してみて、ビルドされるか確かめてください。

終わり

なんか、wordpressを使いたくない一心でやってますけど、まじでwordpress使いたくねぇんだよなぁ…(というと語弊があるけど、一番の狙いはPHP使いたくないってところです。JavaScriptで完結させたい)
あとは、wordpressの管理画面のアクセス制限つけたりすると、より良くなるんじゃないですかね?しらんけど。

コメント