ねとりふぁい
目次
NetlifyにNuxt3をSSRでデプロイする
そういえば、SSRを使ったウェブサイトの公開を体験していないなと思い、やってみることに。無料枠でいけそうだったので、Netlifyで試してみました。想定どおり、一筋縄ではいきませんでしたね。そのため、調べたり、ハマったりしたので、メモします。今回は、エックスサーバーにSSGでアップロードしたプロジェクトを用いました。別ブランチでSSRを作って、デプロイしています。実行環境は以下です。
nuxt 3.6.5
netlify-cli 17.16.0
node v20.10.0
Githubからデプロイする
下記のサイトを参考にやってみましたが、これは驚くほど簡単でした。しかも、Githubにpushするだけでサイトも更新されるんです。FTPでファイルをアップロードするよりも簡単ですね。しかし、ビルド時間が増えると無料枠の制限を超えるようなので、一旦別の手段をとることに。
加えて、Githubへのデプロイとは関係ありませんが、デプロイ時にページ遷移するとCORSエラーが発生していて、下記サイトなどを読むと、どうもサーバーサイドで外部JSONを取得しなきゃダメみたい。そこで、Netlify Functionsも導入することにしました。
Netlify-Cliからデプロイする
まずは、無料枠を維持するべく、デプロイ方法を変更します。検索していると下記の2つの方法が見つかりました。Netlify Functionsも付け加える必要があったので、netlify.tomlを使ったデプロイ方法を選択することに。下記サイトを参考にしながら進めます。
Netlify Functionsがなんか違う
紹介されている色々なサイトの方法を試したんですが、どうもやり方が変わってしまったようで、エラーが出ます。下記を読むと、拡張子を.mtsに変える模様。あと、netlify-lambdaも不要みたいです。ここのところが一番時間を費やしたかもしれません。ただ、.tsでもいけそうな気がするので、またそのうち検証しようかな。
階層は下記のような感じです。外部からJSONを取得したかったので、下記サイトを参考にgetJson.mtsを作ることにしました。getJson.mtsは参考サイトのやり方とだいたい同じです。※URIだけ違います。
package.json
netlify.toml
netlify
| functions
| getJson.mts
ここでまた詰まったのですが、SSGの時はcomposables/useFetchData.tsを置いて、ここで外部JSONを取得していました。しかし、SSRだとエラーになるので、netlify/functionsでデータを取得しなければなりません。ここだけサーバーサイドになるそうです。そのため、composables/useFetchData.tsでのJSON取得もuseFetch系のAPIを使わないとダメだそう。exportしているからimportなのかと思ったら、違うんだとか。結果、productUrlに書いていたURIを/.netlify/functions/getJsonに書き直しました。useFetchData.tsは以下のように修正。
import type { DataType, Report } from '~/types/covid19'
const urlSetting = process.env.NODE_ENV === 'production'
const devUrl = '/api/endpoint'
const productUrl = '/.netlify/functions/getJson'
const fetchUrl = urlSetting ? devUrl : productUrl
export const useFetchData = async () => {
const { data } = await useAsyncData<DataType[]>('json', () =>
$fetch(fetchUrl), {
transform: (array: DataType[]): DataType[] => {
const processedArray = array.map((item: DataType): DataType => {
const newItem: DataType = [
item[0],
replaceZero(item[1]),
replaceZero(item[2])
]
return newItem
})
return processedArray
}
})
// 以下省略
デプロイするとコマンドラインに反応があり、情報は伝わっているが、Cannot read properties of undefined (reading ‘0’)というJSONが読み込めていないエラーが発生し、error.vue画面が表示されています。おかしいなと思い、Function Logを見てみると、環境変数が設定されていないというエラーが返されていました。調べると、Nuxt3の.envで環境変数を設定すると、Netlifyでも同じ設定が必要だそう。下記サイトを参考に設定すると外部JSONの値を取得することに成功しました。
いよいよ最終局面だなと思い、気合を入れて作業を続けますが、Cannot read properties of undefined (reading ‘0’)というエラーは変わりません。ただ、エラー画面からトップページに遷移すると外部JSONの値が表示され、他のページも値が表示されています。さらに、画面をリフレッシュするとエラーがでることは把握しました。ヒントはないか、エラーログなどを見ましたが、特になし。しかし、たまたま見たブラウザの開発者ツールのエレメントに、id=”__NUXT_DATA__”に429 Too Many Requestsが返されているのを発見。これがヒントになりました。
その現象に関連しそうな本番環境と開発環境のURIを入れ替えると、URIが見つからず、何度もアクセスしているのがターミナルのメッセージからわかりました。netlify上の動きと似ていたため、URIを入れ替えると、無事エラーなく、外部JSONの値を取得することに成功です。この部分は自分のミスですね。完全に。ただなぁ、何故かnetlify上とローカルだと動きが異なるんですよね。この気持ち悪さの原因は解消できませんでした。
nuxt-og-imageでinstance unavailableエラーがでる
nuxt-og-imageを使っていると下記のエラーがでました。copilotに聞くと、「nuxt-og-imageは、nuxtのレンダリングフックを使って、ページのOGP画像を生成するモジュールです。しかし、netlifyではSSRをするときに、nuxtインスタンスが利用できないため、nuxt-og-imageがエラーを出します。」とのこと。ただ、そう書いてある記事がなかなか見つからないので、本当かどうかわかりませんが、一旦nuxt-og-imageを抜くことに。すると、確かにエラーは表示されません。ということは、間違いではなさそうです。さすが、AI。今回のSSRにする目的は、nuxt-og-imageの瞬発力を見ることが大きかったので、ダメージは大きいのですが、経験値を稼ぐため、このまま進めることにします。
ERROR Error: [nuxt] instance unavailable
at useNuxtApp (file:///var/task/chunks/app/server.mjs:278:13)
at setup (file:///var/task/chunks/app/server.mjs:2531:21)
at _sfc_main.setup (file:///var/task/chunks/app/server.mjs:2569:23)
at callWithErrorHandling (/var/task/node_modules/@vue/runtime-core/dist/runtime-core.cjs.prod.js:83:18)
at setupStatefulComponent (/var/task/node_modules/@vue/runtime-core/dist/runtime-core.cjs.prod.js:6043:25)
at setupComponent (/var/task/node_modules/@vue/runtime-core/dist/runtime-core.cjs.prod.js:6030:36)
at renderComponentVNode (/var/task/node_modules/@vue/server-renderer/dist/server-renderer.cjs.prod.js:358:15)
at renderToString (/var/task/node_modules/@vue/server-renderer/dist/server-renderer.cjs.prod.js:649:24)
at Object.renderToString$1 [as renderToString] (file:///var/task/chunks/handlers/renderer.mjs:151:24)
at Object.renderToString (file:///var/task/node_modules/vue-bundle-renderer/dist/runtime.mjs:174:40)
リフレッシュすると古い画面が表示される
途中で見つかった、なぜかリフレッシュすると古い画面が表示される問題。動的ルーティングのページだけ、リフレッシュするとjsとcssがリンク切れのファイル名にリンクされて画面に表示されていません。おかしいなと思い、色々検索してみると、下記サイトを発見。本番環境にroutesがいらないようなので、SSGの時に加えていたnitro.prerender.routesを消してみることに。さらに、distに残っていたファイルも全消し。その後デプロイすると、どのページで更新ボタンを押しても、再読込されるだけで、おかしな動作はありません。よかった。よかった。これであらかた不具合は解消されました。しかし、細かい部分がおかしいので、まだまだ続きます。。。