ilrock
ilrock

Reputation: 593

How to deploy Nuxt SSR app to firebase through cloud functions?

I followed this medium post as a guide to host my nuxt app on firebase hosting.

The deploy goes through, however, when I then visit the url I get a Cannot GET / error message. If I check the function logs I see that the function completes with a 404 error.

This is my functions/index.js

const functions = require('firebase-functions')
const admin = require("firebase-admin")
const { Nuxt } = require('nuxt-start')
const nuxtConfig = require('./nuxt.config.js')

admin.initializeApp()

const config = {
  ...nuxtConfig,
  dev: false,
  debug: true,
  buildDir: "nuxt",
  publicPath: "public",
}

const nuxt = new Nuxt(config)

exports.ssrapp = functions.https.onRequest(async (req, res) => {
  await nuxt.ready()
  nuxt.render(req, res)
})

And this is the firebase configuration

{
  "functions": {
    "source": "functions",
    "predeploy": [
      "npm --prefix src run build && rm -rf functions/nuxt && cp -r src/nuxt/ functions/nuxt/ && cp src/nuxt.config.js functions/"
    ]
  },
  "hosting": {
    "predeploy": [
      "rm -rf public/* && mkdir -p public/_nuxt && cp -a src/nuxt/dist/client/. public/_nuxt && cp -a src/static/. public/ && cp -a public_base/. public/"
    ],
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "function": "ssrapp"
      }
    ]
  }
}

The project structure is this

/
 /src
 /functions
 /public
 /public_base

When I run firebase deploy I do see the content of /src being copied to /functions/nuxt. For the sake of testing I also have my /functions/package.json file include all the dependencies that I have in my /src/package.json file.

How can I get this app up and running? If you need any more details, let me know.

Update #1

I tried serving hosting and functions using the command firebase serve --only functions,hosting -p 5004.

Running the server like so gave me some more insights. Specifically I got this warning message at load time that then resulted in actual error message when loading the page.

WARN  Module @firebase/app not found. Silently ignoring module as programatic usage detected

I didn't install this package in the functions directory as I did not have it in my src directory either. However, after installing it inside /functions and restarting the dev server, that warning message was gone and with it also the error I was getting on page load.

I also spotted a couple of warnings that had to do with vue, vue-server-renderer and vue-template-compiler not running the same version.

Now everything seems to be working fine!

Upvotes: 8

Views: 4643

Answers (3)

Luigi
Luigi

Reputation: 314

the following works for me (using nuxt-start instead):

const functions = require("firebase-functions");
const { Nuxt } = require("nuxt-start");

const config = {
  dev: false
};

const nuxt = new Nuxt(config);

let isReady = false;

async function handleRequest(req, res) {
  if (!isReady) {
    try {
      isReady = await nuxt.ready();
    } catch (error) {
      process.exit(1);
    }
  }
  await nuxt.render(req, res);
}

exports.nuxtssr = functions.https.onRequest(handleRequest);

Upvotes: 0

Florian Pallas
Florian Pallas

Reputation: 582

Your config and structure look right.

I also did this about a year ago with my app and I ran into the same problem. It has to do with the function code itself. I also tried using nuxt.render(req, res) (Docs) but it never worked for me so I ended up using nuxt.renderRoute(route) (Docs) instead. This worked perfectly fine.

You could change your code to something like this:

const { Nuxt } = require('nuxt')

...

exports.ssrapp = functions.https.onRequest(async (req, res) => {
  await nuxt.ready()

  const result = await nuxt.renderRoute(req.path) // Returns { html, error, redirected }
  res.send(result.html) // Sends html as response
})

This worked for me. You should consider catching any errors though. I hope this solves your problem.

This is only a work-around, if anyone knows why nuxt.render isn't working, I would be interested to know. I wasted many hours because of this with my app...

Upvotes: 3

ilrock
ilrock

Reputation: 593

I tried serving hosting and functions locally using the command firebase serve --only functions,hosting -p 5004.

By doing this I was able to spot a bunch of warnings and errors such as

FATAL 

Vue packages version mismatch:

- [email protected]
- [email protected]

This may cause things to work incorrectly. Make sure to use the same version for both.

WARN  Module @firebase/app not found. Silently ignoring module as programatic usage detected

I then made sure that those vue packages were indeed running the same version. Then I also added the @firebase/app package in /functions/package.json (that however, is not present in /src/package.json.

I run the local server again and everything worked. I then deployed to firebase and everything was working as expected.

Upvotes: 2

Related Questions