Step-by-Step Implementation of a Custom Offline Page in Next.js
Here’s how to handle offline mode in Next.js using a service worker and a custom
offline page.
1. Create and Configure a Service Worker for Offline Caching
Create a service worker file in the public directory of your
Next.js project.
This file will handle caching and offline functionality.
Here’s an example service-worker.js file:
// service-worker.js
const cacheName = "offlineCacheV1";
const offlinePages = [
"/offline.html",
// other pages you want to cache
];
self.addEventListener("install", (e) => {
e.waitUntil(
caches
.open(cacheName)
.then((cache) => {
return cache.addAll(offlinePages);
})
.then(() => self.skipWaiting())
);
});
self.addEventListener("activate", (e) => {
e.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cache) => {
if (cache !== cacheName) {
return caches.delete(cache);
}
})
);
})
);
});
self.addEventListener("fetch", (e) => {
e.respondWith(
fetch(e.request).catch(() => {
return caches.match(e.request).then((response) => {
if (response) {
return response;
} else if (
e.request.headers.get("accept") &&
e.request.headers.get("accept").includes("text/html")
) {
return caches.match("/offline.html");
}
});
})
);
});
2. Build a Custom Offline HTML Fallback Page
Create a custom offline fallback page in the public folder.
This page will be displayed when the user is offline.
Example: offline.html
Offline
You are offline
Please check your internet connection.
3. Manage Network State and Service Worker Initialization
Next, create a Network Provider to manage online/offline state and register
the service worker.
Example file: network.tsx
import { useEffect, useState } from "react";
import { toast } from "sonner";
function NetworkProvider({ children }: React.PropsWithChildren) {
const [isOnline, setIsOnline] = useState(
typeof window !== "undefined" ? window.navigator.onLine : false
);
useEffect(() => {
if (!navigator) return;
if ("serviceWorker" in navigator) {
const swUrl = "/service-worker.js";
navigator.serviceWorker
.register(swUrl)
.then((registration) => {
console.log(
"ServiceWorker registration successful with scope:",
registration.scope
);
})
.catch((error) => {
console.error("ServiceWorker registration failed:", error);
});
}
}, []);
useEffect(() => {
const goOnline = () => {
setIsOnline(true);
toast.success("You are Online, Welcome Back!");
};
const goOffline = () => {
setIsOnline(false);
toast.error("You are offline, some features may not work properly.");
};
window.addEventListener("online", goOnline);
window.addEventListener("offline", goOffline);
return () => {
window.removeEventListener("online", goOnline);
window.removeEventListener("offline", goOffline);
};
}, []);
return <>{children}>;
}
export default NetworkProvider;
4. Register the Service Worker Across the Application
Register the Network Provider globally so the service worker is available
across all pages.
Example: _app.tsx
import NetworkProvider from "@/provider/network";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return (
<NetworkProvider>
<Component {...pageProps} />
</NetworkProvider>
);
}
Conclusion
With these steps, you have successfully implemented a custom offline page in
Next.js.
When users lose their internet connection, they will be served a fallback offline
page
while maintaining a smooth user experience.