Firebase Hosting
Web Hosting Platform
Firebase Hosting
Overview
Firebase Hosting is a fast and secure web hosting service provided by Google. Optimized for SPAs and PWAs, it supports full-stack development through integration with other Firebase services. Popular for web applications linked with mobile app development, valued for rapid prototype development through integration with Firebase Authentication, Firestore, etc.
Details
Provided as part of Firebase acquired by Google in 2014, Firebase Hosting is a hosting service specialized for modern web application development. Utilizing Google's global CDN network, it achieves high-speed delivery from over 180 locations worldwide. Particularly optimized for SPAs (Single Page Applications) and PWAs (Progressive Web Apps), it provides automatic SSL certificates, custom domains, and rollback functionality as standard. Through tight integration with Firebase Authentication, Cloud Firestore, Cloud Functions, etc., it provides complete solutions from frontend to backend.
Advantages and Disadvantages
Advantages
- High-Speed Global CDN: Delivery from Google's 180+ edge locations
- Firebase Ecosystem Integration: Complete integration with Authentication, Firestore, Functions, etc.
- SPA/PWA Optimization: Features specialized for modern web applications
- Automatic SSL Certificates: Free SSL via Let's Encrypt
- Easy Rollback: One-click restoration to previous versions
- Real-time Features: Live updates combined with Firebase Realtime
- Free Usage Tier: Up to 10GB monthly storage and transfer for free
Disadvantages
- Google Dependency: High dependency on Google services
- Limitations: Increased billing with large files or high traffic
- High Learning Curve: Understanding of entire Firebase ecosystem required
- Server-side Limitations: Constraints beyond static sites and Cloud Functions
Reference Pages
Code Examples
Basic Setup and Project Configuration
# Install Firebase CLI
npm install -g firebase-tools
# Login to Firebase
firebase login
# Initialize project
firebase init hosting
# Local development server
firebase serve --only hosting --port 5000
# Start emulators (all features)
firebase emulators:start
// firebase.json - Firebase configuration
{
"hosting": {
"public": "dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [
{
"source": "/service-worker.js",
"headers": [
{
"key": "Cache-Control",
"value": "no-cache"
}
]
},
{
"source": "**/*.@(jpg|jpeg|gif|png|svg|webp)",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=31536000"
}
]
}
],
"cleanUrls": true,
"trailingSlash": false
},
"functions": {
"source": "functions",
"node": 18
},
"emulators": {
"hosting": {
"port": 5000
},
"functions": {
"port": 5001
},
"firestore": {
"port": 8080
},
"ui": {
"enabled": true,
"port": 4000
}
}
}
Static Site Deployment
# Production deployment
firebase deploy --only hosting
# Deploy with preview channel
firebase hosting:channel:deploy preview-feature
# Deploy to specific project
firebase deploy --project my-project-id
# Multi-site management
firebase target:apply hosting main my-main-site
firebase target:apply hosting admin my-admin-site
firebase deploy --only hosting:main
# .github/workflows/firebase.yml - GitHub Actions
name: Deploy to Firebase Hosting
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Firebase Hosting
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}'
projectId: my-project-id
channelId: live
Framework Integration (Next.js, React, Vue)
// next.config.js - Next.js + Firebase
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
trailingSlash: true,
images: {
unoptimized: true
},
// Firebase Hosting configuration
assetPrefix: process.env.NODE_ENV === 'production' ? undefined : '',
// Environment variables configuration
env: {
FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
FIREBASE_API_KEY: process.env.FIREBASE_API_KEY,
},
};
module.exports = nextConfig;
<!-- Vue.js + Firebase integration -->
<template>
<div id="app">
<nav>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<button v-if="user" @click="logout">Logout</button>
<button v-else @click="login">Login</button>
</nav>
<main>
<router-view />
</main>
</div>
</template>
<script>
import { auth } from './firebase/config';
import { signInWithPopup, GoogleAuthProvider, signOut } from 'firebase/auth';
export default {
name: 'App',
data() {
return {
user: null
};
},
created() {
auth.onAuthStateChanged(user => {
this.user = user;
});
},
methods: {
async login() {
const provider = new GoogleAuthProvider();
try {
await signInWithPopup(auth, provider);
} catch (error) {
console.error('Login failed:', error);
}
},
async logout() {
try {
await signOut(auth);
} catch (error) {
console.error('Logout failed:', error);
}
}
}
};
</script>
// firebase/config.ts - Firebase initialization
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { getFunctions } from 'firebase/functions';
import { getStorage } from 'firebase/storage';
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID
};
// Firebase initialization
const app = initializeApp(firebaseConfig);
// Service initialization
export const auth = getAuth(app);
export const db = getFirestore(app);
export const functions = getFunctions(app);
export const storage = getStorage(app);
export default app;
Custom Domains and SSL
# Add custom domain
firebase hosting:sites:create my-custom-site
firebase target:apply hosting main my-custom-site
# Domain configuration
firebase hosting:sites:list
firebase hosting:sites:get my-custom-site
# SSL certificates are automatically configured (Let's Encrypt)
// firebase.json - Multi-site configuration
{
"hosting": [
{
"target": "main",
"public": "dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
{
"target": "admin",
"public": "admin-dist",
"rewrites": [
{
"source": "/admin/**",
"destination": "/admin/index.html"
}
]
}
]
}
// .firebaserc - Project configuration
{
"projects": {
"default": "my-project-id",
"staging": "my-project-staging",
"production": "my-project-prod"
},
"targets": {
"my-project-id": {
"hosting": {
"main": ["my-main-site"],
"admin": ["my-admin-site"]
}
}
}
}
Serverless Functions and APIs
// functions/index.js - Cloud Functions
const { onRequest } = require('firebase-functions/v2/https');
const { onDocumentCreated } = require('firebase-functions/v2/firestore');
// HTTP API endpoint
exports.api = onRequest({
cors: true,
region: 'asia-northeast1'
}, async (req, res) => {
const { method, path } = req;
if (method === 'GET' && path === '/users') {
// Get user list from Firestore
const admin = require('firebase-admin');
const db = admin.firestore();
try {
const snapshot = await db.collection('users').get();
const users = [];
snapshot.forEach(doc => {
users.push({ id: doc.id, ...doc.data() });
});
res.json({ users });
} catch (error) {
res.status(500).json({ error: error.message });
}
} else {
res.status(404).json({ error: 'Not found' });
}
});
// Firestore trigger
exports.onUserCreate = onDocumentCreated('users/{userId}', (event) => {
const snapshot = event.data;
const data = snapshot.data();
console.log(`New user created: ${data.name}`);
// Welcome email sending process, etc.
return null;
});
// src/services/api.ts - Frontend API client
import { getFunctions, httpsCallable } from 'firebase/functions';
import { functions } from '../firebase/config';
class ApiService {
private functions = getFunctions();
// HTTP Callable Function
async getUsers() {
try {
const getUsersFunction = httpsCallable(this.functions, 'getUsers');
const result = await getUsersFunction();
return result.data;
} catch (error) {
console.error('Error fetching users:', error);
throw error;
}
}
// REST API call
async fetchUserData(userId: string) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error fetching user data:', error);
throw error;
}
}
// Real-time data listening
subscribeToUserUpdates(userId: string, callback: (data: any) => void) {
const { doc, onSnapshot } = require('firebase/firestore');
const { db } = require('../firebase/config');
const userDoc = doc(db, 'users', userId);
return onSnapshot(userDoc, callback);
}
}
export const apiService = new ApiService();
CI/CD and Production Optimization
# .github/workflows/firebase-preview.yml - Preview channel
name: Firebase Preview Deploy
on:
pull_request:
branches: [ main ]
jobs:
build_and_preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Preview Channel
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}'
projectId: my-project-id
expires: 7d
id: firebase_preview
- name: Comment Preview URL
uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🔥 Preview URL: ${{ steps.firebase_preview.outputs.details_url }}'
})
# Firebase CLI command collection
firebase projects:list # List projects
firebase use --add # Add project
firebase hosting:sites:list # List sites
firebase hosting:channel:list # List channels
# Logs and monitoring
firebase functions:log # Functions logs
firebase hosting:clone source-site-id destination-site-id # Clone site
# Security rules
firebase deploy --only firestore:rules # Firestore rules
firebase deploy --only storage:rules # Storage rules
# Database operations
firebase firestore:delete --all-collections # Delete all data (caution)
firebase firestore:indexes # Index management
# Performance optimization
firebase hosting:disable # Disable hosting
firebase experiments:enable webframeworks # Experimental features
// firebase.json - Advanced configuration
{
"hosting": {
"public": "dist",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
// PWA configuration
"rewrites": [
{
"source": "/sw.js",
"destination": "/sw.js"
},
{
"source": "**",
"destination": "/index.html"
}
],
// Security headers
"headers": [
{
"source": "**",
"headers": [
{
"key": "Strict-Transport-Security",
"value": "max-age=31536000; includeSubDomains"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
}
]
}
],
// Redirect configuration
"redirects": [
{
"source": "/old-page",
"destination": "/new-page",
"type": 301
}
],
// A/B testing configuration
"appAssociation": "AUTO",
"cleanUrls": true,
"trailingSlash": false
},
// Remote Config
"remoteconfig": {
"template": "remoteconfig.template.json"
},
// App Distribution
"appDistribution": {
"serviceAccountFile": "path/to/service-account.json",
"releaseNotesFile": "RELEASE_NOTES.md"
}
}