Skip to main content

npx create-nuxt-appコマンドでNuxt.jsのSSRとSSGを使ってみた

· 6 min read

Nuxt.jsにはSPAで動作させる意外に、SSRとSSGというものがある。

今回はこれをプロジェクト作成から実際に動かすまでを行う。

  1. npx create-nuxt-appコマンドでプロジェクト生成
  2. APIサーバを作っておく(api通信してデータをレンダリングする用)
  3. SSR化
  4. SSRのアプリケーションしたものをSSGとして静的ファイルを生成

こんな感じ

アプリケーションの作成​

nuxtプロジェクトはcreate-nuxt-appというコマンドを通して行うと楽。

npx create-nuxt-app nuxt-ssr-app

プロジェクト名はnuxt-ssr-appとした

コマンド実行後対話モードで色々聞かれるので、以下のように選択。

universalを選択するとSSR,SSGが使えるようになるらしい ただ、ここはあとから修正できるので、余り神経質にならなくてよい。

APIサーバを準備する​

SSRでもSSGでもAPIサーバに通信した結果をレンダリングするということをしたいので、予めAPIサーバとしてjson型式でデータを返すサーバを立てておく。

npmのjson-serverを使う

https://www.npmjs.com/package/json-server

db.json

{
"users": [
{ "id": 1, "name": "bob", "age": 20 },
{ "id": 2, "name": "tom", "age": 30 },
{ "id": 3, "name": "takeshi", "age": 70 }
]
}

json-serverがnpmでインストールされていれば以下コマンドで、サーバを起動出来る

./node_modules/json-server/lib/cli/bin.js --watch db.json -p 9000

エンドポイントはこうなるhttp://localhost:9000/users

以上でAPIサーバが準備できた

SSRで起動する​

axiosの設定​

axiosは事前にインストールして使えるように設定しておく

npm install @nuxtjs/axios

nuxt.config.jsにmoduleとしてaxiosを追加

export default {
...,
modules: ['@nuxtjs/axios'],
...

これでvue内からthis.$axiosとしてアクセス出来るようになる

ただのaxiosをインストールして使ってもよいが、vueファイルごとにimportしないといけなくなるので、nuxtjs/axiosが使えるならこの方が良さそう

asyncDataでaxiosを使う場合は、thisは使えないので、このようにアクセスする必要がある

asyncData({ $axios }) {
...
}

asyncDataを使ってSSRにする​

通常データの取得などはcreatedやmountedで行うが、 それではSPAの動きをしてしまうので、サーバサイド側でデータを取得するためにasyncDataを使用する。

pages/index.vueを以下のように書き換える

<template>
<div class="container">
<div>
<Logo />
<h1 class="title">
nuxt-ssr-app
</h1>
<ul>
<li v-for="user in users">
{{ user.id }}
{{ user.name }}
{{ user.age }}
</li>
</ul>
<button @click="resetUser()">reset</button>
<button @click="fetchUser()">fetch user</button>
</div>
</div>
</template>

<script>
export default {
asyncData({ $axios }) {
return $axios.get("http://localhost:9000/users").then(res => {
return {
users: res.data
}
})
},
data() {
return {
message: "hello nuxt ",
}
},
methods: {
resetUser: function () {
this.users = []
},
fetchUser: function () {
this.$axios.get("http://localhost:9000/users").then(res => {
this.users = res.data
})
},
}
}

重要なのは、asyncDataの箇所。ここで9000ポートに対して、リクエストを飛ばしユーザデータを取得している。 このようにすることで、SPAではなくSSRとして動作するようになる。

では起動してみる

npm run dev

リストとしてユーザ情報が表示されたので、実際の通信をみてみると

ちゃんとDocとしてユーザ情報が入っているHTMLが返されている

念の為Xhrもみてみると、API通信している箇所はなかったのでSSRは成功している

今回ついでにresetとfetchメソッドを作成したので、こちらを使用してみると

fetchUserしたタイミングで、API通信が行われているのが確認できる

このように、今まで通りの何らかのアクションをしたときにAPIをコールすることもできる。HTMLを一気にレンダリングした結果を返したい場合は、asyncDataで事前に取得すれば良い。

今までのSPAの開発とほぼ同じなので、SSRで実装する場合も特段意識することは少なそう。

SSGに切り替えてみる​

では先程のページをSSGにしてみる。

とは言ってもかなり簡単にSSG化することができ、

nuxt generate

とするとSSGが完了する。

nuxtコマンドが使えない場合はpackage.jsonに以下追記すると良い

  "scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"export": "nuxt export",
"serve": "nuxt serve",
"generate": "nuxt generate" ←追加
}

これでnpm run generateとして実行できる generateコマンドにより、asyncDataに記述されているAPIをコールしてHTMLが作成されdistディレクトに静的ファイルが配置される。

このdistをホスティングすると静的サイトとして稼働させることが出来る。

生成されたdist/index.htmlをみてみると、HTMLファイル内にAPI経由で取得したユーザデータがきちんと追加されていた。

ホスティングするのが面倒だったので、PHPのビルドインサーバ使用して起動してみた

php -S localhost:8000

すると問題なく表示され、メソッドであるresetやfetchなども効いていた。

SSGの際のnuxt.config.jsについて​

公式サイトではSSGにするときはtarget: 'static'にすることが推奨されているので、それに従っていた方が良さそう。

何やらmodeというオプションが廃止されるようで、ssrというオプションになり、今後はtrue,falseを指定するようになるらしい

現状target: 'server'出会ってもnuxt generateコマンドだけで、SSGは可能だが、警告も出ていたので、やはりstaticとして指定していたほうが無難だろう。

stackoverflowでこれに対する質問もされていた

[https://stackoverflow.com/questions/63336570/whats-the-real-difference-between-target-static-and-target-server-in-nuxt:embed:cite]