Skip to content

FirebaseExtended/firebase-framework-tools

main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
May 11, 2022 05:16
September 21, 2022 01:17
April 23, 2022 15:23
March 14, 2022 13:50
March 14, 2022 13:50
September 21, 2022 01:17

Firebase CLI & Web Frameworks

Frameworks

Built-in frameworks
Next.js Angular Nuxt Custom
SSR🔜👍
SPA🔜👍
SSG🔜👍
SWR/E🔜
Auth+SSR🔜👍
Status🔬🔬🔬🔬

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

Status: Experimental

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:

  1. Run firebase serve from the terminal. This should build your app and serve it using the Firebase CLI.
  2. 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:

  1. Run firebase deploy from the terminal.
  2. Check your website on: SITE_ID.web.app or PROJECT_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

  1. Run the initialization command from the CLI:
firebase init hosting
  1. Choose your hosting source directory; this could be an existing Angular app.
  2. Choose "Dynamic web hosting with web framework."
  3. 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.

  1. Run the initialization command from the CLI and then follow the prompts:
firebase init hosting
  1. Choose your hosting source directory; this could be an existing next.js app.
  2. Choose "Dynamic web hosting with web framework"
  3. 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 in getServerSideProps.
  • 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

  1. Run the initialization command from the CLI:
firebase init hosting
  1. Choose your hosting source directory; this could be an existing web app
  2. Choose "Dynamic web hosting with web framework"
  3. 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