@nullsafe/firebase-frameworks
v0.10.0
Published
Experimental addon to the Firebase CLI to add web framework support
Downloads
1
Maintainers
Readme
Firebase CLI & Web Frameworks
Frameworks
Overview
Firebase Hosting integrates with popular modern web frameworks including Angular and Next.js. Using Firebase Hosting and Cloud Functions for Firebase with these frameworks, you can develop apps and microservices in your preferred framework environment, and then deploy them in a managed, secure server environment. Support during this early preview includes the following functionality:
- Deploy Web apps comprised of static web content
- Deploy Web apps that use pre-rendering / Static Site Generation (SSG)
- Deploy Web apps that use server-side Rendering (SSR)—full server rendering on demand
Firebase provides this functionality through the Firebase CLI. When initializing Hosting on the command line, you provide information about your new or existing Web project, and the CLI sets up the right resources for your chosen Web framework.
Status
This repository is maintained by Google but is not a supported Firebase product. Issues here are answered by maintainers and other community members on GitHub on a best-effort basis.
Enable framework-awareness
An experimental add-on to the Firebase CLI provides web framework support. To enable it, call the following:
firebase experiments:enable webframeworks
Prerequisites
- Firebase CLI version 10.9.1 or later (see installation instructions here)
Serve locally
You can test your integration locally by following these steps:
- Run
firebase serve
from the terminal. This should build your app and serve it using the Firebase CLI. - Open your web app at the local URL returned by the CLI (usually http://localhost:5000).
Deploy your app to Firebase Hosting
When you're ready to share your changes with the world, deploy your app to your live site:
- Run
firebase deploy
from the terminal. - Check your website on:
SITE_ID.web.app
orPROJECT_ID.web.app
(or your custom domain, if you set one up)
Integrate Angular
Easily deploy your Angular application to Firebase and serve dynamic content to your users.
Prerequisites
- Firebase CLI version 10.9.1 or later (see installation instructions here)
- (optional) Billing enabled on your Firebase Project (if you plan to use SSR)
- Optional: AngularFire
Initialize Firebase
To get started, you'll need to initialize Firebase for your framework project. Use the Firebase CLI for a new project,
or modify firebase.json
for an existing project.
Initialize a new project
- Run the initialization command from the CLI:
firebase init hosting
- Choose your hosting source directory; this could be an existing Angular app.
- Choose "Dynamic web hosting with web framework."
- Choose Angular.
Initialize an existing project
Change your hosting config in firebase.json
to have a source
option, rather than a public
option. For example:
{
"hosting": {
"source": "./path-to-your-angular-workspace"
}
}
Serve static content
After initializing Firebase, you can serve static content with the standard deployment command:
firebase deploy
Pre-render dynamic content
To prerender dynamic content in Angular, you need to set up Angular Universal. The Firebase CLI expects Express Engine:
ng add @nguniversal/express-engine
See the Angular Universal guide for more information.
Add prerender URLs
By default, only the root directory will be prerendered. You can add additional routes by locating the prerender step in
angular.json
and adding more routes:
{
"prerender": {
"builder": "@nguniversal/builders:prerender",
"options": {
"routes": [
"/",
"ANOTHER_ROUTE",
"AND_ANOTHER"
]
},
"configurations": {
/* ... */
},
"defaultConfiguration": "production"
}
}
Firebase also respects guessRoutes
or a routes.txt
file in the hosting root, if you need to customize further.
See Angular’s prerendering guide for more information on those options.
Optional: add a server module
Deploy
When you deploy with firebase deploy
, Firebase builds your browser bundle, your server bundle, and prerenders the
application. These elements are deployed to Hosting and Cloud Functions.
Custom deploy
The Firebase CLI assumes that you have server, build, and prerender steps in your schematics with a production configuration.
If you want to tailor the CLI's assumptions, configure ng deploy and alter the configuration in angular.json
. For
example, you could disable SSR and serve pre-rendered content exclusively by removing serverTarget
:
{
"deploy": {
"builder": "@angular/fire:deploy",
"options": {
"browserTarget": "app:build:production",
"serverTarget": "app:server:production",
"prerenderTarget": "app:prerender:production"
}
}
}
Optional: integrate with the Firebase JS SDK
When including Firebase JS SDK methods in both server and client bundles, guard against runtime errors by checking isSupported()
before using the product. Not all products are supported in all environments.
Hint: consider using AngularFire, which does this for you automatically.
Optional: integrate with the Admin SDK
Admin bundles will fail if included in your browser build, so consider providing them in your server module and injecting as an optional dependency:
// your-component.ts
import type { app } from 'firebase-admin';
import { FIREBASE_ADMIN } from '../app.module';
@Component({...})
export class YourComponent {
constructor(@Optional() @Inject(FIREBASE_ADMIN) admin: app.App) {
...
}
}
// app.server.module.ts
import * as admin from 'firebase-admin';
import { FIREBASE_ADMIN } from './app.module';
@NgModule({
…
providers: [
…
{ provide: FIREBASE_ADMIN, useFactory: () => admin.apps[0] || admin.initializeApp() }
],
})
export class AppServerModule {}
// app.module.ts
import type { app } from 'firebase-admin';
export const FIREBASE_ADMIN = new InjectionToken<app.App>('firebase-admin');
Serve fully dynamic content with SSR
Optional: integrate with Firebase Authentication
The web framework-aware Firebase deployment tooling automatically keeps client and server state in sync using cookies. The Express res.locals
object will optionally contain an authenticated Firebase App instance (firebaseApp
) and the currently signed in user (currentUser
). This can be injected into your module via the REQUEST token (exported from @nguniversal/express-engine/tokens).
Integrate Next.js
Using the Firebase CLI, you can deploy your Next.js Web apps to Firebase and serve them with Firebase Hosting. The CLI respects your Next.js settings and translates them to Firebase settings with zero or minimal extra configuration on your part. If your app includes dynamic server-side logic, the CLI deploys that logic to Cloud Functions for Firebase.
Note: Apps with dynamic server-side logic must provide a billing instrument during Cloud Functions setup. Also note that all frameworks-based functionality provided by the Firebase CLI is currently has experimental status, and may change in backward-incompatible ways.
Before you begin
Before you get started deploying your Next.js app to Firebase, first review the following requirements and options:
- All projects must use firebase-tools 10.8 or higher
- If your project requires SSR, you must provide a billing instrument
- Optional: use the experimental ReactFire library to benefit from its Firebase-friendly features
Initialize Firebase
To get started, you'll need to initialize Firebase for your framework project using the Firebase CLI.
- Run the initialization command from the CLI and then follow the prompts:
firebase init hosting
- Choose your hosting source directory; this could be an existing next.js app.
- Choose "Dynamic web hosting with web framework"
- Choose Next.js.
Serve static content
After initializing Firebase, you can serve static content with the standard deployment command:
firebase deploy
You can view your deployed app on its live site.
Pre-render dynamic content (SSG)
The Firebase CLI will detect usage of getStaticProps and getStaticPaths.
Optional: integrate with Firebase JS SDK
When including Firebase JS SDK methods in both server and client bundles, guard against runtime errors by checking isSupported()
before using the product. Not all products are supported in all environments.
Tip: consider using ReactFire, which does this for you automatically.
Optional: integrate with the Admin SDK
Admin SDK bundles will fail if included in your browser build; refer to them only inside getStaticProps and getStaticPaths.
Serve fully dynamic content (SSR)
The Firebase CLI will detect usage of getServerSideProps.
Configure Hosting behavior with next.config.js
Image Optimization
Using Next.js Image Optimization is supported, but it will trigger creation of a Cloud Function, even if you’re not using SSR.
Note: Because of this, Image Optimization and Hosting Preview Channels don’t interoperate well together.
Redirects, Rewrites, and Headers
Firebase CLI respects redirects, rewrites, and headers in next.config.js
, converting them to their respective equivalent Firebase Hosting configuration at deploy time.
If a Next.js redirect, rewrite, or header cannot be converted to an equivalent Firebase Hosting header, it falls back and builds a Cloud Function—even if you aren’t using Image Optimization or SSR.
Optional: integrate with Firebase Authentication
The web framework-aware Firebase deployment tooling will automatically keep client and server state in sync using cookies. There are some methods provided for accessing the authentication context in SSR:
- The Express
res.locals
object will optionally contain an authenticated Firebase App instance (firebaseApp
) and the currently signed in user (currentUser
). This can be accessed ingetServerSideProps
. - The authenticated Firebase App name is provided on the route query (
__firebaseAppName
). This allows for manual integration while in context:
// get the authenticated Firebase App
const firebaseApp = getApp(useRouter().query.__firebaseAppName);
Integrate other frameworks with Express.js
With some additional configuration, you can build on the basic CLI functionality to extend integration support to Frameworks other than Angular and Next.js.
What you’ll need before you begin
Prerequisites/what you need
- firebase-tools 10.8+
- If SSR, billing details
Initialize Firebase
To get started, you'll need to initialize Firebase for your framework project. Use the Firebase CLI for a new project,
or modify firebase.json
for an existing project.
Initialize a new project
- Run the initialization command from the CLI:
firebase init hosting
- Choose your hosting source directory; this could be an existing web app
- Choose "Dynamic web hosting with web framework"
- Choose Express.js / custom
Initialize an existing project
Change your hosting config in firebase.json to have a source
option, rather than a public
option. For example:
{
"hosting": {
"source": "."
}
}
Serve static content
Configure
In order to know how to deploy your application, the Firebase CLI needs to be able to both build your app and know where your tooling places the assets destined for Hosting. This is accomplished with the NPM build script and CJS directories directive in package.json
.
Given the following package.json:
{
"name": "express-app",
"version": "0.0.0",
"scripts": {
"build": "spack",
"static": "cp static/* dist",
"prerender": "ts-node prerender.ts"
},
…
}
The Firebase CLI only calls your build script, so you’ll need to ensure that your build script is exhaustive.
Hint: you can add additional steps using &&. If you have a lot of steps consider a shell script or tooling like npm-run-all or wireit.
{
"name": "express-app",
"version": "0.0.0",
"scripts": {
"build": "spack && npm run static && npm run prerender",
"static": "cp static/* dist",
"prerender": "ts-node prerender.ts"
},
…
}
If your framework doesn’t support pre-rendering out of the box, consider using a tool like Rendertron. Rendertron will allow you to make headless Chrome requests against a local instance of your app, so you can save the resulting HTML to be served on Hosting.
Finally, different frameworks and build tools store their artifacts in different places. Use directories.serve
to tell the CLI where your build script is outputting the resulting artifacts:
{
"name": "express-app",
"version": "0.0.0",
"scripts": {
"build": "spack && npm run static && npm run prerender",
"static": "cp static/* dist",
"prerender": "ts-node prerender.ts"
},
"directories": {
"serve": "dist"
},
…
}
Deploy
firebase deploy
Your application should now be configured as an SPA and deployed to Firebase Hosting.
Serve Dynamic Content
To serve up your Express app on Cloud Functions, ensure that your Express app (or express-style URL handler) is exported in such a way that Firebase can find it after your library has been NPM packed.
To accomplish this, ensure that your files directive includes everything needed for the server and your main entry point is set up correctly in package.json
:
{
"name": "express-app",
"version": "0.0.0",
"scripts": {
"build": "spack && npm run static && npm run prerender",
"static": "cp static/* dist",
"prerender": "ts-node tools/prerender.ts"
},
"directories": {
"serve": "dist"
},
"files": ["dist", "server.js"],
"main": "server.js",
...
}
Export your express app from a function named app
:
// server.js
export function app() {
const server = express();
…
return server;
}
Or if you’d rather export an express-style URL handler, name it handle
:
export function handle(req, res) {
res.send(‘hello world’);
}
Deploy
firebase deploy
Your application should now deploy your static content to Firebase Hosting and fall back to your Express app hosted on Cloud Functions.
Optional: integrate with Firebase Authentication
The web framework-aware Firebase deploy tooling will automatically keep client and server state in sync using cookies. To access the authentication context, the Express res.locals
object optionally contains an authenticated Firebase App instance (firebaseApp
) and the currently signed in User (currentUser
).
Common Configurations
Add cleanUrls
option
By default, a page created on /pages/foo/bar.jsx
is only accessible through the url /foo/bar.html
. To make the page
accessible on /foo/bar
instead, add cleanUrls
option to your hosting config in firebase.json.
{
"hosting": {
"source": ".",
"cleanUrls": true
}
}
Contributors
We'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to follow. See CONTRIBUTING.
Building
$ cd <YOUR-GIT-CHECKOUT>
$ npm i
$ npm run build