メリークリスマス!(昨日) これはVue.jsアドベントカレンダーの記事です。
代打です。
僕は初日にサーバーサイドレンダリングについて書きましたが 今回もサーバーサイドレンダリングです。
今回の内容は本当は初日に書きたかったのですがずっとうまくいかずに悩んでいたけどつい昨日できたGoサーバでのSSR(サーバーサイドレンダリング)です。
GoでSSRをするメリットとしてまず一つにポータビリティです。
Node.jsもポータビリティはありますが、Goであればアセットもワンバイナリにまとめることができるのでバイナリを配置するだけでWebUIがあるツールも作ることもできるかもしれません。
そして、僕にとって1番のメリットであるApp Engine(GAE)でSSRができるようになります!
SSRについては初日の記事を見てください!
サンプルの実行
https://github.com/k2wanko/appengine-go-ssr-example
サンプルのコードはGitHubにあげてあります。
これをベースにGoでSSRを実現するためにやったことを書いていきます。
動かし方は以下の手順です。
$ git clone https://github.com/k2wanko/appengine-go-ssr-example.git
$ git checkout -b vue2.1 7fff5eec2006b6a617696b5db3403dd27e6a8dfe
$ npm install # or yarn
$ go get -v ./...
$ npm run dev
npm run dev
を実行するとで開発サーバが立ち上がります。http://localhost:8080
にアクセスすると確認ができます。
webpack.config.js
まずはwebpackの設定です。
基本は初日の記事のやつと同じですがGoで動かすために少し変えています。
まずGoでJSを実行するランタイムはgojaを使いました。
gojaはottoのようにGo実装のJavaScriptパーサです。
ottoよりもGoとのやり取りがやりやすいので使いました。
gojaについてはドワンゴのアドベントカレンダーに書いたのでそっちを見てください。
gojaを使ってGoでJavaScriptの実行を試してみた - Qiita
まずコードをgojaで動かせるようにする必要があります。
gojaはES5.1を実装しているのでそこの変換はbabelでやります。
次にNode.jsを前提にしているコードのためにwebpackのNodeSourcePlugin
を利用します。
webpackではtarget: 'node'
にするとNodeSourcePlugin
が使われないのでwebpack.config.js
に追加します。
でもそれだけではまだだめでNodeTargetPlugin
の効果を無効にする必要があります。
NodeTargetPlugin
はnativeモジュールを外部から取ってくるようにするためのプラグインです。
process.binding
を置き換えて対処しました。
もっとスマートなやり方があればいいのですが... そのためにはPRが必要かもしれません。
以下がserver用のコードの設定です。
var NodeSourcePlugin = require('webpack/lib/node/NodeSourcePlugin')
webpackModule.rules[1].exclude = null
var binding = process.binding
process.binding = function (name) {
if (name === 'natives') return {}
return binding.apply(process, arguments)
}
var server = Object.assign({}, client, {
entry: './src/server.js',
target: 'node',
devtool: false,
output: Object.assign({}, client.output, {
filename: 'server-build.js',
libraryTarget: 'commonjs2'
}),
plugins: [
new NodeSourcePlugin(
{
console: true,
process: true,
global: true,
Buffer: true,
setImmediate: true,
module: 'empty',
__filename: 'mock',
__dirname: 'mock'
}),
],
module: webpackModule,
})
setTimeout
ES5の仕様にはsetTimeoutの仕様が含まれていないのでgoja_nodejsのeventloopを使いました。
今後の予定
- VuexとVue Routerを使う
- 実践的なアプリケーションを作ってみる
まとめ
というわけで、GAE/GoでSSRができました!