问题描述
遵循一些教程 像这个,我能够将我的 Next.js
应用程序部署到 Firebase 托管/功能.这是我的项目的简化文件夹结构:
Following a few tutorials like this one, I was able to deploy my Next.js
app to Firebase Hosting/Functions. Here's the reduced folder structure of my project:
myApp
node_modules // Next.js app dependencies
.next // destination of npm run build of the Next.js project
pages // Next.js pages
functions
lib // this is where the functions compile
node_modules // functions' dependencies
src
app.ts
index.ts
other.ts
package.json
public // Next.js app public files
firebase.json
package.json
...
当我运行 firebase deploy
时,它会将 functions
编译到它的 lib
文件夹中并成功部署所有内容.
When I run firebase deploy
, it compiles functions
into its lib
folder and deploys everything successfully.
但是,当我尝试访问我的网络应用程序的 url 时,我得到 Error: could not handle the request
.当我查看 Firebase Functions 日志时,我可以看到一条错误提示 Error: Cannot find module 'react'
.因此,我再次成功地将 react
添加到 functions/package.json
、npm install
和 firebase deploy
.但是,另一个错误,但这次它说 Cannot find module 'react-dom'
.
However, when I try to visit the url of my web app, I get Error: could not handle the request
. When I looked into the Firebase Functions log, I can see an error saying Error: Cannot find module 'react'
. So, I added react
to functions/package.json
, npm install
and firebase deploy
successfully again. However, another error, but this time it says Cannot find module 'react-dom'
.
我的理解是,这样做的原因是我的 Next.js 应用程序依赖于我的 root
文件夹中的 package.json
中列出的所有依赖项(减少了下面列出):
My understanding is that the reason for this is that my Next.js app relies on all the dependencies listed in my package.json
in my root
folder (a reduced list below):
"dependencies": {
"babel-plugin-prismjs": "^2.1.0",
"firebase": "^8.8.1",
"firebase-admin": "^9.11.0",
"formik": "^2.2.9",
"js-cookie": "^3.0.0",
"next": "11.0.1",
"next-i18next": "^8.5.5",
"nookies": "^2.5.2",
"prismjs": "^1.24.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-ga": "^3.3.0",
"react-select": "^4.3.1",
"react-spinners": "^0.11.0",
"react-transition-group": "^4.4.2",
"recharts": "^2.0.10",
"styled-components": "^5.3.0",
"yup": "^0.32.9"
}
而我的 functions/package.json
显然要短得多:
while my functions/package.json
was, obviously, much shorter:
"dependencies": {
"@sendgrid/mail": "^7.4.4",
"firebase-admin": "^9.8.0",
"firebase-functions": "^3.14.1",
"next": "^11.0.1",
"react": "^17.0.2"
}
我假设错误会要求我将所有依赖项复制到 functions/package.json
文件中,这显然是我不想要的.
I assume the errors would have asked me to duplicate all the dependencies into the functions/package.json
file, which I obviously don't want.
或者,我可以将 firebase-functions
和 functions/package.json
中的其他相关依赖项添加到 root/package.json
,并且在根文件夹中也有下一个服务器设置.但是,如何包含其他现有的云功能?
Alternatively, I can add firebase-functions
and other relevant dependencies from functions/package.json
to root/package.json
, and have the next server setup in the root folder as well. However, how do I include the other existing cloud functions?
我的 functions/src
文件的内容如下所示:
Here's how the contents of my functions/src
files look:
index.ts
import * as admin from 'firebase-admin'
admin.initializeApp()
export * from './app' // next.js
export * from './other'
other.ts
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
exports.onUserCreate = functions.database.ref...
// my other cloud functions, such as db triggers, https functions, etc.
app.ts
import next from 'next'
import {https} from 'firebase-functions'
const server = next({
dev: process.env.NODE_ENV !== 'production',
conf: {distDir: '.next'}
})
const nextjsHandler = server.getRequestHandler()
exports.app = https.onRequest(async (req, res) => {
await server.prepare()
return await nextjsHandler(req, res)
})
另外,这是我的 firebase.json
:
{
"functions": {
"predeploy": [
"npm --prefix "$RESOURCE_DIR" run lint",
"npm --prefix "$RESOURCE_DIR" run build"
]
},
"hosting": {
"target": "myApp",
"public": "public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [{
"source": "**",
"function": "app"
}]
}
}
如何正确部署 Next.js
应用并确保我的其他云功能继续工作?
How do I deploy the Next.js
app correctly and make sure my other cloud functions continue to work?
谢谢!
推荐答案
虽然您可以将 /functions
目录提升到项目的根目录,但这意味着您的其他函数不必要地臃肿Next.js
应用程序的依赖项.
While you could lift the /functions
directory to your project's root directory, this would mean that your other functions are unnecessarily bloated with all of your Next.js
app's dependencies.
当您部署云函数时,配置的部署目录(默认为 /functions
)中的所有内容都会被部署 - 即使您不使用它.它也为每个功能部署一次.因此,如果您的函数目录中有一个 10MB 的文件,则每个函数的部署大小将增加 10MB.这就是我所说的腹胀".一个函数.
When you deploy a Cloud Function, everything in the configured deployment directory (/functions
by default) is deployed - even if you don't use it. It is also deployed once for each function. So if you had a 10MB file to your functions directory, every function's deployed size would increase by 10MB. This is what I mean by "bloating" a function.
仅供参考:您可以通过将以下内容添加到您的 firebase.json
文件(docs):
FYI: You can change the deployed functions directory by adding the following to your firebase.json
file (docs):
"functions": {
"source": "." // <- the project's root directory
}
相反,您应该使用部分部署.在这种情况下,您需要将 app.ts
移动到 Next 项目的目录中,并将其他不依赖于 Next 部署的函数留在 /functions
文件夹中.如果您部署整个项目目录,即使您不使用它,您最终也会部署 /functions
,因此您应该将 Next 前端和函数移动到它自己的文件夹中.
Instead, you should make use of partial deployment. In this situation you'd move app.ts
to your Next project's directory and leave the other functions that don't depend on your Next deployment in the /functions
folder. If you deploy your entire project directory, you will end up deploying /functions
too even though you don't use it, so you should instead move your Next front-end and functions into its own folder.
文件结构类似于(详情如下):
The file structure will look similar to (details below):
/myApp
/functions
/lib // this is where the functions compile
/node_modules // functions' dependencies
/src
index.ts
other.ts
firebase.json // configuration for this folder's contents
package.json // configuration for this folder's contents
/next
/node_modules // Next.js app dependencies
/.next // compiled Next.js project
/pages // Next.js pages
/public // Next.js app public files
/functions-lib
app.js // compiled Next function
/functions-src
app.ts // source of Next function
firebase.json // configuration for this folder's contents
package.json // configuration for this folder's contents
...
您的 /functions
文件夹的 firebase.json
文件类似于:
Your /functions
folder's firebase.json
file would look similar to:
{
"functions": {
"source": ".",
"predeploy": [
"npm --prefix "$RESOURCE_DIR" run lint",
"npm --prefix "$RESOURCE_DIR" run build"
]
}
}
要使上述结构正常运行,您需要调整 firebase.json
和 package.json
文件的配置.
To get the above structure to behave properly, you need to tweak the configuration of the firebase.json
and package.json
files.
将以下内容添加到 /function
文件夹的 package.json
文件中:
Add the following to the /function
folder's package.json
file:
"scripts": {
"deploy": "firebase deploy --only functions:otherFunc1,functions:otherFunc2",
...
}
您也可以将这些函数导出为单个组以便于部署,但函数将命名为 otherFunctions-otherFunc1
、otherFunctions-otherFunc2
等:
You could also export these functions as a single group for easy deployment, but the functions will be named like otherFunctions-otherFunc1
, otherFunctions-otherFunc2
, and so on:
// index.ts
import * as otherFunctions from './other.ts';
export { otherFunctions };
// package.json
"scripts": {
"deploy": "firebase deploy --only functions:otherFunctions",
...
}
您的 /next
文件夹的 firebase.json
文件类似于:
Your /next
folder's firebase.json
file would look similar to:
{
"functions": {
"source": ".",
"predeploy": [
"npm --prefix "$RESOURCE_DIR" run lint",
"npm --prefix "$RESOURCE_DIR" run build"
]
},
"hosting": {
"target": "myApp",
"public": "public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [{
"source": "**",
"function": "app"
}]
}
}
将以下(或类似内容)添加到 /next
文件夹的 package.json
文件中:
Add the following (or similar) to the /next
folder's package.json
file:
"scripts": {
"build": "npm run build:next && npm run build:functions",
"build:functions": "tsc",
"build:next": "next build",
"lint": "npm run lint:next && npm run lint:functions",
"lint:functions": "eslint --ext .js,.ts ./functions-src",
"lint:next": "...",
"deploy": "firebase deploy --only hosting,functions:app"
}
通过上述更改,放入适当的目录并在使用 firebase deploy
时使用 npm run deploy
.
With the above changes, drop into the appropriate directory and use npm run deploy
whenever you would use firebase deploy
.
注意:不要忘记 Cloud Functions 自动使用请求的主体,因此在 Next 项目中使用主体解析器并使用 next start
进行本地测试时,请确保考虑到这一点.
Note: Don't forget that Cloud Functions consume the bodies of requests automatically, so make sure you account for this when using body parsers in Next projects and testing locally with next start
.
这篇关于使用现有函数将 Next.js 应用部署到 Firebase Functions的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!