npx create-nuxt-appコマンドでNuxt.jsのSSRとSSGを使ってみた
Nuxt.jsにはSPAで動作させる意外に、SSRとSSGというものがある。
今回はこれをプロジェクト作成から実際に動かすまでを行う。
- npx create-nuxt-appコマンドでプロジェクト生成
- APIサーバを作っておく(api通信してデータをレンダリングする用)
- SSR化
- 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]