はじめに
おなじみのエラーですが、初めて遭遇したパターンだったのでまとめていきます。
問題
以下のAPIを作成しました。
pages/api/hello.ts
import supabase from '@/app/utils/supabase'
import type { NextApiRequest, NextApiResponse } from 'next'
type StudyRecord = {
title: string
time: number
}
type StudyRecordData = {
id: number
title: string
time: number
created_at: string
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === 'POST') {
const { title, time } = req.body
const { error } = await supabase.from('study-record').insert([
{ title, time }
])
if (error) {
return res.status(500).json({ message: error.message })
}
return res.status(200).json({ message: 'success' })
} else if (req.method === 'GET') {
const {data, error } = await supabase.from('study-record').select('*')
if (error) {
return res.status(500).json({ message: error.message })
}
const studyRecords: StudyRecord[] = data.map((record: StudyRecordData) => {
return {
title: record.title,
time: record.time
}
})
res.status(200).json({ studyRecords })
}
}
ここで起動すると問題なくAPIは使えます。
そして以下のコマンドを叩くとエラーが発生しました
$ npm run build
TypeError: Failed to parse URL from /api/hello
at Object.fetch (node:internal/deps/undici/undici:13220:11)
at async p (/home/jinwatanabe/workspace/tmp/env-test/.next/server/pages/add.js:1:740) {
[cause]: TypeError: Invalid URL
at new URL (node:internal/url:775:36)
at new Request (node:internal/deps/undici/undici:7173:25)
at fetch2 (node:internal/deps/undici/undici:11161:25)
at Object.fetch (node:internal/deps/undici/undici:13218:18)
at fetch (node:internal/process/pre_execution:282:25)
at p (/home/jinwatanabe/workspace/tmp/env-test/.next/server/pages/add.js:1:746)
at renderWithHooks (/home/jinwatanabe/workspace/tmp/env-test/node_modules/react-dom/cjs/react-dom-server.edge.production.js:4184:18)
at renderElement (/home/jinwatanabe/workspace/tmp/env-test/node_modules/react-dom/cjs/react-dom-server.edge.production.js:4322:14)
at retryNode (/home/jinwatanabe/workspace/tmp/env-test/node_modules/react-dom/cjs/react-dom-server.edge.production.js:4866:16)
at renderNodeDestructive (/home/jinwatanabe/workspace/tmp/env-test/node_modules/react-dom/cjs/react-dom-server.edge.production.js:4684:7) {
code: 'ERR_INVALID_URL',
input: '/api/hello'
}
}
Error occurred prerendering page "/add". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Failed to parse URL from /api/hello
at Object.fetch (node:internal/deps/undici/undici:13220:11)
at async p (/home/jinwatanabe/workspace/tmp/env-test/.next/server/pages/add.js:1:740)
Export encountered an error on /add, exiting the build.
⨯ Static worker exited with code: 1 and signal: null
おなじみのエラーなので、ホスト周りをみたり、環境変数周りをみても解決ができずでした
解決方法
このAPIを呼び出すために利用していたファイルの位置が悪さをしていました
┣ app
┣ page.tsx
┣ pages
┣ add.ts
┣ api
┣ hello.ts
page.tsx
import AddMotivation from "../utils/add";
export default function Home2() {
const handleAdd = async () => {
await AddMotivation();
}
return (
<div>
<button onClick={handleAdd}>click</button>
</div>
)
}
add.ts
export default async function AddMotivation() {
const res = await fetch(`/api/hello`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: "title", time: 1 }),
});
const data = await res.json();
return data;
}
ページではadd.ts
の関数を経由してAPIを読んでいましたがこのファイルの位置がpages/add.ts
にありました。
Next.jsではディレクトリ構造に意味があるため、npm run build
のときにAPIとして?ビルドしようとしてしまうのが問題だったかと思われます。
おわりに
このパターンは初めてだったので環境変数やホストをかなり疑いました。
しっかりと切り分けをしていくのが大切なのを学びました