How to host Nuxt.js application on firebase with a single command
Zigmas Slušnys

Zigmas Slušnys @slushnys

Location:
World
Joined:
Apr 10, 2019

How to host Nuxt.js application on firebase with a single command

Publish Date: Jan 12 '20
76 18

Introduction

I wished to copy a famous website that is lingering across Europe where people share their found deals with others and like that save money (its pepper.com in case anyone is wondering (not that i'm doing this as an ad or anything)).

Therefore I set myself with a task - to learn Nuxt.js as it is a server side rendered (SSR) framework that encapsulates a Node.js server with Vue.js and renders content that is possible to be crawled by google's crawlers in order to be indexed and listed on the search giant.

You can check the demo at:

https://dealas-962d3.firebaseapp.com/

You can fine the full repository at:

https://github.com/slushnys/dealas

Challenges I faced in order to finish my application

  • Understanding the lifecycles of SSR and how to inject data into a page for it to be rendered and be indexed.
  • Understand firebase functions.
  • Learn how to host the code and functions to the cloud on google firebase.

What I have learned

Async data

Even though it's pretty clear in the documentation of nuxt.js (https://nuxtjs.org/guide/async-data) that this method is to retrieve the data of certain resource before the component is rendered.

Also, at that point of time you don't have the access to this within that method, as per documentation:


You do
NOThave access of the component instance throughthisinside asyncData because it is called before initiating the component.

Another thing I learned the hard way is that the asyncData method for retrieving information is only called for a page being rendered, not a regular component where you might try to be filling a select box with data from your api.

Firebase functions

For this part you will need to install firebase under your global npm packages

npm i -g firebase-tools

don't forget to login to firebase after with

firebase login

I had previous experience with running google cloud functions with python language, however I've never made myself learn how do javascript functions run on demand in Google Cloud Platform. This was about to change because i was determined to have my website deployments automated so i wouldn't need to manually do all that work.

// functions/index.js

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

const nuxtConfig = require("./nuxt.config.js");

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

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.ssrapp = functions.https.onRequest(handleRequest);

You might think what is that nuxt-start pacakge you see at the beginning of the index.js file 🤔 Well it's a package that takes away the overhead and lets you start the package without many dependencies in production.

On top of that, we don't want to render the unfinished page, therefore on our request handler function handleRequest we wait to see if nuxt is ready and render the full page only then when it is.

Exporting ssrapp is the most important for our application to work on cloud as the each request will be handled by our handleRequest function which is assigned to our google functions onRequest event listener.

But wait... who's going to call the ssrapp function when it's on the cloud and when will google cloud function know which function to call?

Firebase configuration

In this section I'll discuss my learning points on deploying nuxt to the cloud which in my case - was my biggest painpoint to figuring out why my application doesn't work. Lets first take a look at my ./firebase.json configuration file.

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

There are different configurations for different services here as you can see by the keys of this dictionary, it includes - firestore, functions and hosting.

firestore keys' value includes the rules that you can set up for your firestore real time database. This should include your configuration to disable users reading your database for malicious purposes.

functions keys' value includes predeploy command, exactly this caused me the most of my troubles as I've taken this configuration from other tutorial I tried to apply to my use case. This resulted in my application crashing and not properly rendering when deployed.

hosting keys' value includes the predeployment script that takes files and uploads them to firebase hosting with a rewrite of source function to be the one we defined in our index.js file as ssrapp.

The reason my deployments were failing: this was actually pretty simple yet took me the longest to figure out. I have overwritten my nuxt.config.js buildDir default value of .nuxt/ to ../nuxt/. This in result caused some errors building some packages of 3rd party libraries I was using (especially Vuetify). I really hope this saves time to someone who's trying to deploy their website on firebase.

I haven't figured put much time soon after to figure out why the deployments weren't successful with a custom build directory of nuxt after I finally deployed my application, therefore I'm not going to contemplate on this.

Conclusion

It was a fun experience creating a Nuxt.js web application which is quite a powerful tool that one can use for basically any development needs, from a small website, to a bigger and meaner application release to production. Firebase also gives a very flexible real time database events that your application can listen on demand whenever certain action happens.

What challenges have you faced while trying to use Nuxt or Firebase? Let me know in the comment section.

Bonus

I've experimented with TypeScript so I refactored the repository to have typescript implementation of nuxt and new Vue 3 composition-api including it in ikelti.vue file if anyones interested in checking out how that integrates, i would be keep to receive some feedback.

Comments 18 total

  • Hina-softwareEngineer
    Hina-softwareEngineerJan 14, 2020

    Nice. But it's not in English

    • Zigmas Slušnys
      Zigmas SlušnysJan 14, 2020

      That's true, I'll have to introduce multiple languages. It's in Lithuanian right now.

  • Joshua
    JoshuaMar 18, 2020

    The function is looking for 3rd party libraries used in client.

    • Zigmas Slušnys
      Zigmas SlušnysMar 18, 2020

      Could you specify which function are you talking about and if that is a problem, and if so, what difficulties does it cause? Thanks

      • Joshua
        JoshuaMar 18, 2020

        The functions/index.js I got the same content as yours and when I try to deploy it and open in a browser it gives me this error

        FATAL Cannot find module '@nuxtjs/axios'

        . And this is my nuxt.config.js pastebin.com/LvxBi1yC

        • Zigmas Slušnys
          Zigmas SlušnysMar 18, 2020

          Did you build it with the non scripts provided in the src directory? Everything should be done with those scripts. If there are some missing dependencies it means the package.json may be missing something in functions directory.

          • Joshua
            JoshuaMar 18, 2020

            So do I have to add all of the 3rd party libraries installed inside the src/package.json into my functions/package.json?

  • joshuaholmes90
    joshuaholmes90Mar 18, 2020

    The commands are for linux? I'm having issues, i'm developing via Windows Visual Studio Code, how would I achieve this on Windows?

  • Kresimir Bojcic
    Kresimir BojcicApr 10, 2020

    Nice blogpost, but why is it so painfully slow?

  • Aonghas Anderson
    Aonghas AndersonMay 12, 2020

    Should the publicPath actually be a property of the build object?:

    const config = {
    ...nuxtConfig,
    dev: false,
    debug: false,
    buildDir: ".nuxt",
    build: {
    **publicPath: "public" <--- this property
    }
    };

    • Zigmas Slušnys
      Zigmas SlušnysMay 18, 2020

      I will have to get back to you on this one, I might have changed this, but check the repo I think it should be up to date.

  • skflowne
    skflowneMay 13, 2020

    Nice article very helpful !
    Did you manage to make font-awesome work with it though ?
    I can't get it to work with the "@nuxtjs/fontawesome" package, I followed their setup and it's working in dev but deployed icons do not display.
    Actually, they are here but they all have a size of 0x0, it's like some css is missing.

    • Zigmas Slušnys
      Zigmas SlušnysMay 18, 2020

      I'd say you have to include the icons you want to use with JavaScript, also depends on the package of icons you want to use, I think there are several types of fa icons available that you have to explicitly define

      • skflowne
        skflowneMay 19, 2020

        Yes, I got all the packages there and I can actually go into devtools and make them appear in prod if I change css.
        I would expect the package to add the css needed as part of the built assets in client but it's not there.
        So I'm not sure what's wrong here, it seems to me that the specific config for firebase shouldn't be an issue.
        I've seen they mentionned this css file in another issue where icons were too big in prod.
        So I tried adding this in css: ["@fortawesome/fontawesome-svg-core/styles.css"] in nuxt.config.js but no luck either.

        I don't understand why this is not working the nuxtjs doc clearly says you can include global css this way and the css file has the classes that I'm missing.

  • Taufik Nurhidayat
    Taufik NurhidayatOct 24, 2020
    ⚠  Error: Cannot find module 'nuxt-start'
    Require stack:
    - /home/taufik/project/ssr-novelindo/functions/index.js
    - /home/taufik/.nvm/versions/node/v12.18.3/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js
        at Function.Module._resolveFilename (internal/modules/cjs/loader.js:965:15)
        at Function.Module._load (internal/modules/cjs/loader.js:841:27)
        at Module.require (internal/modules/cjs/loader.js:1025:19)
        at require (internal/modules/cjs/helpers.js:72:18)
        at Object. (/home/taufik/project/ssr-novelindo/functions/index.js:2:18)
        at Module._compile (internal/modules/cjs/loader.js:1137:30)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
        at Module.load (internal/modules/cjs/loader.js:985:32)
        at Function.Module._load (internal/modules/cjs/loader.js:878:14)
        at Module.require (internal/modules/cjs/loader.js:1025:19)
    ⚠  We were unable to load your functions code. (see above)
    [hosting] Rewriting / to http://localhost:5001/novelindo/us-central1/ssrapp for l"

    module nuxt-start is nothing?

  • SeriousLee13
    SeriousLee13Feb 6, 2021

    Those predeploy scripts won't work on windows (I just tried implementing another nuxt/firebase tutorial article that used the same commands). Can you please add windows equivalents of the scripts?

Add comment