12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

vue.js 2.0 で SSR やろう

Posted at

先日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の手順としては、以下の形になります。

  1. フロントのコードをサーバ用にビルドする。
  2. 作成したコードからrendererを作成
  3. rendererを文字列orストリームに変換

フロントのコードをビルド

最初はフロント用に記述したコードをそのままrequireして使えないか…なども考えていたんですが、テンプレートの読み込みとかはwebpackなりbrowserifyなりを使用しているケースが多いので、
サーバでの利用時にも素直にwebpackなりbrowserifyなりを使用する方が良さそうです。

サーバ用のエントリを作成して、Vueインスタンス(またはPromise)をreturnする関数を作成します。

フロント側ready等でデータの読み込みなど行っている場合、SSRで利用できないっぽい(?)ので、
独自の初期化関数を組む方が良さそうです。

この場合 export する関数もPromiseを返す形になります。

server-entry.js
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とかの多言語でフロントのコンポーネント利用できたりしないかなぁ…とか妄想しています。

12
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?