DeNAのデザイン戦略室が主催するイベント「Frontend de KANPAI!」に菅沼がLTで登壇致します。
フロントエンドに関わる人の情報交換と交流を目的としているイベントで、お酒とおつまみの提供もあるので興味のある方は気軽にご参加ください!
制作過程における躓きや気付きのメモ
DeNAのデザイン戦略室が主催するイベント「Frontend de KANPAI!」に菅沼がLTで登壇致します。
フロントエンドに関わる人の情報交換と交流を目的としているイベントで、お酒とおつまみの提供もあるので興味のある方は気軽にご参加ください!
Nuxt.jsでは、外部サーバ等から非同期でデータを取得・表示する場合にも asyncData
を使ってあげることでクライアントサイドはもちろん、サーバサイドでもデータを取得し、HTMLで出力することが出来ます。
SSRできる本番環境があれば何の問題もないのですが、SSRせずプリレンダリングのみで運用する場合には、 asyncData
は静的ファイルをgenerateした時点でしか走っておらず、ページロード時にデータが更新されていない問題が起こり得ます。
例えばコーポレートサイト等で、別のサーバにWordPressが設置してあり、トップページのお知らせとしてWordPressから記事を取得するような場合を想定すると、こんな感じで作ってあげることで解決できます
// 非同期でデータを取ってくる関数
async function getPostData() {
return { data } = await axios.get('https://blog.example.com/wp-json/wp/v2/posts');
}
export default {
async asyncData(context) {
const obj = {};
if (context.isServer) { // asyncDataするのはサーバサイド(プリレンダリング時)のみ
obj.posts = await getPostData();
}
return obj;
},
async created() {
if (!this.$isServer) { // クライアントサイドはここで更新をかける
this.posts = await getPostData();
}
},
};
要は asyncData
を使うのはサーバサイド(プリレンダリング時)のみ。
クライアントサイドでは created
でデータの更新をかけてあげるわけです。
こうすることでプリレンダリング運用でも、一応(少し古いかもしれないけど)非同期データのHTMLもプリレンダリングされていて、ブラウザで訪れた際にはちゃんと最新の情報に更新されます。
Nuxt.jsを含めて、Vue.jsの2.xを使ってSSR(サーバーサイドレンダリング)をする場合に、 v-for
の箇所で下記のようなエラーが出る場合がある。
The client-side rendered virtual DOM tree is not matching server-rendered content.
再現したコードはこれ( items
は単純な文字列の配列)。
ちなみにVue.jsのバージョンは 2.2.6
<template v-for="item in items">
{{ item }}
</template>
回避するには、下記のように個々を要素で囲ってあげる。
<template v-for="item in items">
<span>{{ item }}</span>
</template>
クライアントサイドのみではエラーは出ず、ちゃんとレンダリングされるので、サーバ側の実行ロジックにバグがあるのかもしれない。
タイトルの通りですが、WP REST APIでカテゴリー情報を取得する場合、下記のエンドポイントを使いますよね。
/wp-json/wp/v2/categories
これに対してパラメータ per_page
で取得件数を設定できるのですが、実はこのパラメータ、1〜100の数値以外を渡すとエラーになります。
ドキュメントにも取りうる値の範囲は記載されていません
https://developer.wordpress.org/rest-api/reference/categories/
なんとなく語感がget_postsでよく使う posts_per_page
に似てるので-1を指定すれば全件取得できそうな気がするのですが、ところがどっこいできません。
おそらくパフォーマンスの問題で無茶な使い方を塞がれてるんだと思うのですが、100件以上になりうる可能性がある場合は、本当に必要なカテゴリーだけをパラメータ include
で指定して取得してあげるほうが良さそうです。
それでも100件以上欲しい場合は、パラメータ page
でしっかりロジカルにページングする必要がありそうです。
株式会社なすびのウェブサイトは、Vue.jsを用いたSPAで作られています(2017年4月現在)。
コーポレートサイトのような情報の提供に重きを置くサイトで、SPAのアーキテクチャを使うことはSEOの面からあまり適した用途であるとは言えません。
それは、GoogleボットこそJSを実行してからパースしてくれるので問題にはならないのですが、FacebookなどのSNSにシェアされた場合は未だにJSの実行までしてくれないからです。
これを解決するためには、サーバーからのレスポンスでHTMLを返す必要性が絶対的にあるのですが、いかんせんSSRを前提に環境の構築を考えると、サーバサイドでNode.jsを噛ませる必要があったりなど、なかなかに敷居が高いのです。
しかしコーポレートサイトのような、ページ数も動的コンテンツも少ない小規模サイトであれば、プリレンダリングという選択肢もあります。
今回はwebpackプラグインでサクッとプリレンダリングする方法の紹介です。
Prerender SPA Plugin
https://github.com/chrisvfritz/prerender-spa-plugin
このプラグインを使って、webpackのbuild過程で静的HTMLを書き出してしまいます。
// webpack.conf.js
var Path = require('path')
var PrerenderSpaPlugin = require('prerender-spa-plugin')
module.exports = {
// ...
plugins: [
new PrerenderSpaPlugin(
// Absolute path to compiled SPA
Path.join(__dirname, '../dist'),
// List of routes to prerender
[ '/', '/about', '/contact' ]
)
]
}
上記のように保存先とエンドポイントを設定してbuildすると、下記3ファイルが書き出されます。
/index.html
/about/index.html
/contact/index.html
これらのファイルをウェブサーバーに配置すると、当然下記URLでbuildされたHTMLがレスポンスされるのですが、
http://example.com/
http://example.com/about/
http://example.com/contact/
SPAとしてリンクを辿ってaboutページに遷移すると、URLは /about
となります。
/about
と /about/
は違うファイルを指しているため、この状態でリロードすると404になってしまいます。
これを回避するためには、 /about
にリクエストが来たら /about/
へリダイレクトする.htaccessを置いてあげれば良いのです
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteCond %{REQUEST_URI} !.*\.(css|js|html|png|jpg)
RewriteRule (.*) / [L]
</ifModule>
フロントエンドのウェブ制作会社 なすび のブログを始めます。
主に制作過程においてスタッフが躓いた点や日々の気付きを投稿していきます。