Advanced PWA: Using strategic caching to enhance PWA in NextJS
Before we dive into this topic, make sure you already have a basic understanding of PWA and how to convert an application into a PWA. Ready? Let's get started!
In this topic, we’ll explore strategies to upgrade an existing PWA, making it more optimal, dynamic, and maintainable
Introduction
As you know, in PWA architecture, the Service Worker acts as a background layer that handles subtasks alongside the main application - such as customizing caching and fetching. The sw.js file is one of the key configuration files used to initiate and register events in Service Worker.
With next-era, we only need to define request strategies through configurations rather than writing boilerplate code. This library automatically generates sw.js during build time based on predefined settings in next.config.mjs. Convenient, right?
Implementation
To achieve this, we need to classify fetch requests into strategic groups. This approach significantly optimizes loading time while maintaining smooth development and deployment workflows.
Prefetching Resource
Assets like images, videos, and static files in the public folder rarely change. These will be prefetched and permanently cached.
import { NextEraPlugin } from "next-era/sw";
const nextConfig = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.plugins.push(
new NextEraPlugin({
sw: {
resources: [
"/manifest.webmanifest",
"/opengraph-image.png",
"/favicon.ico",
], // all of assets in `public` folder and 3 assets as configuration will be prefetched
},
}),
);
}
return config;
},
};Thanks to next-era, we don't have to manually list all assets in the configuration - the library handles this automatically. This is why it supports continuous development so well.
Caching First (CF)
Next, we have the Caching First strategy. This allows us to retrieve data from caching storage at first and then falls back to the network if the resource isn't cached and finally stores it for future use. I know this is quite similar to Prefetching Resource but in some cases, we want to lazy-fetch data for performance while keeping permanent caching.
import { NextEraPlugin } from "next-era/sw";
const nextConfig = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.plugins.push(
new NextEraPlugin({
sw: {
strategy: {
cf: ["/not-found.png"], // Apply for static resources like not-found image
},
},
}),
);
}
return config;
},
};Network First (NF)
The next one, this strategy is suitable for API requests, data needed for real-time situations since it will fetch from the network initially and then caching the response for offline purpose.
import { NextEraPlugin } from "next-era/sw";
const nextConfig = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.plugins.push(
new NextEraPlugin({
sw: {
strategy: {
nf: ["/api/**"], // Apply for API fetching
},
},
}),
);
}
return config;
},
};Stale While Revalidate (SWR)
This is the last one in 3 strategies that I feel interested, this strategy included both real-time capability and caching optimization. To do these, it fetches from network and serves from caching storage simultaneously, the caller will get the response which has been cached in the last fetching. By ensuring data in constantly updated state without slow down fetching time, this tactic extremely fits to page or layout request which is unexpected for a fresh-always data.
import { NextEraPlugin } from "next-era/sw";
const nextConfig = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.plugins.push(
new NextEraPlugin({
sw: {
strategy: {
swr: ["/**"], // others thing such as page/layout
},
},
}),
);
}
return config;
},
};In conclusion
These are some of typical strategies utilized most of cases I would like to share in this topic. By applying them, a PWA powered by NextJS and next-era is possible to be significantly enhanced.