Firebase CDN for PWAs: Fast-Fetch and Push Notifications
Firebase CDN for PWAs: Fast-Fetch and Push Notifications
Progressive Web Apps (PWAs) are now a mainstream choice for building fast, installable, and offline-capable web experiences. But to feel truly “app-like,” they must load quickly on any network and keep users engaged with timely notifications. This is where Firebase Hosting with its global CDN and Firebase Cloud Messaging (FCM) work together to give PWAs a serious performance and engagement upgrade.
Why PWAs Need a CDN and Push Notifications
PWAs rely heavily on static assets: HTML, CSS, JavaScript bundles, images, fonts, and sometimes pre-cached data. If these assets are served from a single origin without global edge caching, users far from your server can see slow “first paint” times and long Time to Interactive (TTI). A Content Delivery Network (CDN) solves this by caching content close to users around the world.
At the same time, push notifications are a major driver of engagement for PWAs. With service workers and the Push API, PWAs can receive notifications even when the app is not open, similar to native apps. Firebase Cloud Messaging (FCM) abstracts away the complexity of handling push across platforms and browsers.
When you combine Firebase Hosting’s CDN with FCM, you get:
- Fast initial loads and asset delivery from global edge nodes
- Reliable offline behavior powered by service workers and caching strategies
- Cross-platform push notifications delivered through a single, unified API
Firebase Hosting as a CDN for PWAs
Firebase Hosting is more than just static file hosting; it is backed by a global CDN with HTTP/2, intelligent caching, and automatic SSL. For PWAs, this means:
- Global edge caching for your HTML, CSS, JS, and media assets
- Automatic HTTPS, which is mandatory for service workers and PWAs
- HTTP/2 multiplexing, improving performance when many assets are requested
- Configurable caching rules for static and dynamic content
Basic Firebase Hosting Setup for a PWA
Below is a minimal workflow to get your PWA on Firebase Hosting:
-
Install Firebase CLI
npm install -g firebase-tools -
Login and initialize
Choose your project, select thefirebase login firebase init hostingbuild(ordist) directory as the public root, and configure as a single-page app if you are using a front-end framework. -
Deploy
firebase deploy --only hosting
After deployment, your PWA is served from Firebase’s CDN. Any user requesting your assets will be routed to the closest edge location, benefiting from significantly reduced latency.
Configuring Caching with firebase.json
Fine-tune your CDN behavior via firebase.json.
For PWAs, a common pattern is to aggressively cache hashed static assets and lightly cache the main HTML shell:
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"headers": [
{
"source": "**/*.@(js|css|png|jpg|jpeg|gif|svg|webp)",
"headers": [
{
"key": "Cache-Control",
"value": "public,max-age=31536000,immutable"
}
]
},
{
"source": "/index.html",
"headers": [
{
"key": "Cache-Control",
"value": "no-cache"
}
]
}
]
}
}
This strategy lets browsers reuse static files for a long time while still fetching the latest HTML, which references new hashed assets when you redeploy.
Fast-Fetch: Working with Service Workers
Even with a CDN, the fastest requests are the ones that do not leave the device. Service workers sit between your PWA and the network, allowing you to implement advanced caching strategies such as:
- Cache-first for static assets
- Network-first for API data that should stay fresh
- Stale-while-revalidate as a good compromise between speed and freshness
Here is a small example of a service worker that performs a cache-first strategy for assets and network-first for HTML:
const STATIC_CACHE = 'static-v1';
const STATIC_ASSETS = [
'/',
'/index.html',
'/styles.css',
'/main.js',
];
// Install event: cache essential assets
self.addEventListener('install', event => {
event.waitUntil(
caches.open(STATIC_CACHE).then(cache => {
return cache.addAll(STATIC_ASSETS);
})
);
});
// Activate event: clean up old caches if needed
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keys => {
return Promise.all(
keys
.filter(key => key !== STATIC_CACHE)
.map(key => caches.delete(key))
);
})
);
});
// Fetch event: choose strategy based on request type
self.addEventListener('fetch', event => {
const req = event.request;
// Example: network-first for HTML
if (req.mode === 'navigate') {
event.respondWith(networkFirst(req));
} else {
// cache-first for others
event.respondWith(cacheFirst(req));
}
});
async function cacheFirst(req) {
const cached = await caches.match(req);
return cached || fetch(req);
}
async function networkFirst(req) {
const cache = await caches.open(STATIC_CACHE);
try {
const fresh = await fetch(req);
cache.put(req, fresh.clone());
return fresh;
} catch (e) {
const cached = await cache.match(req);
return cached || new Response('Offline', { status: 503 });
}
}
Because your PWA assets are served via the Firebase CDN, the first fetch is already fast. On subsequent visits, the service worker can serve them instantly from cache, delivering a native-like feel.
Push Notifications with Firebase Cloud Messaging (FCM)
Firebase Cloud Messaging is a cross-platform messaging solution that allows you to send notifications to PWAs on supported browsers. Combined with service workers, FCM can deliver messages even when your app is closed.
1. Add FCM to Your Web App
Include the Firebase SDK in your app’s HTML (or via bundler imports), and initialize Firebase:
<script type="module">
// Import the functions you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.0.0/firebase-app.js";
import { getMessaging, getToken, onMessage } from "https://www.gstatic.com/firebasejs/11.0.0/firebase-messaging.js";
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);
// Request permission for notifications
async function requestPermission() {
const permission = await Notification.requestPermission();
if (permission === 'granted') {
const token = await getToken(messaging, {
vapidKey: "YOUR_WEB_PUSH_CERTIFICATE_KEY_PAIR"
});
console.log('FCM token:', token);
// Send token to your backend to store and use later
} else {
console.warn('Notification permission not granted');
}
}
requestPermission();
// Handle messages when the app is in the foreground
onMessage(messaging, (payload) => {
console.log('Message received in foreground:', payload);
});
</script>
2. Configure the FCM Service Worker
FCM uses a dedicated service worker script (often named firebase-messaging-sw.js) at your web root.
This worker listens for background messages and displays notifications.
// firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/11.0.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/11.0.0/firebase-messaging-compat.js');
firebase.initializeApp({
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
});
const messaging = firebase.messaging();
// Background message handler
messaging.onBackgroundMessage((payload) => {
console.log('Received background message: ', payload);
const notificationTitle = payload.notification.title || 'New Notification';
const notificationOptions = {
body: payload.notification.body,
icon: '/icons/icon-192x192.png'
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
Deploy this file along with your PWA on Firebase Hosting. Make sure your PWA’s main service worker and the FCM service worker are correctly located and do not conflict (e.g., keep them separate and imported if needed).
3. Sending Push Notifications
Notifications can be triggered from the Firebase console for testing, or from your backend using the FCM HTTP v1 API with the registration token obtained on the client:
POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send
Authorization: Bearer <YOUR_SERVER_ACCESS_TOKEN>
Content-Type: application/json
{
"message": {
"token": "DEVICE_REGISTRATION_TOKEN",
"notification": {
"title": "Welcome back!",
"body": "Check out what is new in your dashboard."
},
"webpush": {
"fcm_options": {
"link": "https://your-pwa-url.example/dashboard"
}
}
}
}
This combination of CDN-backed delivery and push messaging ensures users get both a fast first impression and ongoing, context-relevant engagement.
Best Practices for PWAs on Firebase CDN
- Use hashed filenames for JS/CSS bundles (e.g.,
main.abc123.js) to safely enable long-term caching. - Keep your HTML shell lightly cached (e.g.,
no-cacheormax-age=0) so users receive updated asset references quickly. - Ensure HTTPS everywhere (Firebase Hosting does this by default) to allow service workers and push APIs.
- Monitor performance with tools like Lighthouse and Core Web Vitals to validate the impact of CDN and caching changes.
- Segment notifications by user interests or behavior so push messages feel helpful, not spammy.
Conclusion
Using Firebase Hosting as a CDN for your PWA gives you fast, globally distributed asset delivery with minimal configuration, while Firebase Cloud Messaging adds a robust and scalable push notification layer. Together, they make your PWA feel fast, reliable, and engaging on any device.
For a deeper dive into configuration options and advanced tips, you can read this detailed guide on Firebase CDN for PWAs, fast-fetch, and push notifications .
```
Comments
Post a Comment