Introduction
I already have a working website using Nuxt and SSR so why would I move everything to Firebase?
SSR stands for server-side rendering, you can find more information here Understanding Server Side Rendering
There are so many reasons!
To list a few...
Price
Current solution: I have to pay every month for a private server
Firebase: Well, for my needs, it's free.
Configuration
Current solution: I have to configure everything myself. Docker containers, https, Nginx reverse proxy, ...
Firebase: Everything you need is already done. Logging, analytics, https, custom domain, ...
Update
Current solution: A change in my website? here are the steps
- Push changes to git
- Hook on docker hub get triggered and build the container (10-15 min)
- Connect on the server (1 min)
- Pull the latest container version (1 min)
- Find the right folder where the docker-compose.yaml is and update it (2 min)
I know I could've automated things a bit more but still...
Firebase: Steps
- type firebase deploy in terminal (1-2 min)
- done... changes are live
You're hooked? Obviously, you are. Let me help you get it running.
Setup the Firebase project
Create your Firebase account
You want to use Firebase, don't you? Well, you need to create your account first.
Done? We can now create a new project.
Create a Firebase project
Let's head over to Firebase console and click on Add project.
Set your project name.
Click on Continue.
Uncheck Google analytics for now and click on Add Firebase.
Wait for the project initialization and click on continue.
Install Firebase CLI
Now with the help of NPM, we will install the firebase tools on our computer.
Simply enter this command on your favorite terminal
npm i -g firebase-tools
Afterward, you should be able to login with this command
firebase login
A browser window will pop up and allow you to login with your Google account.
Alright, the initial Firebase setup is done...
Before adding firebase to our project, we need to update our application project structure...
Project Structure
I'm supposing you already have a nuxt project.
If not, head over to the Nuxt website to create a new app with express for the server side.
Our project will be decomposed into 3 directories
- src: This is where our development files sit
- functions: This is where our SSR function will be
- public: This directory will hold the files that will be served by Firebase hosting
We won't take care of the functions and public directories. It will be generated automatically.
So create the src directory and move all the nuxt directories into it.
Only the directories, leave the configuration files at the root
You should have something like the structure below
The app is broken now! Let's fix it by updating the nuxt config...
Update Nuxt config
In nuxt.config.js, add the following lines in module.exports
module.exports = {
[...]
srcDir: 'src',
buildDir: 'functions/.nuxt',
[...]
}
And in the build object, set extractCss to true
module.exports = {
[...]
build: {
extractCSS: true,
[...]
}
[...]
}
It is still broken because npm script cannot find our entry file server/index.js
Let's update our package.json
Replace dev and start scripts with these.
I just prefixed the path with "src"
"dev": "cross-env NODE_ENV=development nodemon src/server/index.js --watch server",
"start": "cross-env NODE_ENV=production node src/server/index.js",
You should now be able to start your application by typing yarn dev or npm run dev
Notice that the functions directory has been created with the nuxt files in it.
Add Firebase to the project
Like Git or NPM, Firebase CLI has its init command to get everything you need quickly.
Launch the command
firebase init
The CLI will ask you some questions and here are the answers:
? Are you ready to proceed?
> Yes
? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices.
> Functions: Configure and deploy Cloud Functions,
> Hosting: Configure and deploy Firebase Hosting sites
? Please select an option:
> Use an existing project
(Select the project we created earlier)
? What language would you like to use to write Cloud Functions? (Use arrow keys)
> JavaScript
? Do you want to use ESLint to catch probable bugs and enforce style? (y/N)
> y
? Do you want to install dependencies with npm now? (Y/n)
> Y
? What do you want to use as your public directory? (public)
> public
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N)
> N
A wild public directory appeared! Our project structure is now complete.
We can now edit our function...
Implement SSR function
Open the functions/index.js file, remove everything and paste the code below
const functions = require('firebase-functions')
const { Nuxt } = require('nuxt')
const express = require('express')
const app = express()
const config = {
dev: false
}
const nuxt = new Nuxt(config)
let isReady = false
const readyPromise = nuxt
.ready()
.then(() => {
isReady = true
})
.catch(() => {
process.exit(1)
})
async function handleRequest(req, res) {
if (!isReady) {
await readyPromise
}
res.set('Cache-Control', 'public, max-age=1, s-maxage=1')
await nuxt.render(req, res)
}
app.get('*', handleRequest)
app.use(handleRequest)
exports.nuxtssr = functions.https.onRequest(app)
To sum it up, on each reqest, the function will pass the response and request object to the nuxt.render(req, res) function which will handle the app rendering.
Updating the function package.json
The function will need the same libraries as your nuxt app. Copy the package.json dependencies to the functions/package.json dependencies
At the time of writing this article, firebase supports node version 10. In functions/package.json you can update the node engine version from 8 to 10.
Here's an example of the functions/package.json of a blank nuxt project
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"dependencies": {
"firebase-admin": "^8.0.0",
"firebase-functions": "^3.1.0",
"cross-env": "^5.2.0",
"nuxt": "^2.3.4",
"express": "^4.16.4",
"vuetify": "^1.3.14",
"vuetify-loader": "^1.0.8",
"@nuxtjs/pwa": "^2.6.0"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.1.6"
},
"private": true
}
Updating firebase.json
Replace the whole file with
{
"hosting": {
"public": "public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "**",
"function": "nuxtssr"
}
]
}
}
It will redirect all the requests to the function we've made
Using a node version above 10 can cause some issues...
You can use nvm or directly install NodeJs 10 on your computer.
Automate all the things
Static files
We learned earlier that static files will be held by the public directory. But what are the nuxt static files?
There will be the nuxt app itself, the result of the nuxt build command.
And the static files (.jpg, .ico, .png, ...) stored into the src/static directory
So we'll need to move them both in the public directory, let's see how...
Step by step
Here is what we're going to automate with the scripts
- Clean the directories in case there's already something in it
- Build the nuxt app
- The built app is now in the functions directory. Copy the content of the functions/.nuxt/dist/ directory to the public/_nuxt directory
- Copy the static files from the src/static/ directory to the root of the public directory
- Install the functions dependencies with yarn
The public folder should look something like this
These scripts will do all that for us. So kind of them.
Add these to the main package.json file.
Windows version
scripts: {
"build": "nuxt build",
"build:firebase": "yarn clean && yarn build && yarn copy && cd \"functions\" && yarn",
"clean": "yarn clean:public && yarn clean:functions && yarn clean:static",
"clean:functions": "rimraf \"functions/node_modules\" && rimraf \"functions/.nuxt\"",
"clean:public": "rimraf \"public/**/*.*!(md)\" && rimraf \"public/_nuxt\"",
"clean:static": "rimraf \"src/static/sw.js\"",
"copy": "yarn copy:nuxt && yarn copy:static",
"copy:nuxt": "xcopy \"functions\\.nuxt\\dist\\*\" \"public\\_nuxt\\\" /E /Y",
"copy:static": "xcopy \"src\\static\\*\" \"public\\\" /E /Y",
"start:firebase": "firebase serve --only functions,hosting",
"deploy": "firebase deploy --only functions,hosting"
}
MacOs version
Thanks to Michael Messerli for his MacOs scripts version
"scripts": {
// ...
"build:firebase": "yarn clean && yarn build && yarn copy && cd functions && yarn",
"clean": "yarn clean:public && yarn clean:functions && yarn clean:static",
"clean:functions": "rimraf \"functions/node_modules\" && rimraf \"functions/.nuxt\"",
"clean:public": "rimraf \"public/**/*.*!(md)\" && rimraf \"public/_nuxt\"",
"clean:static": "rimraf \"src/static/sw.js\"",
"copy": "yarn copy:nuxt && yarn copy:static",
"copy:nuxt": "mkdir public/_nuxt && cp -r functions/.nuxt/dist/* public/_nuxt",
"copy:static": "cp -r src/static/* public",
"start:firebase": "firebase serve --only functions,hosting",
"deploy": "firebase deploy --only functions,hosting",
// ...
}
Still having issues? James Block comment might help you https://dev.to/meanjames/comment/leln
Grand finale
You can now launch these commands to start your application:
yarn build:firebase
yarn start:firebase
And to deploy:
yarn build:firebase
yarn deploy
Tho, for development, you can still use
yarn dev
Conclusion
You now got a server-rendered nuxt application on firebase... Easy huh?
For this article, I did an example with a blank nuxt app. Here's the final project nuxt-on-firebase example repository.
Did you spot an error? Shame on me! You can correct it by doing a pull request right here nuxt-on-firebase repository


Oldest comments (54)
Thanks for the article; really helped me. I'm new to web development and evaluating several technologies. Right now nuxt + firebase is on top of my list.
Did you make any comparison to e.g. ssr with next.js on firebase?
Do you think nuxt.js + firebase is the way to go or is there anything you didn't like; testing, dev process, deploy process, ...?
Hey Rob,
I'm glad the post helped.
I didn't do any kind of comparison but I guess the firebase part would be pretty much the same.
If you try with nextJs, I'd like to know how it went.
is there any way to enable axios proxy in firebase deployment ?
Thank you so much for writing this!!
I've been pulling my hair out for ages trying to get a universal nuxt app deployed with firebase.
After following your article, I have it working running the start:firebase script, however when I deploy and follow the url I get a "500 Internal Server Error" :(
Would very much appreciate any help.
P.s. the firebase function logs just say "Function execution took 9 ms, finished with status code: 500"
Glad I could help!
That's odd. Do you have your code hosted somewhere? I could take a look
Really appreciate the response.
I started again with a blank nuxt project and built it up from there which is working so far :)
Thank you so much for this guide!
Here's what I changed in the package.json for anyone on macOs:
I'm glad you liked it.
Thanks for the macOs scripts, I'll update the article.
Thank you so much, this guide really helped me a lot to deploy my project. It's working on Firebase right now but i'm having a "Error: [vuex] must call Vue.use(Vuex) before creating a store instance." error on local environment.
I tried everything i know but could'nt find a way to make it working. Just to make sure, could it be that i changed the node version from 8 to 10? Or anything else?
Here is the folder structure:
thepracticaldev.s3.amazonaws.com/i...
I've had issues when trying to change node version so you could try that.
I didn't use VueX in my project. Is your code hosted somewhere so I can have a look ?
hello, it worked perfect, but it doesn't show me the home page,
I get this message
Welcome
Firebase Hosting Setup Complete
You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!
Hello Jesus,
Is your project hosted somewhere?
I'm also getting the same output, I did the exact same steps that the article provided.
How do I deploy a vuejs app with a nodejs backend to firebase? Are the steps the same?
Great article, it really helped out a lot! But, I still had some issues
The Story
The one issue I had was with writing the scripts. Im using a mac and didn't have access to the rimraf command. I was able to write scripts just using the the rm -rf command as a substitute. However I ran into an issue when trying to run the fallowing command...
Sidenote
The command should work fine if you are using git bash and run it in your terminal after enabeling extended globing and remove the escaped double quotations. The commands to do that are as fallows...
Enable
Disabled
This lead me on a journey to discover a little bit of information that to most is probably well known and obvious, and that is that the npm run scripts don't use the users shell. In other words if I wanted to use the extended globing feature in my scripts I would need to install additional node packages like the rimraf node package. Furthermore, using the rimraf package is apparently faster then rm -rf and is more cross platform compatible.
Take Away
I learned a few important things from trying to fallow this article. For clarity I think the article would benefit from having them included even if they seem obvious.
rm -rfand allows for a work around to therm -rfwith pattern matching in node scripts issue.Granted most of these issues are from the view point of someone using a macOS or git bash. However, I'm assuming writing scripts on a windows computer has similar issues if you try to avoid using the packages like rimraf. I just think it would be a good thing to mention what the package is and how to use them because chances are someone like myself wont know about the package.
Scripts if using npm on macOS.
This should be fairly obvious but all you need to do is replace yarn with npm run...
Hey James,
Thanks for the deep explanation!
I'll put a link to your comment in the article for every other macOs users out there.
Thanks again for them.
Glad I could help!
To make it more obvious: Replace yarn with npm run, but at the end of build:firebase change run to i (install)
First of all, thank you for this article, it's pretty awesome!
Although I am struggling with one issue for some time now and really can't figure it out.
In my nuxt app I have a server middleware with sendMessage function accessible under
/api/contactroutenuxt.config.js:I can't make it work with Firebase configuration. Should I move
~/api/contactto thefunctionsdirectory?Should I define it as a separate Firebase function or import somehow to the
nuxtssrfunction?I would appreciate any tips ;)
Hey Bartłomiej, thank you. I'm glad you liked it.
I had to do the exact same thing, you can check how I did it here
In short, I had to add a route to catch post method on 'api/contact' in here at the end of the file.
Tell me if you need any deeper explanations
That clarified a lot, thank you!
One more question: after following steps from the article I can't use
yarn devanymore. It looks like my plugins are nowundefinedon page render and Nuxt throwsCannot read property ... of undefinederror instead of rendering my page.yarn build:firebase && yarn start:firebaseworks fine.Do you have any idea what may be wrong? Do I need some additional configuration in
src/server/index.jsto make it work again?Weird, i get the same error...
I'll investigate on this when i get some free time (so rare these days :D)
Did you guys manage to solve this issue? I'm having the same error.
Found the solution in the comment below... just run yarn clean before running the yarn dev.
Sr ,I'm having the same error. And your link github is 404. How do you solve this issue? Tks.
Found the index.js he was talking about
github.com/KiritchoukC/kiritchoukc...
const functions = require('firebase-functions')
const { Nuxt } = require('nuxt')
const express = require('express')
const contact = require('./contact')
const app = express()
app.use(express.json())
const config = {
/**
const nuxt = new Nuxt(config)
let isReady = false
const readyPromise = nuxt
.ready()
.then(() => {
isReady = true
})
.catch(() => {
process.exit(1)
})
async function handleRequest(req, res) {
if (!isReady) {
await readyPromise
}
res.set('Cache-Control', 'public, max-age=1, s-maxage=1')
await nuxt.render(req, res)
}
app.post('/api/contact', contact)
app.get('*', handleRequest)
app.use(handleRequest)
exports.nuxtssr = functions.https.onRequest(app)
This guide probably saved me hours of configuration hell. Thank you! I had a relative path issue with the default setup:
WARN No pages directory found in [path to project]/functions. Using the default built-in page..Took me a while to figure out it was because I'd tweaked the render function to enable dev in the
configobject when it's set in the node ENV (config.dev = process.env.NODE_ENV !== 'production'). If you want to be able to run the code in dev mode for debugging purposes just addsrcDir: '../src'to the config object.