Serve dynamic content and host microservices with Cloud Functions

Pair Cloud Functions with Firebase Hosting to generate and serve your dynamic content or build REST APIs as microservices.

Cloud Functions for Firebase lets you automatically run backend code in response to HTTPS requests. Your code is stored in Google's cloud and runs in a managed environment. There's no need to manage and scale your own servers.

For example use cases and samples for Cloud Functions integrated with Firebase Hosting, visit our serverless overview.

Connect Cloud Functions to Firebase Hosting

This section provides a walk-through example for connecting a function to Firebase Hosting.

Note that to improve the performance of serving dynamic content, you can optionally tune your cache settings.

Step 1: Set up Cloud Functions

  1. Make sure that you have the latest version of the Firebase CLI and that you've initialized Firebase Hosting.

    For detailed instructions about installing the CLI and initializing Hosting, see the Get Started guide for Hosting.

  2. Make sure that you've set up Cloud Functions:

    • If you've already set up Cloud Functions, you can proceed to Step 2: Create and test an HTTPS function.

    • If you've not set up Cloud Functions:

      1. Initialize Cloud Functions by running the following command from the root of your project directory:

        firebase init functions
      2. When prompted, select JavaScript (this walk-through example uses JS).

      3. Check that you have a functions directory in your local project directory (created by the Firebase command you just ran). This functions directory is where the code for Cloud Functions lives.

Step 2: Create and test an HTTPS function for your Hosting site

  1. Open /functions/index.js in your favorite editor.

  2. Replace the file's contents with the following code.

    This code creates an HTTPS function (named bigben) that replies to HTTPS requests with a BONG for each hour of the day, just like a clock.

    const functions = require('firebase-functions/v1');
    
    exports.bigben = functions.https.onRequest((req, res) => {
      const hours = (new Date().getHours() % 12) + 1  // London is UTC + 1hr;
      res.status(200).send(`<!doctype html>
        <head>
          <title>Time</title>
        </head>
        <body>
          ${'BONG '.repeat(hours)}
        </body>
      </html>`);
    });
    
  3. Test your functions locally using the Firebase Local Emulator Suite.

    1. From the root of your local project directory, run the following command:

      firebase emulators:start
    2. Access the function via the local URL returned by the CLI, for example: http://localhost:5001/PROJECT_ID/us-central1/bigben.

Visit the Cloud Functions documentation to learn more about HTTPS requests.

The next step walks you through how to access this HTTPS function from a Firebase Hosting URL so that it can generate dynamic content for your Firebase-hosted site.

Step 3: Direct HTTPS requests to your function

With rewrite rules, you can direct requests that match specific patterns to a single destination. The following steps show you how to direct all requests from the path ../bigben on your Hosting site to execute the bigben function.

  1. Open your firebase.json file.

  2. Add the following rewrite configuration under the hosting section:

    "hosting": {
      // ...
    
      // Add the "rewrites" attribute within "hosting"
      "rewrites": [ {
        "source": "/bigben",
        "function": {
          "functionId": "bigben",
          "region": "us-central1"  // optional (see note below)
          "pinTag": true           // optional (see note below)
        }
      } ]
    }
    
  3. Confirm that your redirect works as expected by testing again with the Firebase emulators.

    1. From the root of your local project directory, run the following command:

      firebase emulators:start
    2. Visit the locally hosted URL for your site as returned by the CLI (usually localhost:5000), but append the URL with bigben, like so: http://localhost:5000/bigben

  4. Iterate on your function and its functionality for your site. Use the Firebase emulators to test these iterations.

For the best performance, colocate your functions with Hosting by choosing one of the following regions:

  • us-west1
  • us-central1
  • us-east1
  • europe-west1
  • asia-east1

Visit the Hosting configuration page for more details about rewrite rules. You can also learn about the priority order of responses for various Hosting configurations.

Note that to improve the performance of serving dynamic content, you can optionally tune your cache settings.

Step 4: Deploy your function

Once your function is working as desired in the emulator, you can proceed to deploying, testing, and running it with real project resources. This is a good time to consider setting runtime options to control scaling behavior for functions running in production.

  1. Deploy your function as well as your Hosting content and config to your site by running the following command from the root of your local project directory:

    firebase deploy --only functions,hosting
  2. Access your live site and your function at the following URLs:

    • Your Firebase subdomains:
      PROJECT_ID.web.app/bigben and PROJECT_ID.firebaseapp.com/bigben

    • Any connected custom domains:
      CUSTOM_DOMAIN/bigben

Use a web framework

You can use web frameworks, like Express.js, in Cloud Functions to serve your app's dynamic content and write complex web apps more easily.

The following section provides a walk-through example for using Express.js with Firebase Hosting and Cloud Functions.

  1. Install Express.js in your local project by running the following command from your functions directory:

    npm install express --save
  2. Open your /functions/index.js file, then import and initialize Express.js:

    const functions = require('firebase-functions/v1');
    const express = require('express');
    const app = express();
  3. Add the following two endpoints:

    1. Add the first endpoint to serve the index of our website at /.

      app.get('/', (req, res) => {
        const date = new Date();
        const hours = (date.getHours() % 12) + 1;  // London is UTC + 1hr;
        res.send(`
          <!doctype html>
          <head>
            <title>Time</title>
            <link rel="stylesheet" href="/style.css">
            <script src="/script.js"></script>
          </head>
          <body>
            <p>In London, the clock strikes:
              <span id="bongs">${'BONG '.repeat(hours)}</span></p>
            <button onClick="refresh(this)">Refresh</button>
          </body>
        </html>`);
      });
      
    2. And another endpoint to return the BONG count as an API, in JSON format, under /api:

      app.get('/api', (req, res) => {
        const date = new Date();
        const hours = (date.getHours() % 12) + 1;  // London is UTC + 1hr;
        res.json({bongs: 'BONG '.repeat(hours)});
      });
      
  4. Export the Express.js app as an HTTPS function:

    exports.app = functions.https.onRequest(app);
  5. In your firebase.json file, direct all requests to the app function. This rewrite allows Express.js to serve the different subpath that we configured (in this example, / and /api).

    {
     "hosting": {
       // ...
    
       // Add the "rewrites" attribute within "hosting"
       "rewrites": [ {
         "source": "**",
         "function": "app"
       } ]
     }
    }

Add middleware

Continuing our example, now that you're using Express.js, you can add Express.js middleware in the typical way. For example, you can enable CORS requests on our endpoints.

  1. Install the cors middleware by running the following command:

    npm install --save cors
  2. Open your /functions/index.js file, then add cors to your Express.js app, like so:

    const cors = require('cors')({origin: true});
    app.use(cors);

Visit the Cloud Functions documentation to learn more about using Firebase with Express apps and middleware modules.

Next steps