artooras
artooras

Reputation: 6805

Firebase Functions do not build Next.js project when deployed

I'm able to deploy my Next.js project to Firebase Functions successfully as per this post. However, when I try to visit my project in the browser, I get a Error: could not handle the request error, and in the Functions log I see this error message:

Error: Could not find a production build in the '/workspace/.next' directory. Try building your app with 'next build' before starting the production server. https://nextjs.org/docs/messages/production-start-no-build-id
    at Server.readBuildId (/workspace/node_modules/next/dist/next-server/server/next-server.js:151:355)
    at new Server (/workspace/node_modules/next/dist/next-server/server/next-server.js:3:120)
    at NextServer.createServer (/workspace/node_modules/next/dist/server/next.js:1:2935)
    at process._tickCallback (internal/process/next_tick.js:68:7)

I'm not sure how to resolve this though... Adding below my config files:

package.json

{
  "main": "server.js", // my next.js app init file
  "scripts": {
    "dev": "FIREBASE_AUTH_EMULATOR_HOST=localhost:9099 next dev",
    "start": "next start",
    "build": "next build",
    "build:functions": "tsc",
    "lint": "npm run lint:next && npm run lint:functions",
    "lint:functions": "eslint --ext .js",
    "lint:next": "next lint",
    "deploy": "firebase deploy --only database,hosting,functions:nextServer",
    "emulate": "firebase emulators:start --import=./emulator-data --export-on-exit",
    "test": "jest --runInBand --detectOpenHandles",
    "cypress": "cypress open"
  },
  "dependencies": {
    // including next
  }
}

firebase.json

{
  "functions": {
    "source": ".",
    "runtime": "nodejs10",
    "ignore": [
      "**/.next/cache/**",
      "**/__tests__/**",
      "**/components/**",
      "**/cypress/**",
      "**/emulator-data/**",
      "**/functions/**",
      "**/layouts/**",
      "**/node_modules/**",
      "**/pages/**",
      "**/public/**",
      "**/utils/**",
      "**/.*",
      "**/*.log",
      "**/cypress.json",
      "**/database.rules.json",
      "**/firebase.json"
    ],
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build:functions"
    ]
  },
  "hosting": {
    "target": "my_app",
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [{
      "source": "**",
      "function": "nextServer"
    }]
  }
}

I assume that, once deployed, Firebase Functions environment would run npm run build and npm run start scripts. Or is the workflow different? Perhaps my scripts are incorrect?

Upvotes: 0

Views: 1997

Answers (2)

Vladimir Valse
Vladimir Valse

Reputation: 1

I was this error, my solution was:

First, in the packege.json file, in the section scripts, we must modify the property “build”: "next build && next export", and a new property "export": "next export"

Second, we must establish the component and data folders in the root of the project

Third: use the command: a)You must make log in, so type: firebase login

  b)select de option "Configure files for Firebase Hosting and (optionally) set 
                      up GitHub Action deploys"
  c)in the question:  if you have a build process 
                      for your assets, use your build's output directory?
                      What do you want to use as your public directory?
     
     You must type:   out  (really important, it's a folder output) 
  d) You must type:   npm run build
  f) last step: type: firebase deploy

package.json out folder

Upvotes: 0

samthecodingman
samthecodingman

Reputation: 26256

Similar to scripts in package.json files, the predeploy and postdeploy lines are executed before and after a call to firebase deploy when using the Firebase CLI (documented here).

When the Firebase CLI uploads your code to the Cloud Functions staging servers, it is expected to have already been compiled and only needs its runtime dependencies installed. Once an upload has completed, the staging server will execute npm install --production and then prepare your function to handle requests (essentially performing a cold-start, without actually executing the function). If either step fails, you will be shown an error like you have. If both steps succeed, your code with the dependencies installed is persisted as an image and saved to Cloud Storage, ready to use when requests to be handled come in.

In your case, the error seems to be that your .next folder is missing the compiled version of your application.

There are two possible causes of this, either your build prior to deployment is incomplete or when your files are uploaded, something in your ignore list that is required by the deployed code is missing.

For the first part, you modified the predeploy hook in my previous answer from:

{
  "functions": {
    "source": ".",
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  },
  ...
}

incorrectly to:

{
  "functions": {
    "source": ".",
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build:functions"
    ]
  },
  ...
}

By changing this, you aren't building your next app prior to deploying the code to the staging server.

In regards to the second part, the deployed next application may be missing some of its dependencies - you can either fine tune the ignore list or you can perform the next build step on the server using a postinstall script in your package.json file:

{
  "main": "server.js", // my next.js app init file
  "scripts": {
    ...
    "build:next": "next build",
    ...
    "postinstall": "npm run build:next"
  },
  "dependencies": {
    // including next
  }
}

Note: If your main file is just JavaScript, you no longer need the typescript compile step defined in npm run build:functions and it can be removed.

Upvotes: 2

Related Questions