【Next.js】【エラー】TypeError: fetch failed

エラー

 

VercelにNext.jsをデプロイしたときに「TypeError: fetch failed」がでて

デプロイに失敗しました。

 

解決していきまーーーす!

 

TypeError: fetch failed ①

エラー内容確認

 

Vercelでデプロイログを確認しました

 

fetchでRoute Handlersで作成したAPIを呼び出したときにエラーになってるっぽい

 

ググってみる

 

TypeError: fetch failed」「ECONNREFUSED」ここら辺の単語でググってみました

 

ECONNREFUSED on NodeJS 18 · Issue #1624 · node-fetch/node-fetch
When using node-fetch on NodeJS 18, got ECONNREFUSED // test.mjs import { Server } from '@hapi/hapi' import fetch from 'node-fetch' const start = async () => { ...
[NEXT-1190] TypeError: fetch failed in server componant since next 13.0.6 · Issue #44062 · vercel/next.js
Verify canary release I verified that the issue exists in the latest Next.js canary release Provide environment information Operating System: Platform: linux Ar...

↑の記事によると、

Node.js 17/18 ではlocalhostがIPv6で名前解決されることが原因みたいです。

 

Vercelで Project Settings > General > Node.js Version を確認してみると、

確かに18系っぽい。。

 

ただ、デプロイログを再度見てみると127.0.0.1で解決できているので原因は別にありそう

まあ、一応試してみます。

 

コード修正

 

たたいているAPIのURLをlocalhost ⇒ 127.0.0.1へ変更しIPv4を直書きしてみます

 

再デプロイ

 

修正したコードをGitHubにpushして再デプロイしてみます。

失敗しました。。。

デプロイログを見てみると、エラーの内容変わらずでした。

 

うーーん、なんでしょう??

 

TypeError: fetch failed ②

エラー内容確認

 

fetch failedなので、やっぱりAPIがたたけないことが原因ですよね。。

localhostとか127.0.0.1ではなく、Vercelのデプロイ用のURLじゃないとダメなのか??

 

試してみます

 

Vercelのデプロイ用のURLとは?

 

Vercelでデプロイしたときに発行されるURLのこと。GitでいうコミットIDぐらいの感覚。

この値はVercelで設定されているVERCEL_URLという環境変数から取得できます

 

Vercelで設定されている環境変数については↓をご覧ください

System Environment Variables Overview
Vercel Environment variables that are automatically populated by the System, such as the URL of the Deployment or the name of the Git branch deployed.

 

今回はClient Componentでもこの環境変数を使用したいので、

NEXT_PUBLIC_VERCEL_URL を使います

Next.js では、基本的に環境変数はServer Componentでのみ参照できます。
  
Client Componentでも参照したい場合は、環境変数の先頭にNEXT_PUBLIC_をつけます
   
https://maku.blog/p/gbpeyov/

 

コード修正

 

APIのURLを環境変数から生成するようにします

 

(変更前)

 

(変更後)

  1. .env ファイルにNEXT_PUBLIC_API_PREFIXNEXT_PUBLIC_VERCEL_URLを定義
  2. 環境変数を読み込む src/lib/config.tsを作成
  3. APIのURLをconfig.tsファイルを読み込み生成

という3つのステップで修正します。

 

1..env ファイルにNEXT_PUBLIC_API_PREFIXNEXT_PUBLIC_VERCEL_URLを定義

 

NEXT_PUBLIC_VERCEL_URL では、https:// が取得できないので、
NEXT_PUBLIC_API_PREFIX として定義しておきます。

 

2.環境変数を読み込む src/lib/config.tsを作成

 

3.APIのURLをconfig.tsファイルを読み込み生成

 

環境変数からAPIのURLを指定すると、undefined同士の足し算でエラーになります
なので、config.tsでデフォルト値を指定しstring型にして足しています

 

ビルド設定修正

 

NEXT_PUBLIC_VERCEL_URLはVercelで設定されているのですが

NEXT_PUBLIC_API_PREFIXはあらかじめ設定しておく必要があります

 

Project Settings  > Environment Variables にて

Key  :NEXT_PUBLIC_API_PREFIX

Value :https://

で環境変数を設定します

 

 

再デプロイ

 

修正したコードをGitHubにpushして再デプロイしてみます。

失敗しました。。。

デプロイログを見てみると、エラーの内容変わりました

 

SyntaxError: Unexpected token < in JSON at position 0

エラー内容確認

 

 

JSONだと思ったけど1文字目が<だから、JSONじゃなくない??

というエラーです。

1文字目が<のため、おそらくAPIからHTMLが返ってきていると思います。

 

APIからのレスポンスヘッダーを確認する

 

↓のようにヘッダを出力させます

 

このコードでデプロイしてみるとログがこんな感じでした

 

‘content-type’ => { name: ‘Content-Type’, value: ‘text/html; charset=utf-8’ },

なので、やっぱりHTMLが返ってきていますね。

 

 

コード修正

 

どうしてHTMLが返ってきているのかは不明だったので、

レスポンスボディを取り出す処理をtry-catchしていきます

 

try-catchではなく、Client Componentに変更するのもありだと思います

 

再デプロイ

 

修正したコードをGitHubにpushして再デプロイしてみます。

成功しました!!

 

 

最後に

 

今回はとりあえずtry-catchで逃げましたが、

APIからHTMLが返ってきている原因を探らないとですね。。

 

コメント

タイトルとURLをコピーしました