3 Ways To Integrate a Node.JS App With Firebase
Deliver a Node.JS App With Firebase
Since 2017 is possible to deliver a Node.JS app using Firebase.1 Google team released a demonstration of two Node.JS endpoints running on the platform. Also, there’s a tutorial building an API from scratch. Now, what happens when an already developed Node.JS app needs to be integrated with Firebase? There’ll be an issue.
Getting a Node.JS app working on the platform requires a few hours of understanding, debugging and more troubleshooting of the issue. Hopefully, this article will save you time on that process finding the cause of the main issue, the analysis and the development of a Node.JS app with Firebase on three different ways for a successful deployment.
Things to Consider
Before talking about the main issue let’s define two things:
- Node.JS app structure
- Cloud Functions integration
First, the Node.JS app structure.
Node.JS App Structure
The structure of a regular Node.JS app looks something like this:
> bin/
> www.js
> src/
> controllers
> routes
> more modules
> test/
> src
> app.js
> package.json
The script bin/www.js
will serve the application configuring the HTTP server.
The application main entry is app.js
which configures the app
(eg. routes, middlewares, etc.) and requires the app’s source from the src/
directory.
The test/
directory contains *.spec.js
files testing each script at the src/
directory.
Now it’s time to talk about the Cloud Functions integration.
Cloud Functions Integration
The installation of Cloud Functions via the Firebase CLI
creates a functions/
directory by default with functions/index.js
as the main entry.
The most natural connection will be to require the app in the main entry of the functions
module.
// functions/index.js
const functions = require('firebase-functions');
const app = require('../app');
exports.app = functions.https.onRequest(app);
The smoke testing comes at deployment time by executing the firebase deploy
command.
If that’d work then this post won’t exist and so now is time to talk about the issue.
Issue
The Cloud Functions deployment fails with the following message:
Cannot find module '../app'
Cloud Functions uploads the content of the functions/
directory on deployment and so there was no Node.JS app inside it.
That’s where our journey begins since there are three ways to solve it.
Solutions
There are three ways to solve it. Each of them is defined with its “pros-and-cons” making the election easier for different scenarios.
NOTE: all solutions has a common requirement and is that the Firebase project must be configured with Pay as you go. It does not mean that there’s payment requirements since the free quota is large enough for testing. However, it requires a billing account to be in place. Read more at the Quotas and limits page.
Solution A: App Inside Functions
With this solution the project’s structure will change to the next shape:
> bin/
> www.js
> functions/
> src/
> test/
> app.js
> index.js
> package.json
> package.json
Steps
- Move
app.js
,src/
andtest/
intofunctions/
-
Update the app’s path in
functions/index.js
-- const app = require('../app'); ++ const app = require('./app');
-
Update the app’s path in
bin/www.js
-- var app = require('../app'); ++ var app = require('../functions/app');
-
Tests’ path must be updated in
package.json
"test": "nyc --reporter=html mocha --recursive 'functions/test/**/*.js'"
-
All
dependencies
(do not confuse withdevDependencies
) frompackage.json
must be installed atfunctions/package.json
. For example: if@google-cloud/firestore
is declared as an app’s dependency then it must be installed as follows.cd functions npm i @google-cloud/firestore
Pros
- It works!
Cons
- Code coupled with hosting solution. In case we want to switch from Firebase into another solution will be a nightmare.
- Loss of classic Node.JS app structure. Looking at the project’s root level there’ll be no indicator of a Node.JS app. Instead, an app that only supports Cloud Functions will be highlighted.
- Double installation of dependencies.
In order to make app work locally they must be installed at
package.json
. To make it also work for Cloud Functions they must be installed atfunctions/package.json
.
Solution B: Functions at Root
With this solution the project’s structure will change to the next shape:
> bin/
> www.js
> src/
> test/
> app.js
> package.json
Steps
- Move
functions/index.js
to the root level -
Update the app’s path in
index.js
-- const app = require('../app'); ++ const app = require('./app');
- Carefully integrate
functions/package.json
withpackage.json
It consists of, mainly, the next sub-steps:- Merging
scripts
- Merging
engines
- Merging
dependencies
- Merging
devDependencies
Real example:
- Merging
- Remove
functions/
-
Update Cloud Functions path’s configuration from the
firebase.json
file."functions": { "source": "." }
Pros
- It also works!
- No duplication of NPM packages.
Cons
- Is tedious as heck.
- Ends up with two entry points at the root level (
app.js
andindex.js
). - A single node version for both, local and Cloud Functions (
package.json@engines
).
Solution B: Mirror App Inside Functions
With this solution the project’s structure will change to the next shape:
> bin/
> www.js
> functions
> index.js
> package.json
> src/
> test/
> app.js
> package.json
Steps
-
Update the app’s path in
functions/index.js
-- const app = require('../app'); ++ const app = require('./app');
-
All
dependencies
(do not confuse withdevDependencies
) listed atpackage.json
must be installed atfunctions/
. For example: if@google-cloud/firestore
is declared as a dependency at the root app then it must be installed as follows.cd functions npm i @google-cloud/firestore
-
Copy the app before deployment starts into the Functions module. This can be done via the
firebase.json
file by updating it with the following block."functions": { "predeploy": "mkdir functions/app && cp -r {app.js,src} functions/app", "postdeploy": "rm -r functions/app" }
Pros
- It works too!
- Original app structure is almost untouched. The Node.JS app continue to look exactly as expected.
- Same code tested locally will be deployed automatically on the Cloud Functions.
- Migrating from Firebase into another solution will be as simply as removing Cloud Functions related files and enable the new solution
Cons
- Needs to keep track of dependencies and make sure to install them twice.
These were a description of the three ways that I’ve found to integrate a Node.JS app into Firebase. Which one is the right one depends on the project and its requirements. In my experience, solution C has been the best option. Anyways, it might be that any of the other solutions could fit better for a different project. The choice is up to you.
Conclusion
Is worth to give it a shot and deploy a Node.JS app via Firebase. The platform counts with a list of exciting solutions to develop mobile and web apps. It includes extensions that accelerate the development of common solutions and integrations to quickly connect with existing platforms. Integrating your application into this platform can be very handy for professional as well personal projects.
Feedback
Let me know your thoughts through my Twitter account. I’m looking forward to hearing from you!