我有一个API路由app/api/posts/route.ts
,它使用Prisma ORM从我的数据库中检索所有帖子。在localhost上,数据库是我的本地PostgreSQL服务器,而在生产环境中,数据库托管在render.com
上。我在函数内部的app/page.tsx
上使用axios来获取来自API路由的响应。代码如下:
import Card from "@/components/Card";
import axios from "axios";
const getPosts = async () => {
const url =
process.env.NODE_ENV === "development"
? "http://localhost:3000/api/posts"
: "https://dropconnect.vercel.app/api/posts";
const res = await axios.get(url);
const data = await res.data;
return data;
};
export default async function Home() {
const posts = await getPosts();
return (
<div>
{posts.length === 0 ? (
<div>
<p>No Posts have been made yet</p>
</div>
) : (
<div>
{posts.map((post: any) => (
<div key={post.id}>
<Card
id={post.id}
title={post.title}
content={post.content}
comments={post.comments}
noComments={post.noComments}
noLikes={post.noLikes}
name={post.author.name}
image={post.author.image}
/>
</div>
))}
</div>
)}
</div>
);
}
字符串
下面是我的/app/api/posts/route.ts
代码:
import { prisma } from "@/lib/database";
import { NextResponse } from "next/server";
export async function GET(req: Request) {
const allPosts = await prisma.post.findMany({
include: {
comments: true,
author: {
select: {
name: true,
image: true,
},
},
},
});
return NextResponse.json(allPosts);
}
型
下面是我的schema.prisma
:
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Post {
id String @id @default(cuid())
title String
content String?
noLikes Int? @default(0)
noComments Int? @default(0)
author User? @relation(fields: [authorId], references: [id])
authorId String?
comments Comment[]
}
model Comment {
id String @id @default(cuid())
content String
upvote Int @default(0)
downvote Int @default(0)
author User @relation(fields: [authorId], references: [id])
authorId String
post Post? @relation(fields: [postId], references: [id])
postId String?
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
comments Comment[]
posts Post[]
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
型
在localhost上运行良好:
的数据
当我将代码推送到GitHub时,vercel会抛出一个AxiosError,如下所示:
...
[00:36:27.999] AxiosError: Request failed with status code 404
[00:36:27.999] at settle (/vercel/path0/.next/server/chunks/228.js:32264:16)
[00:36:27.999] at BrotliDecompress.handleStreamEnd (/vercel/path0/.next/server/chunks/228.js:33220:21)
[00:36:28.000] at BrotliDecompress.emit (node:events:525:35)
[00:36:28.000] at endReadableNT (node:internal/streams/readable:1359:12)
[00:36:28.000] at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
[00:36:28.000] code: 'ERR_BAD_REQUEST',
[00:36:28.000] config: {
[00:36:28.000] transitional: {
[00:36:28.000] silentJSONParsing: true,
[00:36:28.000] forcedJSONParsing: true,
[00:36:28.000] clarifyTimeoutError: false
[00:36:28.000] },
[00:36:28.000] adapter: [ 'xhr', 'http' ],
[00:36:28.001] transformRequest: [ [Function: transformRequest] ],
[00:36:28.001] transformResponse: [ [Function: transformResponse] ],
[00:36:28.002] timeout: 0,
[00:36:28.002] xsrfCookieName: 'XSRF-TOKEN',
[00:36:28.002] xsrfHeaderName: 'X-XSRF-TOKEN',
[00:36:28.002] maxContentLength: -1,
[00:36:28.002] maxBodyLength: -1,
[00:36:28.002] env: { FormData: [Function], Blob: [class Blob] },
[00:36:28.002] validateStatus: [Function: validateStatus],
[00:36:28.002] headers: AxiosHeaders {
[00:36:28.002] Accept: 'application/json, text/plain, */*',
[00:36:28.002] 'User-Agent': 'axios/1.4.0',
[00:36:28.002] 'Accept-Encoding': 'gzip, compress, deflate, br'
[00:36:28.002] },
[00:36:28.002] method: 'get',
[00:36:28.003] url: 'https://dropconnect.vercel.app/api/posts',
[00:36:28.003] data: undefined
[00:36:28.003] },
[00:36:28.003] request: <ref *1> ClientRequest {
[00:36:28.004] _events: [Object: null prototype] {
[00:36:28.004] abort: [Function (anonymous)],
[00:36:28.004] aborted: [Function (anonymous)],
[00:36:28.004] connect: [Function (anonymous)],
[00:36:28.004] error: [Function (anonymous)],
[00:36:28.005] socket: [Function (anonymous)],
[00:36:28.005] timeout: [Function (anonymous)],
[00:36:28.005] finish: [Function: requestOnFinish]
[00:36:28.005] },
[00:36:28.005] _eventsCount: 7,
[00:36:28.005] _maxListeners: undefined,
[00:36:28.005] outputData: [],
[00:36:28.005] outputSize: 0,
[00:36:28.005] writable: true,
[00:36:28.005] destroyed: true,
[00:36:28.005] _last: true,
[00:36:28.005] chunkedEncoding: false,
[00:36:28.005] shouldKeepAlive: false,
[00:36:28.006] maxRequestsOnConnectionReached: false,
[00:36:28.006] _defaultKeepAlive: true,
[00:36:28.006] useChunkedEncodingByDefault: false,
[00:36:28.006] sendDate: false,
[00:36:28.006] _removedConnection: false,
[00:36:28.006] _removedContLen: false,
[00:36:28.006] _removedTE: false,
[00:36:28.006] strictContentLength: false,
[00:36:28.006] _contentLength: 0,
[00:36:28.006] _hasBody: true,
[00:36:28.006] _trailer: '',
[00:36:28.006] finished: true,
[00:36:28.007] _headerSent: true,
[00:36:28.007] _closed: true,
[00:36:28.007] socket: TLSSocket {
[00:36:28.007] _tlsOptions: [Object],
[00:36:28.007] _secureEstablished: true,
[00:36:28.007] _securePending: false,
[00:36:28.007] _newSessionPending: false,
[00:36:28.007] _controlReleased: true,
[00:36:28.007] secureConnecting: false,
[00:36:28.007] _SNICallback: null,
[00:36:28.007] servername: 'dropconnect.vercel.app',
[00:36:28.007] alpnProtocol: false,
[00:36:28.007] authorized: true,
[00:36:28.007] authorizationError: null,
[00:36:28.007] encrypted: true,
[00:36:28.007] _events: [Object: null prototype],
[00:36:28.007] _eventsCount: 9,
[00:36:28.007] connecting: false,
[00:36:28.008] _hadError: false,
[00:36:28.008] _parent: null,
[00:36:28.008] _host: 'dropconnect.vercel.app',
[00:36:28.008] _closeAfterHandlingError: false,
[00:36:28.008] _readableState: [ReadableState],
[00:36:28.008] _maxListeners: undefined,
[00:36:28.008] _writableState: [WritableState],
[00:36:28.008] allowHalfOpen: false,
[00:36:28.008] _sockname: null,
[00:36:28.008] _pendingData: null,
[00:36:28.008] _pendingEncoding: '',
[00:36:28.008] server: undefined,
[00:36:28.008] _server: null,
[00:36:28.008] ssl: null,
[00:36:28.008] _requestCert: true,
[00:36:28.008] _rejectUnauthorized: true,
[00:36:28.008] parser: null,
[00:36:28.008] _httpMessage: [Circular *1],
[00:36:28.009] write: [Function: writeAfterFIN],
[00:36:28.009] [Symbol(res)]: null,
[00:36:28.009] [Symbol(verified)]: true,
[00:36:28.009] [Symbol(pendingSession)]: null,
[00:36:28.009] [Symbol(async_id_symbol)]: 2096,
[00:36:28.009] [Symbol(kHandle)]: null,
[00:36:28.009] [Symbol(lastWriteQueueSize)]: 0,
[00:36:28.009] [Symbol(timeout)]: null,
[00:36:28.009] [Symbol(kBuffer)]: null,
[00:36:28.009] [Symbol(kBufferCb)]: null,
[00:36:28.009] [Symbol(kBufferGen)]: null,
[00:36:28.009] [Symbol(kCapture)]: false,
[00:36:28.009] [Symbol(kSetNoDelay)]: false,
[00:36:28.009] [Symbol(kSetKeepAlive)]: true,
[00:36:28.009] [Symbol(kSetKeepAliveInitialDelay)]: 60,
[00:36:28.009] [Symbol(kBytesRead)]: 1500,
[00:36:28.009] [Symbol(kBytesWritten)]: 190,
[00:36:28.010] [Symbol(connect-options)]: [Object]
[00:36:28.010] },
[00:36:28.010] _header: 'GET /api/posts HTTP/1.1\r\n' +
[00:36:28.010] 'Accept: application/json, text/plain, */*\r\n' +
[00:36:28.010] 'User-Agent: axios/1.4.0\r\n' +
[00:36:28.010] 'Accept-Encoding: gzip, compress, deflate, br\r\n' +
[00:36:28.010] 'Host: dropconnect.vercel.app\r\n' +
[00:36:28.010] 'Connection: close\r\n' +
[00:36:28.011] '\r\n',
[00:36:28.011] _keepAliveTimeout: 0,
[00:36:28.011] _onPendingData: [Function: nop],
[00:36:28.011] agent: Agent {
[00:36:28.011] _events: [Object: null prototype],
[00:36:28.011] _eventsCount: 2,
[00:36:28.011] _maxListeners: undefined,
[00:36:28.011] defaultPort: 443,
[00:36:28.011] protocol: 'https:',
[00:36:28.011] options: [Object: null prototype],
[00:36:28.011] requests: [Object: null prototype] {},
[00:36:28.011] sockets: [Object: null prototype] {},
[00:36:28.011] freeSockets: [Object: null prototype] {},
[00:36:28.011] keepAliveMsecs: 1000,
[00:36:28.012] keepAlive: false,
[00:36:28.012] maxSockets: Infinity,
[00:36:28.012] maxFreeSockets: 256,
[00:36:28.012] scheduling: 'lifo',
[00:36:28.012] maxTotalSockets: Infinity,
[00:36:28.012] totalSocketCount: 0,
[00:36:28.012] maxCachedSessions: 100,
[00:36:28.012] _sessionCache: [Object],
[00:36:28.012] [Symbol(kCapture)]: false
[00:36:28.012] },
[00:36:28.012] socketPath: undefined,
[00:36:28.012] method: 'GET',
[00:36:28.012] maxHeaderSize: undefined,
[00:36:28.012] insecureHTTPParser: undefined,
[00:36:28.012] joinDuplicateHeaders: undefined,
[00:36:28.012] path: '/api/posts',
[00:36:28.013] _ended: true,
[00:36:28.013] res: IncomingMessage {
[00:36:28.013] _readableState: [ReadableState],
[00:36:28.013] _events: [Object: null prototype],
[00:36:28.014] _eventsCount: 4,
[00:36:28.014] _maxListeners: undefined,
[00:36:28.014] socket: [TLSSocket],
[00:36:28.014] httpVersionMajor: 1,
[00:36:28.015] httpVersionMinor: 1,
[00:36:28.015] httpVersion: '1.1',
[00:36:28.015] complete: true,
[00:36:28.015] rawHeaders: [Array],
[00:36:28.015] rawTrailers: [],
[00:36:28.015] joinDuplicateHeaders: undefined,
[00:36:28.015] aborted: false,
[00:36:28.015] upgrade: false,
[00:36:28.015] url: '',
[00:36:28.015] method: null,
[00:36:28.015] statusCode: 404,
[00:36:28.015] statusMessage: 'Not Found',
[00:36:28.015] client: [TLSSocket],
[00:36:28.015] _consuming: true,
[00:36:28.015] _dumped: false,
[00:36:28.015] req: [Circular *1],
[00:36:28.015] responseUrl: 'https://dropconnect.vercel.app/api/posts',
[00:36:28.016] redirects: [],
[00:36:28.016] [Symbol(kCapture)]: false,
[00:36:28.016] [Symbol(kHeaders)]: [Object],
[00:36:28.016] [Symbol(kHeadersCount)]: 30,
[00:36:28.016] [Symbol(kTrailers)]: null,
[00:36:28.016] [Symbol(kTrailersCount)]: 0
[00:36:28.016] },
[00:36:28.016] aborted: false,
[00:36:28.016] timeoutCb: null,
[00:36:28.016] upgradeOrConnect: false,
[00:36:28.016] parser: null,
[00:36:28.016] maxHeadersCount: null,
[00:36:28.016] reusedSocket: false,
[00:36:28.016] host: 'dropconnect.vercel.app',
[00:36:28.016] protocol: 'https:',
[00:36:28.016] _redirectable: Writable {
[00:36:28.016] _writableState: [WritableState],
[00:36:28.017] _events: [Object: null prototype],
[00:36:28.017] _eventsCount: 3,
[00:36:28.017] _maxListeners: undefined,
[00:36:28.017] _options: [Object],
[00:36:28.017] _ended: true,
[00:36:28.017] _ending: true,
[00:36:28.017] _redirectCount: 0,
[00:36:28.017] _redirects: [],
[00:36:28.017] _requestBodyLength: 0,
[00:36:28.017] _requestBodyBuffers: [],
[00:36:28.017] _onNativeResponse: [Function (anonymous)],
[00:36:28.017] _currentRequest: [Circular *1],
[00:36:28.017] _currentUrl: 'https://dropconnect.vercel.app/api/posts',
[00:36:28.017] [Symbol(kCapture)]: false
[00:36:28.017] },
[00:36:28.017] [Symbol(kCapture)]: false,
[00:36:28.017] [Symbol(kBytesWritten)]: 0,
[00:36:28.018] [Symbol(kNeedDrain)]: false,
[00:36:28.018] [Symbol(corked)]: 0,
[00:36:28.018] [Symbol(kOutHeaders)]: [Object: null prototype] {
[00:36:28.018] accept: [Array],
[00:36:28.018] 'user-agent': [Array],
[00:36:28.018] 'accept-encoding': [Array],
[00:36:28.018] host: [Array]
[00:36:28.018] },
[00:36:28.018] [Symbol(errored)]: null,
[00:36:28.018] [Symbol(kUniqueHeaders)]: null
[00:36:28.018] },
[00:36:28.018] response: {
[00:36:28.018] status: 404,
[00:36:28.018] statusText: 'Not Found',
[00:36:28.018] headers: AxiosHeaders {
[00:36:28.018] 'access-control-allow-origin': '*',
[00:36:28.018] age: '424',
[00:36:28.019] 'cache-control': 'public, max-age=0, must-revalidate',
[00:36:28.019] 'content-disposition': 'inline; filename="404"',
[00:36:28.019] 'content-type': 'text/html; charset=utf-8',
[00:36:28.019] date: 'Tue, 25 Jul 2023 19:06:27 GMT',
[00:36:28.019] etag: 'W/"38cd104fd7654933c13ecd14fe3bb23a"',
[00:36:28.019] server: 'Vercel',
[00:36:28.019] 'strict-transport-security': 'max-age=63072000; includeSubDomains; preload',
[00:36:28.019] 'x-matched-path': '/404',
[00:36:28.019] 'x-vercel-cache': 'HIT',
[00:36:28.019] 'x-vercel-id': 'iad1::ld85f-1690311987976-439f46b5306b',
[00:36:28.019] connection: 'close',
[00:36:28.019] 'transfer-encoding': 'chunked'
[00:36:28.019] },
[00:36:28.019] config: {
[00:36:28.019] transitional: [Object],
[00:36:28.019] adapter: [Array],
[00:36:28.019] transformRequest: [Array],
[00:36:28.020] transformResponse: [Array],
[00:36:28.020] timeout: 0,
[00:36:28.020] xsrfCookieName: 'XSRF-TOKEN',
[00:36:28.020] xsrfHeaderName: 'X-XSRF-TOKEN',
[00:36:28.020] maxContentLength: -1,
[00:36:28.020] maxBodyLength: -1,
[00:36:28.020] env: [Object],
[00:36:28.020] validateStatus: [Function: validateStatus],
[00:36:28.020] headers: [AxiosHeaders],
[00:36:28.020] method: 'get',
[00:36:28.020] url: 'https://dropconnect.vercel.app/api/posts',
[00:36:28.020] data: undefined
[00:36:28.020] },
[00:36:28.020] request: <ref *1> ClientRequest {
[00:36:28.020] _events: [Object: null prototype],
[00:36:28.020] _eventsCount: 7,
[00:36:28.021] _maxListeners: undefined,
[00:36:28.021] outputData: [],
[00:36:28.021] outputSize: 0,
[00:36:28.021] writable: true,
[00:36:28.021] destroyed: true,
[00:36:28.021] _last: true,
[00:36:28.021] chunkedEncoding: false,
[00:36:28.021] shouldKeepAlive: false,
[00:36:28.021] maxRequestsOnConnectionReached: false,
[00:36:28.021] _defaultKeepAlive: true,
[00:36:28.021] useChunkedEncodingByDefault: false,
[00:36:28.021] sendDate: false,
[00:36:28.021] _removedConnection: false,
[00:36:28.021] _removedContLen: false,
[00:36:28.021] _removedTE: false,
[00:36:28.021] strictContentLength: false,
[00:36:28.021] _contentLength: 0,
[00:36:28.021] _hasBody: true,
[00:36:28.022] _trailer: '',
[00:36:28.022] finished: true,
[00:36:28.022] _headerSent: true,
[00:36:28.022] _closed: true,
[00:36:28.022] socket: [TLSSocket],
[00:36:28.022] _header: 'GET /api/posts HTTP/1.1\r\n' +
[00:36:28.022] 'Accept: application/json, text/plain, */*\r\n' +
[00:36:28.022] 'User-Agent: axios/1.4.0\r\n' +
[00:36:28.022] 'Accept-Encoding: gzip, compress, deflate, br\r\n' +
[00:36:28.022] 'Host: dropconnect.vercel.app\r\n' +
[00:36:28.022] 'Connection: close\r\n' +
[00:36:28.022] '\r\n',
[00:36:28.022] _keepAliveTimeout: 0,
[00:36:28.022] _onPendingData: [Function: nop],
[00:36:28.022] agent: [Agent],
[00:36:28.022] socketPath: undefined,
[00:36:28.023] method: 'GET',
[00:36:28.023] maxHeaderSize: undefined,
[00:36:28.023] insecureHTTPParser: undefined,
[00:36:28.023] joinDuplicateHeaders: undefined,
[00:36:28.023] path: '/api/posts',
[00:36:28.023] _ended: true,
[00:36:28.023] res: [IncomingMessage],
[00:36:28.023] aborted: false,
[00:36:28.023] timeoutCb: null,
[00:36:28.023] upgradeOrConnect: false,
[00:36:28.024] parser: null,
[00:36:28.024] maxHeadersCount: null,
[00:36:28.024] reusedSocket: false,
[00:36:28.024] host: 'dropconnect.vercel.app',
[00:36:28.024] protocol: 'https:',
[00:36:28.024] _redirectable: [Writable],
[00:36:28.024] [Symbol(kCapture)]: false,
[00:36:28.024] [Symbol(kBytesWritten)]: 0,
[00:36:28.024] [Symbol(kNeedDrain)]: false,
[00:36:28.024] [Symbol(corked)]: 0,
[00:36:28.024] [Symbol(kOutHeaders)]: [Object: null prototype],
[00:36:28.024] [Symbol(errored)]: null,
[00:36:28.024] [Symbol(kUniqueHeaders)]: null
[00:36:28.024] },
[00:36:28.024] data: '<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/_next/static/chunks/webpack-92754179cd20598c.js" defer=""></script><script src="/_next/static/chunks/framework-8883d1e9be70c3da.js" defer=""></script><script src="/_next/static/chunks/main-a12802a46038f17d.js" defer=""></script><script src="/_next/static/chunks/pages/_app-52924524f99094ab.js" defer=""></script><script src="/_next/static/chunks/pages/_error-c92d5c4bb2b49926.js" defer=""></script><script src="/_next/static/qfvK-D30q5wNwyttqQ8cC/_buildManifest.js" defer=""></script><script src="/_next/static/qfvK-D30q5wNwyttqQ8cC/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"qfvK-D30q5wNwyttqQ8cC","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>'
[00:36:28.024] }
[00:36:28.025] }
[00:36:28.026]
[00:36:28.026] Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
[00:36:28.026] AxiosError: Request failed with status code 404
[00:36:28.026] at settle (/vercel/path0/.next/server/chunks/228.js:32264:16)
[00:36:28.026] at BrotliDecompress.handleStreamEnd (/vercel/path0/.next/server/chunks/228.js:33220:21)
[00:36:28.026] at BrotliDecompress.emit (node:events:525:35)
[00:36:28.026] at endReadableNT (node:internal/streams/readable:1359:12)
[00:36:28.026] at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
[00:36:28.461] prisma:query SELECT "public"."Post"."id", "public"."Post"."title", "public"."Post"."content", "public"."Post"."noLikes", "public"."Post"."noComments", "public"."Post"."authorId" FROM "public"."Post" WHERE 1=1 OFFSET $1
[00:36:28.468] - info Generating static pages (7/7)
[00:36:28.473]
[00:36:28.473] > Export encountered errors on following paths:
[00:36:28.473] /page: /
[00:36:28.525] Error: Command "npx prisma generate && next build" exited with 1
型
任何帮助这是赞赏。
2条答案
按热度按时间1dkrff031#
出现此错误是因为
localhost
在vercel上不可用,并且您也是一个custom domain
,这也是未定义的,因为域在部署的最后阶段连接,但您的代码是SSG
,也是一个server component
。你需要在你的服务器组件中直接使用这个代码。。
字符串
wwtsj6pe2#
这就是我解决这个问题的方法。
我删除了
app/page.tsx
中的所有内容,返回了一个带有h1标记的简单组件。在那之后,我推送了代码,并在Vercel上部署,没有任何错误。后来,我将问题中分享的相同代码写入app/page.tsx
,并将其推送到GitHub。部署没有任何问题。我猜测Vercel和Next正在检查代码并尝试Axios GET请求,由于
npm build
命令尚未创建/app/api/posts/route.tsx
文件,因此该请求失败。通过做我所做的,在第一次部署中,路由被创建,然后在第二次部署中,API路由在那里,因此Axios没有抛出任何错误。