先日betaがリリースされたvue.js 2.0
仮想DOMの導入でパフォーマンス向上、SSR対応が図られています。
パフォーマンス向上のサンプルは
http://qiita.com/mikakane/items/78614572d964420e7e31
をご確認下さい。
以下はSSRに関する覚書。イベント公開前でサンプルコードがUP出来ないのですが、
後でサンプルコード含めて加筆してUPする予定。
SSR して遊んでみる
vue.js 2.0 のSSRサンプルとしては、公式で下記の様なものが提供されており非常に参考になります。
vue.jsでSSRの手順としては、以下の形になります。
- フロントのコードをサーバ用にビルドする。
- 作成したコードからrendererを作成
- rendererを文字列orストリームに変換
フロントのコードをビルド
最初はフロント用に記述したコードをそのままrequireして使えないか…なども考えていたんですが、テンプレートの読み込みとかはwebpackなりbrowserifyなりを使用しているケースが多いので、
サーバでの利用時にも素直にwebpackなりbrowserifyなりを使用する方が良さそうです。
サーバ用のエントリを作成して、Vueインスタンス(またはPromise)をreturnする関数を作成します。
フロント側ready等でデータの読み込みなど行っている場合、SSRで利用できないっぽい(?)ので、
独自の初期化関数を組む方が良さそうです。
この場合 export する関数もPromiseを返す形になります。
const Vue = require('vue')
Vue.component("my-component",require("../frontend/component/myComponent/"))
const app = new Vue(require("../frontend/app.js"))
app.ssrInit = ()=>{
return new Promise(resolve => {
app.loadData().then((articles) => {
app.articles = articles
resolve()
})
})
}
export default (context) => {
return app.ssrInit().then( ()=>{
return app;
} )
}
作成したコードからrendererを作成
export default
でappを返す関数を実装しwebpackで target node のビルドを行うと、vue.js側からbundleでrendererを作成出来るようになります。
var fs = require("fs");
const createBundleRenderer = require('vue-server-renderer').createBundleRenderer
const renderer = createBundleRenderer(fs.readFileSync(__dirname+'/server-bundle.js'))
rendererを文字列orストリームに変換
renderer からSSRコンパイル済文字列を受け取るにはrenderToString やrenderToStream を利用する。
シンプルに様子を見るだけだとrenderToStringとかでも良さそう。
公式の方ではrenderToStreamを使ったサンプルが掲載されています。
生成されたvue.jsのコードをテンプレートに埋め込んで吐き出せば完了。
var express = require('express');
var app = express();
app.get("/", (req,res)=>{
const renderStream = renderer.renderToString((e,result)=>{
let html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WP API Sample Application</title>
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<script src="./assets/js/common.bundle.js"></script>
</head>
<body>
<div id="app">
<h1 class="app-title">WP API Sample Application</h1>
${result}
</div>
</body>
</html>
`;
res.send(html)
})
})
運用を考える
とりあえずサーバ側で利用可能、という所は分かったとして、後はどのように運用を考えるか。
公式サンプルのコードでは初期のデータを取得して、HTML側に__INITIAL_STATE__と言うかたちの変数で、値を格納しています。
この辺はやっぱりVuex(Vue.js 向けのflux実装)とかと混ぜて使うほうが使い勝手が良さそう。
個人的には SSR出来るようになったなら、コマンドラインツール的にHTML吐き出す実装使って、PHPとかの多言語でフロントのコンポーネント利用できたりしないかなぁ…とか妄想しています。