We’re excited to announce several new features that make developing with Firebase Hosting even better!
Our new integration with Cloud Logging gives you access to web request logs for your Hosting sites. Cloud Logging, previously known as Stackdriver Logging, makes it easy to view, search, and filter logs. You can learn from where and when you have visits to your site, your site's response statuses, the latency of end user requests, and more.
To get started, link your Firebase project to Cloud Logging in the Cloud Logging integration card in the Firebase console or visit the Hosting docs to learn more.
Hosting will now compress your assets with Brotli encoding. We’ll automatically serve the smallest, best-compressed version of your content, based on what your user's client is able to handle.
Brotli compression gives you a boost in performance because assets are smaller, use less bandwidth, and are delivered more quickly to your end users. This means you’ll have lower bandwidth costs, while your end users will enjoy faster sites.
The best part? You’ll get this automatically the next time you deploy.
We know it’s important to you to provide a great experience for your users everywhere. Firebase Hosting now supports serving country and language specific content, backed by the power of our global CDN. Previously, the best strategy was to use Cloud Functions to look at the country and/or language code and reply with a redirect as necessary.
Firebase Hosting’s i18n rewrites allow developers to serve different content, depending on a user's language preferences or country location. In your public directory, create an i18n directory containing separate folders for each language/country combination, then add the i18n field to your project's firebase.json config. I18n rewrites also work for localized 404 pages. Learn more about using i18n rewrites in our documentation.
i18n
firebase.json
We hope you all are excited for these new features, but stay put because we have even more coming in the future!
Today we're excited to announce Firebase Hosting integration for Google Cloud’s new Cloud Run service. Cloud Run is a fully managed compute platform that enables developers to run stateless containers that are invocable via HTTP requests in a language and framework of their choosing. Firebase Hosting integration lets you use this architecture as a backend for a web app or microservice in your Firebase project.
Firebase Hosting is already a convenient and secure way to host sites and microservices. It can serve static pages you upload directly and, with the proper configuration in the firebase.json file, direct incoming requests to Cloud Functions for Firebase to serve dynamic content. This workflow is a one stop shop if you don’t mind working in the NodeJS environment. You can already build a fast site with dynamic content that automatically scales horizontally to meet user demand.
Not every developer wants to work with NodeJS though. Many already have large teams with existing knowledge in other languages and frameworks. Languages such as Go, Ruby, and Java have a huge presence in the server market but are currently absent in Firebase’s existing cloud backend solutions.
Leveraging the power of Google’s own experience building infrastructure for Kubernetes and the efforts of the Knative open source project, Google Cloud Platform now lets you deploy stateless servers. The only requirements are that you can generate a docker image able to interact to HTTP requests on the port specified in the $PORT environment variable for Kubernetes and that you respond within 60 seconds for Firebase Hosting. How does this tie into Firebase Hosting though?
If you’re new to Hosting, you may only be aware of static hosting or the free SSL certificates. To facilitate serving dynamic content, rewrites allow you to hit your cloud functions, which we’ve extended to support Cloud Run as well. With a few minor changes to your firebase.json file, you can now point a specific path to your container:
{ "hosting": { "public": "public", "rewrites": [ { "source": "/cloudrun", "run": { "serviceId": "my-awesome-api", // Optional (default is us-central1) "region": "us-central1", } } ] } }
or use wildcards to expose an entire API
{ "hosting": { "public": "public", "rewrites": [ { "source": "/api/**", "run": { "serviceId": "my-awesome-api", // Optional (default is us-central1) "region": "us-central1", } } ] } }
If you have a dynamic site that doesn’t update very frequently, take advantage of Firebase Hosting’s global CDN (content delivery network) to improve your site’s response time. For example, if you’re using ExpressJS and NodeJS, configure the caching behavior using the Cache-Control header like so:
Cache-Control
res.set('Cache-Control', 'public, max-age=300, s-maxage=600');
which caches the results of a request in the browser (max-age) for 5 minutes and in the CDN (s-maxage) for 10 minutes. With properly tuned cache settings, you can have a fast, flexible, dynamically rendered site that doesn’t need to run your server logic every time the user opens the page.
max-age
s-maxage
Unlike Cloud Functions for Firebase, when you use Cloud Run, you can build an image with any combination of languages and frameworks to handle these requests. Ruby developers can easily pull in Sinatra, you can fire up the Spring framework for Java teams, or check out server side Dart using Shelf to serve content. You don’t have to wait for any official language support -- if you can create a docker container, you can make and deploy backend code. Even if you’re working in high performance computing and your engineering team is trained up in Fortran, you can just leverage that existing knowledge to create a web dashboard with Fortran.io without having to wait for any official support from Google or Firebase.
Similar to Cloud Functions, Cloud Run automatically scales your containers horizontally to meet the demands of your users. There’s no need to manage clusters or node pools; you simply use the resources needed at the time to accomplish the task at hand. One tradeoff is that, also like Cloud Functions, Cloud Run images are stateless. However, unlike Cloud Functions, each container can handle up to 80 concurrent users, which can help reduce the frequency of cold starts.
Using Firebase Hosting with Cloud Run, we hope to empower you to build better web apps faster than ever before. Now your frontend and backend developers can truly use a single language, even share a code base. To get started right away, follow our step-by-step guide. Note that Cloud Run exists in the Google Cloud console rather than the Firebase console, but if you have a Firebase project then you already have a Google Cloud Platform project as well.
Do you manage multiple Firebase Hosting sites? Do these sites share a single resource like a Firestore or Realtime database? Do you wish you could manage these sites from one place instead of having to create multiple projects? Do you wish that Firebase Hosting could deploy only the new or modified files? Wish no more! Because it's all here!
Firebase Hosting now allows you to create multiple sites inside of one Firebase project. If your admin site and blog site consume data from a shared Firebase resource, they can now both live in a single project - saving you time and developer resources. You can manage these sites directly in the Firebase Console and deploy via the command line.
Firebase automatically provisions a firebaseapp domain for you, which is the same as your Firebase project name. We currently do not support subdomains on the firebaseapp.com domain, but you can still provision subdomains on your own by connecting a custom domain for your sites. To get started with multiple sites, you'll need to be on the Blaze plan. Once you're on the Blaze plan you'll be able to add multiple sites inside of the Firebase Console.
To help switch between different sites in a single project we introduced a new configuration setup in firebase.json. Make sure you update to the latest version of the Firebase CLI!
{ "hosting": [ { "target": "blog", "public": "blog/dist" }, { "target": "app", "public": "app/dist" } ] }
The "hosting" config can now take in an array of site configurations. A single object still works if you still have just one site. Each configuration has a "target". The CLI uses this target to know what "public" folder to use for deploying assets. Speaking of the CLI! We have a new command for you.
"hosting"
"target"
"public"
To manage switching between multiple sites in one project, we're going to use the target:apply command. This command is a bit like the firebase use --add command except instead of linking the project to the alias, it establishes a link between the site and the target. The applied target can then be used with the firebase deploy and firebase serve commands.
target:apply
firebase use --add
firebase deploy
firebase serve
The firebase use command is helpful for deploying to multiple projects. This is common for those who have a "staging" project versus a "production" project. For managing one site across different environments, we still recommend multiple projects for promoting best practices of each environment having its own set of Firebase resources.
firebase use
However, managing multiple sites is a different problem. The CLI now has to know about multiple sites instead of just one. The CLI must know:
This why we introduced target:apply for Hosting.
firebase target:apply hosting target-name site-name
Let's break down this command.
firebase
hosting
target-name
"blog"
"app"
site-name
Let's say you wanted to deploy your blog using the example firebase.json above:
firebase target:apply hosting blog my-cool-blog firebase deploy --only hosting:blog
In this command, we first identified the target-name of "blog", then associated it with the targeted site "my-cool-blog", and finally deployed to that target. If you don't specify a target in your firebase deploy or firebase serve commands, then all your targets will be deployed, or served locally on different ports, respectively. Note that you only have to define your targets once per project.
If you updated the Firebase CLI recently, you might have noticed that your uploads got a bit faster. You may have also noticed a new .firebase folder in your project. That's because we rolled up a new deployment system that we call Delta Uploads.
.firebase
This new system only processes new, modified, or deleted files. You know, the delta. This means any files that are unchanged aren't uploaded when you run firebase deploy. You may not notice a big improvement in performance if your site is only a few files. However, it will make a huge difference for sites with a large amount of existing unmodified assets.
Check out the official documentation and make sure to update your CLI! Both multi-site and delta uploads features require the latest version of the Firebase CLI. Make sure you're either above or at version 4.2.0 to use these features. Happy deploying!
4.2.0
firebase.initializeApp()
// DON'T DO THIS ANYMORE! switch (location.hostname) { case 'myapp.com': firebase.initializeApp(prodConfig); break; case 'myapp-staging.com': firebase.initializeApp(stagingConfig); break; default: firebase.initializeApp(devConfig); break; }
script
<!doctype html> <html> <body> ... <!-- Import and initialize the Firebase SDK --> <script src="/__/firebase/3.7.4/firebase-app.js"></script> <script src="/__/firebase/3.7.4/firebase-auth.js"></script> <script src="/__/firebase/init.js"></script> <script> // The Firebase SDK is ready to rock! firebase.auth().onAuthStateChange(function(user) { /* … */ }); </script> </body> </html>
/__/firebase/{VERSION}/firebase-{app,auth,database,messaging,storage}.js
/__/firebase/{VERSION}/firebase.js
/__/firebase/init.js
/__/firebase/init.json
init.js
3.6.0
firebase login --reauth
firebase setup:web
firebase-tools
$ npm install --save firebase-tools@^3.6
const fbcli = require('firebase-tools'); const fs = require('fs'); // by default, uses the current project and logged in user fbcli.setup.web().then(config => { fs.writeFileSync( 'build/initFirebase.js', `firebase.initializeApp(${JSON.stringify(config)});` ); }); // alternatively, you can pass project or token information fbcli.setup.web({ project: 'my-custom-project', token: process.env.FIREBASE_TOKEN });