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
...
When I run firebase deploy, it compiles functions into its lib folder and deploys everything successfully.
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'.
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"
}
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"
}
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.
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?
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)
})
Also, here's my 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"
}]
}
}
How do I deploy the Next.js app correctly and make sure my other cloud functions continue to work?
Thanks!