Nuxt.jsでURL直叩きの時はページが表示されるのに、nuxt-linkやブラウザバックでAn error occurredになる


事象

ググった時にもっと引っかかっても良いのになーと思いつつ、全然記事がヒットしなかったのでメモ。

Nuxt.jsでaxiosを使いAPIからデータを取得。
そのデータを元にページを表示している場合、URLを直接叩くと正常に表示されるが、nuxt-linkで遷移したりブラウザバックで移動するとAn error occurredというエラーが出る。

参考:Chrome開発者ツール開いた時のエラー

結論

nuxt.config.jsで、axiosのproxyを設定しましょう。

理由

CORS(オリジン間リソース共有)が原因。

  • URLを直接開いた時=SSR(サーバサイドレンダリング)が実行される。その名の通りサーバサイドで実行される。
  • ブラウザバックやページ遷移=CSR(クライアントサイドレンダリング)が実行される。つまりクライアントのjsで実行されるので、CORSが関係してくる。

URL叩いた時に表示されるのであれば、APIのパスが誤っていたり処理がおかしいのではない。
サーバサイドとクライアントサイド、どちらで実行されているか気付けるかが鍵。
筆者は1時間以上悩みました

たとえ同じサーバ上で動いていても、バックエンドとフロントエンド(Nuxt)が違うportで動いていたら、CORSの対策が必要。

対処法

nuxt.config.js
   ** Nuxt.js modules
   */
   modules: [
-    "@nuxtjs/axios"
+    "@nuxtjs/axios",
+    "@nuxtjs/proxy"
   ],
+  axios: {
+    proxy: true
+  },
+  proxy: {
+    '/v1/': {
+      target: "https://example.com:8080/"
+    }
+  },
参考(API呼び出し):pages/posts/_id.vue
<script>
export default {
  validate({ params }) {
    return /^\d+$/.test(params.id)
  },
  async asyncData({ $axios, params }) {
    const response = await $axios.$get(`/v1/posts/${params.id}`)
    return {
      post: response.post
    }
  }
}
</script>
  • @nuxtjs/proxyはaxiosにセットで入っているので、yarn add不要です
  • /v1/の部分はお使いのAPIのパスに応じて変えてください。多くの場合、/api/になるはずです
  • targetの部分はAPIのrootパスになるよう(必要だったらport番号も)適宜置き換えてください。