Example and step by step guide: nestfire-example
When working with Firebase Functions, Firebase only gives us a folder to work in. There is no clear structure, no dependency injection, and no separate layers. This puts us at high risk of ending up with code that is hard to maintain and full of errors.
The solution is NestJS. With this framework we get a clear structure and all these problems are solved. It is used in large projects and has a strong community.
But how do we combine NestJS with Firebase Functions?
When we start a project with the command nest new projectName
, NestJS creates the initial structure and a src folder where we can add our modules.
A module has a .module.ts
file. One of the roles of this file is to define everything the module needs to run.
So, if a module includes all its dependencies, can we build and deploy it on its own to Google Cloud (Firebase Functions) or AWS Lambda? The answer is yes, but there are a few things to keep in mind.
- A module by itself is just code. If you drop it into Firebase Functions without the Nest server bootstrap, it won’t run because there’s no HTTP server process listening.
- You need a “main” entry file to start Nest, load the module, and expose its routes.
- Controllers inside the module only work if that entry file wires them up to an HTTP handler.
- Global providers (like APP_FILTER or APP_INTERCEPTOR) you’ve defined in your AppModule won’t automatically be included when you compile and deploy a single module — you have to re-apply them or import the same provider configuration in each module’s bootstrap.
The solution to all of this is NestFire.
NestFire
NPM: https://www.npmjs.com/package/nestfire
This npm package automatically solves all those problems.
All you have to do is:
- Install it in your project
- Configure it by adding an environment variable and updating your
firebase.json
- Add the
@FirebaseHttps()
decorator to each module you want to deploy - Run
firebase deploy --only functions
Module example:
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { EnumFirebaseFunctionVersion, FirebaseHttps } from 'nestfire';
@FirebaseHttps(EnumFirebaseFunctionVersion.V2, { memory: '256MiB' })
@Module({
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
This module will create a version 2 function (using Google Cloud Run) with 256 MiB of memory.
FirebaseHttps Decorator
This decorator adds the info passed as a parameter to the UserModule class. NestFire will use that info to know which Firebase Functions version to create and how to configure the function.
The decorator takes two parameters:
- The Firebase Functions version, using the
EnumFirebaseFunctionVersion
enum - The function configuration: use RuntimeOptions for version 1 and HttpsOptions for version 2
Index.ts File
When NestFire is installed, it automatically creates an index.ts file in the project root.
index.ts:
import { AppModule } from 'src/app.module';
import { firebaseFunctionsHttpsDeployment } from 'nestfire';
export = firebaseFunctionsHttpsDeployment(AppModule);
The function firebaseFunctionsHttpsDeployment(AppModule) takes the AppModule as a parameter.
When you run firebase deploy --only functions
, Firebase uses the settings in your firebase.json. That setup needs to point at the index.ts file created by NestFire, so you must change the source to "source": "."
{
"functions": [
{
"source": ".",
"runtime": "nodejs22",
}
]
}
When we run firebase deploy --only functions
, the firebaseFunctionsHttpsDeployment(AppModule)
function in index.ts
will execute. It goes through every module imported in AppModule
and looks for the information added by the @FirebaseHttps
decorator. When it finds a configured module, it adds the providers from AppModule, creates an Express server, and uses NestFactory.create
to make a Nest application instance. It also saves that instance so it does not have to recreate it from scratch on cold start.
This way, all modules with the @FirebaseHttps()
decorator will be deployed when you run firebase deploy --only functions
. You can easily change their configuration and avoid a lot of problems.
The result is a regular NestJS backend, but we can deploy it separately on smaller, faster, and cheaper instances.
Example
Example and step by step guide: nestfire-example
NPM: https://www.npmjs.com/package/nestfire
Top comments (0)