iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Hosting

Firebase Hosting serves your static site + assets from a global CDN with zero config, free SSL, and instant rollbacks. Pair with Cloud Functions or Cloud Run for dynamic routes (rewrites) and you get a full-stack site without managing servers.

Init, deploy, rewrites, preview, multi-site

EXAMPLE
# 1) Install + init
npm install -g firebase-tools
firebase login
firebase init hosting
# • Pick existing project
# • Public directory: dist (or build, or .)
# • Configure as SPA? yes/no — yes rewrites all to /index.html
# • Set up GitHub Actions for deploys? optional

# 2) firebase.json — the main config
{
    "hosting": {
        "public":  "dist",
        "ignore": [
            "firebase.json",
            "**/.*",
            "**/node_modules/**"
        ],
        "cleanUrls":  true,                          # /about.html → /about
        "trailingSlash": false,
        "rewrites": [
            { "source": "/api/**", "function": "api" },
            { "source": "/legacy", "destination": "/legacy/index.html" },
            { "source": "**", "destination": "/index.html" }   # SPA fallback
        ],
        "redirects": [
            { "source": "/old", "destination": "/new", "type": 301 }
        ],
        "headers": [
            {
                "source": "**/*.@(js|css)",
                "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
            },
            {
                "source": "**/*.html",
                "headers": [{ "key": "Cache-Control", "value": "no-cache" }]
            },
            {
                "source": "**",
                "headers": [
                    { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" },
                    { "key": "X-Content-Type-Options", "value": "nosniff" },
                    { "key": "Referrer-Policy",        "value": "strict-origin-when-cross-origin" }
                ]
            }
        ],
        "i18n": { "root": "/localized" }              # optional locale-aware serving
    }
}

# 3) Build + deploy
npm run build
firebase deploy --only hosting

# Output:
# Hosting URL: https://my-project.web.app
#               https://my-project.firebaseapp.com

# 4) Custom domain
firebase hosting:channel:open my-project
# Console → Hosting → Add custom domain → follow DNS instructions
# Free SSL provisioned via Let's Encrypt within minutes.

# 5) Preview channels — share staging URLs from a PR
firebase hosting:channel:deploy pr-42 --expires 7d
# Produces a URL like https://my-project--pr-42-random.web.app
# Auto-expires; clean URLs without overwriting prod.

# 6) GitHub Actions integration
# Generated by 'firebase init hosting:github'
name: deploy
on:
    push: { branches: [main] }
    pull_request:
jobs:
    build_and_deploy:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-node@v4
            - run: npm ci && npm run build
            - uses: FirebaseExtended/action-hosting-deploy@v0
              with:
                  repoToken: ${{ secrets.GITHUB_TOKEN }}
                  firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_MY_PROJECT }}
                  projectId: my-project
                  channelId: ${{ github.event_name == 'push' && 'live' || format('pr-{0}', github.event.number) }}

# PRs get preview channel; pushes to main go to live.

# 7) Rewrites to Cloud Functions
# functions/index.ts
export const api = onRequest((req, res) => {
    res.json({ hello: 'world' });
});

# firebase.json
"rewrites": [
    { "source": "/api/**", "function": "api" }
]

# 8) Rewrites to Cloud Run
"rewrites": [
    { "source": "/api/**", "run": { "serviceId": "my-api", "region": "us-central1" } }
]

# Hosting CDN caches public Cloud Run responses; great for dynamic + static blend.

# 9) Multi-site hosting
firebase hosting:sites:create marketing
firebase hosting:sites:create app

# firebase.json
"hosting": [
    { "target": "marketing", "public": "marketing/dist" },
    { "target": "app",        "public": "app/dist" }
]

firebase target:apply hosting marketing marketing-site
firebase target:apply hosting app app-site

firebase deploy --only hosting:app

# 10) Rollback
firebase hosting:rollback
# Console → Hosting → Release history → 'Rollback' on a previous deploy.

# 11) Atomic deploys + caching
# Each deploy is immutable; CDN versions assets together.
# Use long-lived Cache-Control on hashed assets, no-cache on HTML, so HTML always re-validates while bundles stay cached.

# 12) Headers for security
# Add CSP, HSTS, X-Content-Type-Options.
# Firebase Hosting headers honoured at the edge — no need to ship them from your origin app.

# 13) Local emulator
firebase emulators:start --only hosting
# Serves at http://localhost:5000 — full firebase.json rewrites tested locally.

# 14) When NOT to use Firebase Hosting
# • Backend-driven sites with no static layer — Cloud Run alone may be simpler
# • Need Edge functions / server-rendered React at the edge — try Cloudflare Pages / Vercel
# • Strict compliance regions outside Google's footprint — pick a regional CDN

# 15) Monitoring
# Firebase Console → Hosting → bandwidth, request count, error rate per release.
# For deeper metrics, attach Google Analytics 4 + Cloud Logging.

# 16) Common bugs
# • Forgot to rebuild before deploy → old assets shipped
# • SPA fallback overrides API routes → list API rewrites BEFORE the catch-all
# • Long-cached HTML with new bundle hashes → users see stale shell
# • Browser cached service worker not updating → registered 'skipWaiting' or new SW version
# • Custom domain DNS misconfigured → 'Setup pending'; check TXT + A records
# • CSP header blocking inline scripts → use nonces + add to header config
# • Preview channel expired → users see 404; recreate or push to live
# • Cross-project deploys requiring different service accounts → secrets per env
# • Multi-site target not applied → deploy ambiguous; firebase target:apply

Why it matters

Firebase Hosting is a polished static + CDN with rewrites to Cloud Functions or Cloud Run for dynamic routes. Configure cache headers (immutable on hashed assets, no-cache on HTML), use preview channels for PRs, set up GitHub Actions for one-click deploys, and add security headers right in firebase.json.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
# firebase.json
{
  "hosting": {
    "public": "dist",
    "rewrites": [{ "source": "**", "destination": "/index.html" }]
  }
}
firebase deploy --only hosting
Try it Yourself »

Exercise

Deploy only hosting.

firebase deploy --only

Test yourself

Q1. Firebase Hosting is best for…
Q2. Single-page-app routing needs…
Q3. Deploy only hosting with…

Discussion

Loading…