
Cloud
Learning Level
Advanced Firebase Hosting enables sophisticated deployment patterns, traffic management, performance optimization, and integration with backend services at scale.
By the end of this lesson, you'll understand:
# Deploy v2.0.0
firebase deploy --version v2.0.0
# Split traffic: 90% old, 10% new
firebase hosting:channels:deploy staging --expires=24h
# Gradually increase traffic to v2
firebase hosting:versions:list
# Promote v2 after testing
firebase hosting:versions:promote NEW_VERSION_ID#!/bin/bash
# Deploy to preview channel
firebase hosting:channel:deploy canary
# Get preview URL
PREVIEW_URL=$(firebase hosting:channels:list | grep canary | awk '{print $2}')
# Run performance tests
npx lighthouse ${PREVIEW_URL} --output-path=lighthouse-report.html
# If tests pass, promote
if [ $? -eq 0 ]; then
firebase hosting:channel:promote canary
echo "Promoted to production"
else
echo "Tests failed, keeping preview"
firebase hosting:channels:delete canary
fi// Cloud Function for A/B routing
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.abtest = functions.https.onRequest(async (req, res) => {
const userId = req.query.userId || req.headers['x-user-id'];
const variants = ['control', 'variant-a', 'variant-b'];
// Consistent assignment per user
const hash = userId.split('').reduce((a, b) => {
a = ((a << 5) - a) + b.charCodeAt(0);
return a & a;
}, 0);
const variant = variants[Math.abs(hash) % variants.length];
// Log to BigQuery for analysis
await admin.firestore().collection('ab_tests').add({
userId,
variant,
timestamp: new Date(),
page: req.path
});
res.json({variant});
});firebase.json with multiple sites:
{
"hosting": [
{
"target": "prod",
"public": "dist/prod",
"rewrites": [{"source": "**", "destination": "/index.html"}]
},
{
"target": "blog",
"public": "dist/blog",
"rewrites": [{"source": "**", "destination": "/index.html"}]
},
{
"target": "docs",
"public": "dist/docs"
}
]
}# Deploy all sites
firebase deploy --only hosting
# Deploy specific site
firebase deploy --only hosting:prod
firebase deploy --only hosting:blog{
"hosting": {
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
{
"source": "/cdn/:file*",
"destination": "/static/:file"
},
{
"source": "/blog/:year/:month/:day/:post",
"destination": "/posts/:post.html"
},
{
"source": "**",
"destination": "/index.html"
}
],
"redirects": [
{
"source": "/old-url/**",
"destination": "/new-url/:path**",
"type": 301
}
]
}
}{
"hosting": {
"headers": [
{
"source": "/**",
"headers": [
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net; img-src 'self' data: https:"
},
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
}
]
}
]
}
}vercel.json (for comparison):
{
"public": "public",
"cleanUrls": true,
"trailingSlash": false,
"redirects": [],
"rewrites": [
{
"source": "/api/:match*",
"destination": "https://api.example.com/:match*"
}
]
}# Build for static export
npm run build
# Deploy to Firebase
firebase deploy --only hosting:prod// Cloud Function for on-the-fly image optimization
const functions = require('firebase-functions');
const sharp = require('sharp');
const {Storage} = require('@google-cloud/storage');
exports.optimizeImage = functions.https.onRequest(async (req, res) => {
const {file, width, format} = req.query;
const storage = new Storage();
const originalFile = storage.bucket('images-raw').file(file);
const buffer = await originalFile.download();
let image = sharp(buffer[0]);
if (width) image = image.resize(parseInt(width), null, {withoutEnlargement: true});
if (format) image = image.toFormat(format);
const optimized = await image.toBuffer();
res.set('Content-Type', `image/${format || 'webp'}`);
res.set('Cache-Control', 'public, max-age=31536000, immutable');
res.send(optimized);
});// Cloud Function serving as API gateway
const functions = require('firebase-functions');
const express = require('express');
const app = express();
app.get('/api/products', async (req, res) => {
// Backend logic
const products = await getProducts();
res.json(products);
});
exports.api = functions.https.onRequest(app);firebase.json:
{
"hosting": {
"rewrites": [
{"source": "/api/**", "function": "api"},
{"source": "**", "destination": "/index.html"}
]
}
}// Track Web Vitals
import {getCLS, getFID, getFCP, getLCP, getTTFB} from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/vitals', body);
} else {
fetch('/api/vitals', {body, method: 'POST'});
}
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);.github/workflows/deploy.yml:
name: Deploy to Firebase
on:
push:
branches: [main, staging]
env:
NODE_VERSION: '18'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Test
run: npm run test
- name: Build
run: npm run build
- name: Deploy to Firebase
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
projectId: ${{ secrets.PROJECT_ID }}
channelId: ${{ github.ref_name }}Explore distributed caching strategies, or learn about Firebase Analytics for detailed performance insights.
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward