Help us understand the problem. What is going on with this article?

Vue.js + Wordpressで作ってみる

WordPress(以下WP)はまだまだ現役だけど、もっさり感がねぇ。
なので、WPは運用者の更新用にして、実際のビュー部分はVue.js(Nuxt.js)でやろうって話です。

WPの準備

インストールは割愛
最近のWPはデフォルトでWP REST APIが入っているので、既存の投稿を使う場合は何もしなくていいです。
カスタムフィールドを追加する場合は、Advanced Custom FieldならAPI化が簡単らしいです。

カスタム投稿をAPI化する

カスタム投稿追加とAPI化のコードをfunctions.phpに追加する。
https://ドメイン/wp/ にWPがインストールされているとして、https://ドメイン/wp/wp-json/wp/v2/samplepost でjson返します。

functions.php
function create_post_type() {
    $supports = [ 
      'title',
      'editor',
      'author',
      'thumbnail', 
      'excerpt', 
      'custom-fields',
    ];
    register_post_type( 'samplepost', 
      array(
        // 以下は適当に
        'label' => 'サンプルポスト',  
        'public' => true,  
        'has_archive' => false,  
        'menu_position' => 7, 
        'supports' => $supports, 
        'show_in_rest' => true,
        'rest_base' => 'samplepost'
      ) 
    );  
  }
  add_action( 'init', 'create_post_type' );

  function slug_register_cutomposts() {
      register_rest_field( 'samplepost', //デフォルトの投稿のカスタムフィールドをAPI化する場合はpostsに
          'data',
          array(
              'get_callback'  => function(  $object, $field_name, $request  ) {
                $meta_fields = array( //ここにAPIで呼び出すカスタムフィールドを列挙
                    'Customfield01',
                    'Customfield02',
                    'Customfield03',
                );
                $meta = array();
                foreach ( $meta_fields as $field ) {
                  $meta[ $field ] = get_post_meta( $object[ 'id' ], $field, true );
                }
                return $meta;
              },
              'update_callback' => null,
              'schema'          => null,
          )
      );      
  }
  add_action( 'rest_api_init', 'slug_register_cutomposts' );

カスタムフィールドは適当に準備してください。

Nuxt.jsの準備

インストール

vueとvue-cliはインストール済みとして。
$ vue init nuxt-community/starter-template projName
$ npm install
$ npm run dev

http://localhost:3000/ で以下が表示できていればOK
Screen Shot 2019-05-09 at 13.47.00.png

ページの作成

pagesフォルダにこんな感じでフォルダとvueファイルを作っていきます。
newsはデフォルトのpostsに対応しています。Vueでは、アンダースコアをつけることで動的なルーティングを定義できます。
news/index.vue、samplepost/index.vue がそれぞれのアーカイブページに対応しています。

pages
├── index.vue
├── news
│   ├── _id.vue
│   └── index.vue
└── samplepost
    ├── _id.vue
    └── index.vue

ページを作っていきます。WPの投稿とも紐づけます。
axiosを使用します。

$ npm install --save-dev axios

pages/news/index.vue
<template>
<div>
    <PostList :posts="posts" />
</div>
</template>

<script>
import PostList from '~/components/posts/PostList.vue'
import wp from '~/wp'

export default {
    asyncData ({ params }) {
        return wp.posts()
    },
    components: {
        PostList,
    }
}
</script>
components/posts/PostList.vue
<template>
  <ul>
    <li v-for="post in posts" :key="post.id">
        <article>
          <a v-bind:href="'/news/' + post.id">
            <h2 class="subtitle">{{ post.title.rendered }}</h2>
            <div class="info" v-html="post.excerpt.rendered"></div>
          </a>
        </article>
    </li>
  </ul>
</template>

<script>

export default {
  props: ['posts'],
}
</script>
wp.js
import axios from 'axios'

class WpApi {
  constructor (siteurl) {
    this.apiBase = `${siteurl}/wp-json`
  }
  async posts () {
    try {
          const json = await axios.get(`${this.apiBase}/wp/v2/posts`, {
              params: {
                  page: 1,
                  per_page: 5
              }
          });
          return { posts: json.data };
      }
      catch (e) {
          return { error: e };
      }
  }
  async samplepost () {
    try {
          const json = await axios.get(`${this.apiBase}/wp/v2/samplepost`, {
              params: {
                  page: 1,
                  per_page: 5
              }
          });
          return { samplepost: json.data };
      }
      catch (e) {
          return { error: e };
      }
  } 
}
const wp = new WpApi('https://ドメイン/wp/')
export default wp
pages/news/_id.vue
<template>
  <div>
      <h2>{{ post.id }}</h2>
      <h3 class="subtitle">{{ post.title.rendered }}</h3>
      <div class="info" v-html="post.content.rendered"></div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  async asyncData ({ params }) {
    //id指定で個別の記事なんで直接書いた
    //WPのパーマリンク設定によってはgetするときのurlが違うかもですので、適宜変更してください。
    const { data: post } = await axios.get(`https://ドメイン/wp/wp-json/wp/v2/posts/${params.id}`)
    return {
      post
    }
  }
};
</script>

サイト公開

nuxt.config.js
//ここでもaxios呼んでおいてください
const axios = require('axios')
const apiUrl = 'https://ドメイン'


中略// nuxt generateの変更


  generate: {
    interval: 1000, //インターバルないとサーバーが落ちます。
    routes () {
      return Promise.all([
        axios.get(`${apiUrl}/wp-json/wp/v2/posts`),
      ]).then((data) => {
        const posts = data[0]
        return posts.data.map((post) => {
          return {
            route: '/news/' + post.id,
            payload: post
          }
        })
      })
    }
  },


以下略

npm run generate でdistフォルダが作成されます。中身を丸っとドメインのルートに入れれば、ページが公開されます。

(未対応)WP更新で自動反映

このままだと、WP側で更新しても、サイトには反映されません。
generateして静的ファイルを生成しなおす必要があります。
そのため、WP更新 → Nuxt generate → 生成ファイルのアップロード を自動化できるとみんなハッピーですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした