2
0

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.

SSR する時にフロントエンドからバックエンドのエンジニアに最小限伝えておきたい Nuxt.js の挙動

Last updated at Posted at 2018-10-23

というわけで

実際に手を動かしてもらった方が早いので Tutorial を用意しました。

準備

vue-cli がなければ install しておく

% npm install -g vue-cli

デモプロジェクトを用意する

mkdir practice-nuxt-docker && cd $_
vue init nuxt-community/starter-template myapp 
touch myapp/Dockerfile docker-compose.yml
cd myapp
yarn init -y
yarn
yarn nuxt build # 重要
cd ..

create myapp/Dockerfile

RUN yarn add nuxt
WORKDIR /app
ENV HOST 0.0.0.0
EXPOSE 3000
CMD yarn nuxt start

create Dockerfile

version: '3' 
services:
  nuxt:
    build: myapp
    tty: true
    volumes:
      - "./myapp:/app"
    ports:
      - "3000:3000"
docker-compose build
docker-compose up

http://localhost:3000 へアクセスして動作確認します。nuxt build が必要ですのでデプロイツールを構築する人にちゃんと伝えておきましょう。

最初の Request は Node.js が HTML を返しますが、その直後にブラウザ側でレンダリングされている

以下のように修正します。

% git diff                                                               [master ~/samurai/practice-nuxt-docker/myapp]
diff --git a/myapp/pages/index.vue b/myapp/pages/index.vue
index cf60434..2e2e2b5 100644
--- a/myapp/pages/index.vue
+++ b/myapp/pages/index.vue
@@ -8,6 +8,8 @@
       <h2 class="subtitle">
         Nuxt.js project
       </h2>
+      <h3 v-if="isClient()">Client</h3>
+      <h3 v-else>Server</h3>
       <div class="links">
         <a
           href="https://nuxtjs.org/"
@@ -28,6 +30,11 @@ import AppLogo from '~/components/AppLogo.vue'
 export default {
   components: {
     AppLogo
+  },
+  methods: {
+    isClient() {
+      return (typeof window !== 'undefined' && window.document)
+    }
   }
 }

Nuxt.js のアプリを起動します。(以下の例は docker を経由しない例です)

cd myapp
yarn nuxt build
yarn nuxt start

この状態で http://localhost:3000 を Reload すると一瞬 Server と表示されますが、直後に Client に置き換わる挙動を確認する事ができます。これ以降はブラウザ側で JavaScript が実行されます。

最初のリクエストの段階では Node.js が Javascript を処理するため、このタイミングでは localStorage へのアクセスはできません。access_token の保持などは cookie を使うと良いでしょう。素直に @nuxtjs/axios を使っていれば Header の情報はそのままバックエンドに渡されるはずです。たぶん。

nuxt build が生成しているファイルの行方

nuxt build を実行すると以下のように圧縮された js ファイルが生成されます。

Hash: 893dbac70d5b02802558
Version: webpack 4.22.0
Time: 6225ms
Built at: 2018-10-23 12:02:07
                  Asset       Size  Chunks             Chunk Names
41297c5455157e9ca810.js   2.18 KiB       3  [emitted]  runtime
714f38d18aae84388e71.js   3.84 KiB       2  [emitted]  pages/index
               LICENSES  422 bytes          [emitted]  
a136c91fe4110122940e.js   31.1 KiB       0  [emitted]  app
ca15e729f68a6493bcb3.js    134 KiB       1  [emitted]  commons.app

これは以下の場所に配備されます。


% ls -l myapp/.nuxt/dist/client                                                
total 360
-rw-r--r--  1 okamuuu  staff    2228 10 23 12:02 41297c5455157e9ca810.js
-rw-r--r--  1 okamuuu  staff    3928 10 23 12:02 714f38d18aae84388e71.js
-rw-r--r--  1 okamuuu  staff     423 10 23 12:02 LICENSES
-rw-r--r--  1 okamuuu  staff   31824 10 23 12:02 a136c91fe4110122940e.js
-rw-r--r--  1 okamuuu  staff  137438 10 23 12:02 ca15e729f68a6493bcb3.js

そして以下の URL で配信されます。このファイルを nuxt start で動いているプロセスが返すのは効率が悪い気がするのでどうやってデプロイしてキャッシュしたりするかなどをインフラエンジニアに相談してみてください。

http://localhost:3000/_nuxt/41297c5455157e9ca810.js
http://localhost:3000/_nuxt/714f38d18aae84388e71.js
http://localhost:3000/_nuxt/LICENSES
http://localhost:3000/_nuxt/a136c91fe4110122940e.js
http://localhost:3000/_nuxt/ca15e729f68a6493bcb3.js

asyncData

非同期処理を SSR する場合、Nuxt.js では asyncData に記述するだけで簡単に実装できます。


mkdir myapp/pages/posts
touch myapp/pages/posts/index.vue

create pages/posts/index.vue


<template>
  <div class="container">
    <h1>Posts</h1>
    <ul>
      <li v-for="(post, index) in posts" :key="index">
        <nuxt-link :to="{ name: 'posts-id', params: { id: post.id } }">{{ post.title }}</nuxt-link>
      </li>
    </ul>
    <p><nuxt-link to="/">Back to home page</nuxt-link></p>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  asyncData({ req, params }) {
    return axios.get('https://jsonplaceholder.typicode.com/posts')
      .then((res) => {
        return { posts: res.data.slice(0, 5) }
      })  
  }
}
</script>

nuxt あるいは nuxt build && nuxt start でプロセスを起動してから以下の curl コマンドを実行してください。非同期処理で取得している情報が HTML で記述されてる事を確認できます。

curl -s http://localhost:3000/posts

他にも何かあれば

追記します。

  • 非同期処理であっても Node.js のプロセスで rendering して HTML を返す挙動が若干イメージしづらいようなので asyncDate について を追記しました。
2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?