がもたらすの新たな可能性
CSS Nite LP64
Coder's High 20192019.10.19
Kite (KITERETZ inc.)Designer

Programmer

Ruby on Rails
WordPress
Core Contributor Contributor

KITEDirector

Manager

ReactContributor

Vue CLIContributor

FrascoDeveloper

ViewportScale
Developer

KITERETZ inc. CEO & Founder­ kite.koga¬ ixkaito® ixkaito

Ŷ ixkaito

Ʃ ixkaito

ŧ ixkaito

WockerDeveloper

BatheDeveloperおしゃぶり社長＝バブバブカイト

最近は Notion にハマっています！

権
利
権利の本

本

クリエイタのための著
作権トラブル
解決のバイブル！

現場でトラブルになりがちな権利の問題についてクリエイターとしてやってはいけないこと権利を侵害された時の具体的な対処法を、わかりやすくまとめたクリエイターのためのバイブル

著 大串 肇

北村 崇

木村 剛大

古賀 海人

齋木 弘樹

角田 綾佳

染谷 昌利

https://wocker.dev

Wocker でテスト環境を作成

wocker ~ $ wocker run --name cssnite

Wocker でテスト環境を作成

http://wocker.test/https://wocker.dev★ Star 463

テストコンテンツを自動注入

wocker ~ $ wocker theme-testテストコンテンツを自動注入

http://wocker.test/

Agenda① モダンなウェブ開発についての用語解説② 使用ツールの解説と採用理由③ デモによる体験④ 問題点と課題点
技術選定する際の参考になれば

What is

モダンなウェブ開発アーキテクチャ
A modern architecture —Create fast and secure sites and dynamic apps with JavaScript,APIs, and prerendered Markup, served without web servers.

What isJavaScript (クライアントサイド)
APIs
MarkupWhy• パフォーマンスがいい＝高速• セキュリティが高い• コストが低い• スケールしやすい• 開発の役割分担がしやすいWhat isフロントエンド (ヘッド) がない (レス)＝バックエンドのみの CMS

Why• GUI によるコンテンツ管理が可能• JAMstack アーキテクチャの API の部分を担えるWhat is

• CMS
• 全世界の3分の1以上のウェブサイトで(コンテンツマネージメントシステム)利用されている

Why• REST API がある• 成熟安定期• 使っている、あるいは使ったことがある• Gutenberg• 開発の自由度が高い＆プラグインが多い• ほとんどのレンタルサーバーでサポートされている(新エディタ、多機能で操作が直感的)(サーバーを借りずに無料から使えるサービス WordPress.com もある)

What is• Vue.js のフレームワーク (Vue.js + プリセット + 規約)• レンダリングモードを選べる
• SSR
• SPA
• 静的ファイルの生成(サーバーサイドレンダリング)(シングルページアプリケーション)(スタティックサイトジェネレーター)

Why• Vue.js のメリットを得られる• ベストプラクティスが詰まっている• 環境や用途に応じて利用できる• 規約によって開発に秩序が生まれる

Use Cases ofWordPress サイトのリニューアル(旧サイトの既存機能はそのまま使える)

WordPress サイトの静的化
JAMstack な構成で開発したいが、管理画面と REST API を作るのが手間な場合

×
もっともシンプルなサンプルを見ていきましょう
https://github.com/ixkaito/wp-nuxt

全体構成

API 通信

デプロイ

静的配信

💻
User

Nuxt.js プロジェクトの作成$ npx create-nuxt-app <project-name>or$ yarn create nuxt-app <project-name>Nuxt.js のディレクトリ構造

nuxt.config.js
Nuxt.js のカスタム設定を記述します。

layouts
アプリケーションのレイアウトを含みます。レイアウトはページの外観を変更するために使用されます（例えばサイドバーなど）。

pages
アプリケーションのビュー及びルーティングファイルを入れます。Nuxt.js フレー
ムワークはこのディレクトリ内のすべての .vue ファイルを読み込み、アプリケーションのルーターを作成します。

Nuxt.js のディレクトリ構造

components
Vue.js のコンポーネントファイルを入れます。

store
Vuex ストア のファイルを入れます。Vuex ストアは Nuxt.js に付属していますが、デフォルトでは無効になっています。このディレクトリに index.js ファイルを作成するとストアが有効になります。

コンポーネント
components/SiteHeader.vue<template><header><h1>WordPress + Nuxt.js</h1><nav><n-link to="/">Home</n-link><n-link to="/about/">About</n-link></nav></header></template><style scoped>
header {align-items: center;
display: flex;
justify-content: space-between;}</style>コンポーネント
layouts/default.vue<template><div><SiteHeader /><nuxt /></div></template><script>
import SiteHeader from '~/components/SiteHeader.vue'
export default {components: {SiteHeader}}</script>コンポーネント
pages/index.vue<template><div><p>Hello world!</p></div></template>コンポーネント

http://localhost:3000

WP REST API から固定ページを取得

WordPress のパーマリンク設定は投稿IDがおすすめ

WP REST API から固定ページを取得

http://wocker.test/wp-json/wp/v2/

WP REST API から固定ページを取得
nuxt.config.js
export default {...
axios: {baseURL: 'http://wocker.test/wp-json/wp/v2'},...
}

WP REST API から固定ページを取得
pages/about.vue<template><div><h2>{{ post.title.rendered }}</h2><div v-html="post.content.rendered"></div></div></template><script>
export default {async asyncData({ $axios }) {const { data } = await $axios.get('/pages/2')
return { post: data }}}</script>

WP REST API から固定ページを取得

http://localhost:3000/about

WP REST API から投稿一覧を取得
pages/index.vue<template>
<div>
<ul>
<li v-for="post in posts"><h2>{{ post.title.rendered }}</h2><div v-html="post.excerpt.rendered"></div>
</li>
</ul>
</div></template><script>
export default {async asyncData({ $axios }) {const { data } = await $axios.get('/posts')
return { posts: data }}}</script>

WP REST API から投稿一覧を取得

http://localhost:3000

アイキャッチ画像の表示
pages/index.vue<template>
<div>
<ul>
<li v-for="post in posts"><img v-if="post._embedded['wp:featuredmedia']":src="post._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url" alt="Post thumbnail"><h2>{{ post.title.rendered }}</h2><div v-html="post.excerpt.rendered"></div>
</li>
</ul>
</div></template><script>...
</script>アイキャッチ画像の表示
pages/index.vue<template>...
</template><script>
export default {async asyncData({ $axios }) {const { data } = await $axios.get('/posts?_embed')
return { posts: data }}}</script>アイキャッチ画像の表示

http://localhost:3000

静的ファイルの生成$ npm run generateor$ yarn generate静的ファイルの生成

Vuex ストア
store/index.js
export const state = () => ({posts: []})
export const mutations = {setPosts(state, posts) {state.posts = posts}}
export const actions = {async getPosts({ commit }) {const { data } = await this.$axios.get('/posts?_embed')commit('setPosts', data)}}

Vuex ストア
pages/index.vue<template>...
</template><script>
export default {async fetch({ store }) {await store.dispatch('getPosts')},
computed: {posts() {return this.$store.state.posts}}}</script>

WP REST API から動的に個別投稿ページを取得
pages/_id.vue<template><div><img v-if="post._embedded['wp:featuredmedia']":src="post._embedded['wp:featuredmedia'][0].media_details.sizes.full.source_url" alt="Post thumbnail"><h2>{{ post.title.rendered }}</h2><div v-html="post.content.rendered"></div></div></template><script>
export default {async asyncData({ $axios, params }) {const { data } = await $axios.get(`/posts/${params.id}?_embed`)
return { post: data }}}</script>

WP REST API から動的に個別投稿ページを取得.nuxt/router.js...
routes: [{path: "/about",
component: _4db849a2,
name: "about"}, {path: "/",component: _0e489418,name: "index"}, {path: "/:id",component: _9ff2b548,
name: "id"}],...

自動的に生成されるWP REST API から動的に個別投稿ページを取得
pages/index.vue<template>
<div>
<ul>
<li v-for="post in posts">...
<n-link :to="{name: 'id', params: { id: post.id } }">Read more</n-link>
</li>
</ul>
</div></template><script>...
</script>

WP REST API から動的に個別投稿ページを取得

http://localhost:3000

WP REST API から動的に個別投稿ページを取得

http://localhost:3000/1

WP REST API から動的に個別投稿ページを取得

動的なルーティングは、静的ファイル生成時に無視される

動的ルーティングの静的ファイル生成
nuxt.config.js
import axios from 'axios'
const apiUrl = process.env.API_URL || 'http://wocker.test/wp-json/wp/v2'
export default {...
axios: {baseURL: apiUrl},
generate: {routes: async () => {const { data } = await axios.get(`${apiUrl}/posts?_embed`)
return data.map(post => {return {route: `${post.id}`,
payload: post}})}
},
...
}

動的ルーティングの静的ファイル生成
pages/_id.vue<template>...
</template><script>
export default {async asyncData({ $axios, params, payload }) {if (payload) {return { post: payload }} else {const { data } = await $axios.get(`/posts/${params.id}?_embed`)
return { post: data }}}}</script>動的ルーティングの静的ファイル生成

Netlify へのデプロイ
nuxt.config.jsimport axios from 'axios'
const apiUrl = process.env.API_URL || 'http://wocker.test/wp-json/wp/v2'...

Netlify へ自動的にデプロイするためには、インターネット上に公開されている API にする必要がある
ここを変更する or
後述ビルドコマンドに API_URL という環境変数を渡す

Netlify へのデプロイ

GitHub などのリモートリポジトリに上げておくNetlify へのデプロイ

Netlify へのデプロイ

Netlify へのデプロイ

Netlify へのデプロイ

環境変数 API_URL を指定する場合は下記のようにする：
API_URL=https://example.com/wp-json/wp/v2 npm run generateWordPress の新規投稿や更新で、Netlify で静的ファイルを再生成WordPress の新規投稿や更新で、Netlify で静的ファイルを再生成WordPress の新規投稿や更新で、Netlify で静的ファイルを再生成WordPress の新規投稿や更新で、Netlify で静的ファイルを再生成

コピーWordPress の新規投稿や更新で、Netlify で静的ファイルを再生成
wp-config.php
<?php
...
define('NETLIFY_WEBHOOK', 'https://api.netlify.com/build_hooks/xxxxxxxx');...

NETLIFY_WEBHOOK という定数を定義して、値に先程コピーした URL をペースト

WordPress の新規投稿や更新で、Netlify で静的ファイルを再生成
functions.php
<?php
...
function ktrz_netlify_webhook( $post_id, $post, $update ) {if ( defined( 'NETLIFY_WEBHOOK' ) ) {wp_remote_post( NETLIFY_WEBHOOK );}}add_action( 'save_post', 'ktrz_netlify_webhook', 10, 3 );

WordPress の新規投稿や更新で、Netlify で静的ファイルを再生成

DemoIssues
多くのプラグインが使えなくなる

そもそもカルーセルやライトボックスのようなサイトの表示を制御するようなプラグインをあまり使っていないのでそこまで困らないIssues
WordPress と Nuxt.js での二重作業や不一致

がんばる、運用でカバー

Issues
API と公開サイトのドメインが異なる場合
WordPress 投稿内などのサイト内リンク問題

WordPress のフィルタフックで改造する

Issues
API と公開サイトのドメインが同一の場合
静的ファイルのデプロイをどうするかシェルスクリプトなどでがんばるIssues
記事プレビュー

Gutenberg をサイトデザインに合わせる
or
別サーバ SSR で API 認証を行い、下書きを見れるようにする

まとめ

Summary
JAMstack 開発をしたい

JavaScript + Markup + API
JS フレームワーク(Nuxt.js おすすめですよ)Summary
JAMstack で作られたウェブサイトの更新をしたい

JavaScript + Markup + API
Headless CMS の出番

Summary
Headless CMS はどれがいいの？

みなさんがよく知っている WordPress もHeadless CMS として使えますよhttps://kiteretz.com/careers/

THANK YOU