Firebase Hosting allows you to use Cloud Functions to perform server-side processing. This means that you can support dynamic generation of content for your Firebase Hosting site. Here are some examples of what this allows you to do:
- Serve dynamic content. Instead of only serving static content, you can perform
server-side logic through a function to return a dynamically generated
response. For example, you can have a URL like
/blog/<id-for-blog-post>. This URL pattern can be pointed to a function that dynamically uses the URL blog post ID parameter to retrieve content dynamically from your Firebase Realtime Database. - Prerendering for single page apps to improve SEO. This allows you to create
dynamic
metatags for sharing across various social networks. - Keep your web app lightweight. You can create an API through Cloud Functions for your Firebase Hosting site to asynchronously retrieve content. This allows you to reduce initial load times for your web app by keeping the client code lightweight and loading content asynchronously through a function.
Connecting Cloud Functions to Firebase Hosting
To connect a function to Firebase Hosting, you'll need to set up Cloud Functions, write your function, create rewrite rules, and deploy your changes. To improve the performance of your dynamic content, you can optionally tune your caching settings. Here's an example to demonstrate how to do this.
Setup Cloud Functions for Firebase Hosting
If you've already set up Cloud Functions for Firebase you can skip this step and proceed to Create an HTTPS function. This will set up Cloud Functions for your Firebase project.
First make sure you have the latest version of the Firebase CLI, which requires
Node.js version 6.3.1 or greater. You can install Node by following the
instructions on https://nodejs.org/. Installing Node.js will
also install npm.
To check what version of Node.js version you're running, run this command in your terminal:
node --version
You can install the latest version of the Firebase CLI by running the following command in your terminal:
npm install -g firebase-tools
After you've updated the Firebase CLI, you'll have to initialize functions. If you have not initialized your Hosting project, run the following command and choose to initialize Hosting and Cloud Functions within your project directory when prompted.
firebase init
If you have an existing project with Hosting, run the following command within your project directory to only initialize Cloud Functions.
firebase init functions
Create an HTTP function to your Hosting site
Open /functions/index.js in your favorite editor and replace its contents with
the following code. This will create a simple HTTPS function named
bigben.
const functions = require('firebase-functions');
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>`);
});
Directing Hosting requests to your function
With rewrite rules you can direct requests that match specific patterns to a
single destination. For example, to direct all requests from the page
/bigben on your Hosting site to execute the bigben function, you
would open firebase.json and add the following rewrite configuration under
the hosting section.
{
"hosting": {
"public": "public",
// Add the following rewrites section *within* "hosting"
"rewrites": [ {
"source": "/bigben", "function": "bigben"
} ]
}
}
You can learn more about rewrite rules.
Deploying
After creating a function and setting your rewrite rules, you'll need to deploy your Firebase project. Run the following command in the terminal.
firebase deploy
After deployment, you'll notice that your function is normally accessible through a URL like the following:
https://us-central1-<your-project-id>.cloudfunctions.net/bigben
All traffic on your Firebase Hosting site that matches the path specified in the rewrite rules will be proxied to the appropriate function.
Trying it out
Once everything is deployed you can go to /bigben on your
Firebase Hosting site to see it in action.
https://<your-project-id>.firebaseapp.com/bigben
Managing Cache Behavior
Firebase Hosting uses a powerful global content delivery network (CDN) to make your site as fast as possible. Static content on Firebase Hosting is cached until a new version is deployed. Because functions generate content dynamically, requests that are handled by a function do not cache in the CDN by default. You can configure caching behavior yourself to speed up your app and reduce function execution costs.
Setting Cache-Control
The main tool you'll use to manage cache is the Cache-Control header. By setting it, you can communicate both to the browser and the CDN how long your content should be cached. In your function, you set Cache-Control like so:
res.set('Cache-Control', 'public, max-age=300, s-maxage=600');
The above header does three things:
- Marks the cache as public. This means that this content is okay to be cached by intermediate servers (in our case, the CDN). By default Cache-Control is set to private which means that only the user's browser is allowed to cache it.
- Tells the browser for how many seconds it can cache the content with max-age. In the above example, we're telling the browser to cache for five minutes.
- Tells the CDN for how many seconds it can cache the content with s-maxage. In the above example, we're telling the CDN to cache for ten minutes.
When setting max age, you should set it to the largest amount of time with which you're comfortable having users receive stale content. If a page changes every few seconds, this will be a small number. Other content, however, can safely be cached for hours, days, or even months.
You can learn more about the Cache-Control header on the Mozilla Developer Network.
When is cached content served?
If you have set a public Cache-Control header, your content will be cached in the CDN based on:
- The hostname
- The path
- The query string
- The content of the headers specified in Vary
The Vary header is how you can signal to which parts of the request were
important in determining your response. Most of the time, you don't need to
worry about this. Firebase Hosting will automatically ensure that an
appropriate Vary header is set on your response for common situations. This
includes making sure that any session cookie or authorization header you're
using is made part of the cache key, preventing accidental leaks of
content.
In some advanced use cases, you may have other headers that you need to affect the cache. When that's the case, you can simply set the Vary header on your response:
res.set('Vary', 'Accept-Encoding, X-My-Custom-Header');
Now two otherwise identical requests with different X-My-Custom-Header headers would be cached separately.

