Vue.js向けSSRフレームワークnuxt.jsを触ってみた

## nuxt.jsとは
[nuxt/nuxt.js](https://github.com/nuxt/nuxt.js)

> Few hours after the announcement of Next.js, the idea of creating server-rendered Vue.js applications the same way as Next.js became inevitable: Nuxt.js was born.

> Writing a server-rendered Vue.js application with Nuxt.js is easy:

> No need to write Webpack/Babel configuration
> No need to create a node.js server
> Writing *.vue files, because it rocks
> Creating new routes by adding a file in the pages/ directory
> Accessing the server data inside the routes components easily

[What is Nuxt.js ?](https://nuxtjs.org/guide)

WebpackやBabelの設定が不要でnode.jsのサーバも不要。
[vueファイル](https://github.com/vuejs/vueify)を追加するだけで簡単にVue.jsアプリのSSRができるようです。

ようは[next.js](https://github.com/zeit/next.js/)のVue.js版ということですね。
next.jsについては以下の記事が詳しいです。

- http://qiita.com/nkzawa/items/1e0e93efd13fb982c8c0


## プロジェクトを作成する
ではさっそく、適当なアプリを作ってみます。
まずはディレクトリを作成します。

```
$ mkdir nuxt-sample
$ cd nuxt-sample
```

package.json作成後、nuxt.jsをインストールします。

```
$ npm init -y
$ npm install --save nuxt
```

テンプレートはjadeを使いたいのでこちらもインストールしておきます。

```
$ npm install --save-dev jade
```

nuxtをインストール後、package.jsonを以下のように変更します。
これで`npm run dev`でサーバが起動するようになります。

``` package.json
{
  "name": "nuxt-sample",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "dev": "nuxt"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "nuxt": "^0.8.8"
  },
  "devDependencies": {
    "jade": "^1.11.0"
  }
}
```

### pagesディレクトリの作成
pagesディレクトリの構造からroutesが生成されます。
*.vueファイルを追加していくことでアプリケーションを作成していきます。

**例**

|pageディレクトリ構造|path|
|:--|:--|
|./pages/index.vue|/|
|./pages/hoge.vue|/hoge|
|./pages/foo/bar.vue|/foo/bar|

ということでpagesディレクトリを作成します。

```
$ mkdir pages
```

#### 参考
- https://nuxtjs.org/guide/routing


## ページを作ってみる
まずはHelloWorldを表示してみようということで、
pagesディレクトリに以下のファイルを追加します。

``` pages/index.vue
<template lang="jade">
.container
  h1 {{msg}}
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello World.'
    };
  }
};
</script>
```

起動して確認してみます。

```
$ npm run dev
```

![hello.png](https://qiita-image-store.s3.amazonaws.com/0/148095/b8162938-3040-a0ef-c6e0-1fc7fd55154d.png "hello.png")


表示されました。
curlでSSRされているか確認してみます。

```
$ curl localhost:3000
<!DOCTYPE html>
<html n-head-ssr n-head="">
  <head>
    <title n-head="true"></title>
    <base href="/">
  </head>
  <body n-head="">
    <div id="__nuxt" server-rendered="true"><div><div class="progress" style="width:0%;height:2px;background-color:black;opacity:0" data-v-0808b48a></div> <div class="container"><h1>Hello World.</h1></div></div></div>
    <script type="text/javascript" defer>window.__NUXT__={"data":[{"msg":"Hello World."}],"error":null,"serverRendered":true}</script>
    <script src="/_nuxt/vendor.bundle.js" defer></script>
    <script src="/_nuxt/nuxt.bundle.js" defer></script>
  </body>
</html>
```

ちょっと見づらいですが`<h1>Hello World.</h1>`と表示されていますね。
ちゃんとSSRされているようです。

## AJAXなページを作ってみる
外部のAPIからデータを取得して画面上に表示してみます。
[myjson](http://myjson.com/) [^1] に以下のようなjsonを保存して取得してみます。

```
{
  "items": [
    "foo",
    "bar",
    "baz"
  ]
}
```


### xhrライブラリの追加
今回は[axios](https://github.com/mzabriskie/axios)を使います。

```
$ npm install --save axios
```

### pages/index.vueを修正

pages/index.vueを以下のように修正します。

``` pages/index.vue
<template lang="jade">
.container
  ul
    li(v-for="item in items") {{item}}
</template>

<script>
import axios from 'axios';

export default {
  data () {
    // dataを非同期で取得
    return axios.get('https://api.myjson.com/bins/jewnd').then(res => res.data);
  }
};
</script>
```

では確認してみます。

![ajax.png](https://qiita-image-store.s3.amazonaws.com/0/148095/7a83571e-6f0e-77ff-ac60-9f22977f2e5e.png "ajax.png")


OKです。
続いてcurlでSSRされているか確認してみます。

```
$ curl localhost:3000
<!DOCTYPE html>
<html n-head-ssr n-head="">
  <head>
    <title n-head="true"></title>
    <base href="/">
  </head>
  <body n-head="">
    <div id="__nuxt" server-rendered="true"><div><div class="progress" style="width:0%;height:2px;background-color:black;opacity:0" data-v-0808b48a></div> <div class="container"><ul><li>foo</li><li>bar</li><li>baz</li></ul></div></div></div>
    <script type="text/javascript" defer>window.__NUXT__={"data":[{"items":["foo","bar","baz"]}],"error":null,"serverRendered":true}</script>
    <script src="/_nuxt/vendor.bundle.js" defer></script>
    <script src="/_nuxt/nuxt.bundle.js" defer></script>
  </body>
</html>
```

ajaxなページもちゃんとSSRされているようです！

```
<div class="container"><ul><li>foo</li><li>bar</li><li>baz</li></ul></div></div></div>
```


## 終わりに
[ドキュメント](https://nuxtjs.org/guide/)はほとんとのページがcoming soonになっていたりとまだまだこれからと言った感じではありますが開発も活発なようですし、これから注目していきたいです。

[^1]: JSONをホスティングできるサービス。