我有一个 NEXT.JS 项目(v13.5.6,使用 App Router),在 Google App Engine(标准)上运行,我在数据存储模式下使用 Google Firestore 来存储一些数据,并且在构建时所有这些都运行良好并在我的笔记本电脑(Windows)上本地运行该项目,但是当我尝试部署到 Google App Engine 时,它会抛出此错误:
Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 62 files to Google Cloud Storage ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Cloud build [hash] status: FAILURE
> [email protected] build
> next build
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry
Creating an optimized production build ...
✓ Compiled successfully
Linting and checking validity of types ...
Collecting page data ...
Generating static pages (0/19) ...
Generating static pages (4/19)
Generating static pages (9/19)
Generating static pages (14/19)
Error occurred prerendering page "/robots.txt". Read more: https://nextjs.org/docs/messages/prerender-error
Error: 7 PERMISSION_DENIED: Missing or insufficient permissions.
at callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:192:76)
at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:360:141)
at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:323:181)
at /workspace/node_modules/@grpc/grpc-js/build/src/resolving-call.js:99:78
at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
for call at
at ServiceClientImpl.makeUnaryRequest (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:160:32)
at ServiceClientImpl.<anonymous> (/workspace/node_modules/@grpc/grpc-js/build/src/make-client.js:105:19)
at /workspace/node_modules/@google-cloud/datastore/build/src/v1/datastore_client.js:224:29
at /workspace/node_modules/google-gax/build/src/normalCalls/timeout.js:44:16
at repeat (/workspace/node_modules/google-gax/build/src/normalCalls/retries.js:80:25)
at /workspace/node_modules/google-gax/build/src/normalCalls/retries.js:118:13
at OngoingCall.call (/workspace/node_modules/google-gax/build/src/call.js:67:27)
at NormalApiCaller.call (/workspace/node_modules/google-gax/build/src/normalCalls/normalApiCaller.js:34:19)
at /workspace/node_modules/google-gax/build/src/createApiCall.js:84:30
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
✓ Generating static pages (19/19)
> Export encountered errors on following paths:
/robots.txt/route: /robots.txt
Full build logs: https://console.cloud.google.com/cloud-build/builds;region=[region]/[hash]?project=[project-id]
据我了解,数据存储应该可以从App Engine访问,因为它们位于同一个Google项目中,我不需要为其创建单独的服务/凭据,并且它对于应用程序中的所有页面都运行良好app/ 文件夹,但不适用于 api/ 或 robots.ts、sitemap.ts、manifest.ts 中的route.ts 文件。
这是我的package.json
{
"name": "myproject",
"version": "3.1.0",
"description": "...description...",
"private": true,
"author": "Ivan Melnyk",
"main": "next start",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"deploy": "gcloud app deploy"
},
"dependencies": {
"@google-cloud/datastore": "^8.2.1",
"cookies-next": "^4.0.0",
"date-fns": "^2.30.0",
"next": "^13.5.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.11.0",
"server-only": "^0.0.1",
"sharp": "^0.32.6"
},
"devDependencies": {
"@types/node": "20.6.5",
"@types/react": "18.2.22",
"autoprefixer": "^10.4.16",
"cssnano": "^6.0.1",
"eslint-config-next": "^13.5.3",
"eslint-config-prettier": "^9.0.0",
"postcss": "^8.4.30",
"sass": "^1.68.0",
"tailwindcss": "^3.3.3",
"typescript": "5.2.2"
}
}
这是 robots.ts
import { General } from 'data'
export default async function robots() {
const data = await General()
return {
rules: {
userAgent: '*',
// disallow: '/'
allow: '/',
disallow: '/email',
},
sitemap: `${data.url}/sitemap.xml`,
}
}
这是data.ts中General函数的代码
import 'server-only'
import { Datastore } from '@google-cloud/datastore'
export async function General() {
const datastore = new Datastore()
const [[records]] = await datastore.runQuery(datastore.createQuery('general'))
return records
}
数据存储中的“常规”表只有一行字段(如配置)。
任何route.ts(即api/*/route.ts、./robots.ts、./sitemap.ts、./manifest.ts)都可以重现同样的问题。
我也尝试在 api/ 文件夹中创建一条路由,然后在 next.config.js 中重写 - 没有帮助。
我做错了什么?
相同的代码在我的笔记本电脑(Windows)上运行良好。我正在连接到 Google Cloud(生产)上的同一个数据存储数据库,而不是模拟器。
找到解决方案,与Google Cloud无关。 最新的 Next.js 版本(目前为 13.5.6)在 Windows 中构建和上传到 Linux(如 Google AppEngine VM)时存在反斜杠问题。 我过去没有解决这个问题的方法,所以我决定在 AppEngine 上运行构建。 截至今天,这个问题有一个临时修复,描述在这里,我已经应用了这个修复,现在我不需要在 AppEngine 上远程构建我的包,我在本地构建并将构建文件上传到 AppEngine,并且它运行良好,反斜杠没有问题,数据存储权限也没有问题。 希望它对其他人有帮助。