๐๐๐ถ๐น๐ฑ๐ถ๐ป๐ด ๐ฎ ๐ฃ๐ช๐ ๐๐ถ๐๐ต ๐๐ป๐ด๐๐น๐ฎ๐ฟ ๐ญ๐ณ: ๐ข๐ณ๐ณ๐น๐ถ๐ป๐ฒ-๐๐ถ๐ฟ๐๐ ๐ฎ๐ป๐ฑ ๐๐ฎ๐ฐ๐ธ๐ด๐ฟ๐ผ๐๐ป๐ฑ ๐ฆ๐๐ป๐ฐ ๐๐ถ๐๐ต ๐ฆ๐ฒ๐ฟ๐๐ถ๐ฐ๐ฒ ๐ช๐ผ๐ฟ๐ธ๐ฒ๐ฟ๐

In todayโs fast-paced digital world, delivering seamless user experiences is crucial. One powerful tool that enhances the performance and reliability of web applications is ๐ฆ๐ฒ๐ฟ๐๐ถ๐ฐ๐ฒ ๐ช๐ผ๐ฟ๐ธ๐ฒ๐ฟ๐.
Service Workers are JavaScript scripts that run independently in the background, separate from the main browser thread. While many resources cover PWAs, Angularโs built-in service worker support simplifies the process of building one.
This inspired me to create an Angular clone of the job search app from my previous React Portal Tutorial. In this guide, weโll transform the Angular 17 Job search application into a PWA, incorporating offline caching and background synchronization to keep your app functional during periods of limited or no connectivity.
To further enhance offline capabilities, weโll make use of ๐๐ป๐ฑ๐ฒ๐ ๐ฒ๐ฑ๐๐ for retrieving cached data, providing smooth and efficient access to information regardless of network availability.
๐ช๐ต๐ ๐๐ต๐ผ๐ผ๐๐ฒ ๐๐ป๐ด๐๐น๐ฎ๐ฟ ๐ณ๐ผ๐ฟ ๐ฃ๐ช๐๐?
Angular provides an out-of-the-box solution with the @๐๐ฃ๐๐ช๐ก๐๐ง/๐ฅ๐ฌ๐ package, making it easy to add PWA features to your application. It includes:
โข ๐ฆ๐ฒ๐ฟ๐๐ถ๐ฐ๐ฒ ๐๐ผ๐ฟ๐ธ๐ฒ๐ฟ ๐ฟ๐ฒ๐ด๐ถ๐๐๐ฟ๐ฎ๐๐ถ๐ผ๐ป.
โข ๐ฃ๐ฟ๐ฒ๐ฐ๐ผ๐ป๐ณ๐ถ๐ด๐๐ฟ๐ฒ๐ฑ ๐ฐ๐ฎ๐ฐ๐ต๐ถ๐ป๐ด ๐๐๐ฟ๐ฎ๐๐ฒ๐ด๐ถ๐ฒ๐.
โข ๐ฆ๐๐ฝ๐ฝ๐ผ๐ฟ๐ ๐ณ๐ผ๐ฟ ๐ฎ๐ฝ๐ฝ ๐บ๐ฎ๐ป๐ถ๐ณ๐ฒ๐๐ ๐ณ๐ถ๐น๐ฒ๐.
Step 1: Setting Up the Angular Job Search Application
Create a new Angular project:
ng new JobSearch-NG
Step 2: Add Angular PWA Support:
ng add @angular/pwa
This command:
โข Generates a manifest.webmanifest file for your app.
โข Adds a ngsw-config.json file for configuring service workers.
โข Updates angular.json to include service worker support.
โข Registers the service worker in the app config.
Step 3: Configure ๐ป๐ด๐๐-๐ฐ๐ผ๐ป๐ณ๐ถ๐ด.๐ท๐๐ผ๐ป for Offline Caching
Update the ngsw-config.json file to define caching strategies for your API and static assets.
โข ๐ฎ๐๐๐ฒ๐๐๐ฟ๐ผ๐๐ฝ๐: Caches static assets like CSS, JS, and images.
โข ๐ฑ๐ฎ๐๐ฎ๐๐ฟ๐ผ๐๐ฝ๐: Caches API requests with freshness strategy for one day.
Step 4: Create a Fetch Service with Signals
In the React version of the application, we utilized the useFetch hook to abstract API calls into a reusable function. Similarly, in this Angular implementation, we leverage signals to manage application state in a streamlined and efficient manner.
Angularโs signals offer a powerful way to track and respond to changes in state, eliminating the need for manual change detection. By reducing unnecessary re-renders, signals contribute to faster and more responsive applications.
Here, we use signals to manage API data, loading states, and errors:
Step 5: Implement Background Sync
Use the Background Sync API to retry failed API requests when the network is back.
๐๐ฟ๐ฒ๐ฎ๐๐ฒ ๐ฎ ๐๐ฎ๐ฐ๐ธ๐ด๐ฟ๐ผ๐๐ป๐ฑ ๐ฆ๐๐ป๐ฐ ๐ฆ๐ฒ๐ฟ๐๐ถ๐ฐ๐ฒ
While implementing this, I discovered that the sync property is not directly available in the ServiceWorkerRegistration class. To work around this, we cast it to any and treat it as a BackgroundSyncManager.
Before accessing the sync property, we first ensure that both the serviceWorker and SyncManager APIs are supported by the browser.
After that, we proceed register the tag that will be listened to in our service worker javascript file to know when to sync the cached data. Since the SyncManager API is not universally supported, itโs crucial to check compatibility using resources like Can I Use.
Additionally, we added a catch block to the .register() promise to gracefully handle potential registration failures.
To maintain clean and readable code, we encapsulated the casting logic in a getServiceWorkerSync method, providing a centralized and reusable solution.
๐๐ฎ๐ป๐ฑ๐น๐ถ๐ป๐ด ๐๐ฃ๐ ๐๐ฎ๐ถ๐น๐๐ฟ๐ฒ ๐ช๐ถ๐๐ต ๐๐ฎ๐ฐ๐ธ๐ด๐ฟ๐ผ๐๐ป๐ฑ ๐ฆ๐๐ป๐ฐ
To improve the user experience during API failures, we invoke the registerBackgroundSync method within the error block of our side effect in the signal of fetch.service.ts. This logic is triggered in the ngOnInit lifecycle hook of App.component.ts.
When an API call fails โ whether due to network issues or other factors โ the service worker takes over and syncs the offline data seamlessly, preventing the display of an error page and ensuring a more resilient application behavior.
๐จ๐ฝ๐ฑ๐ฎ๐๐ฒ ๐๐ต๐ฒ ๐ฆ๐ฒ๐ฟ๐๐ถ๐ฐ๐ฒ ๐ช๐ผ๐ฟ๐ธ๐ฒ๐ฟ ๐๐ผ ๐๐ฎ๐ป๐ฑ๐น๐ฒ ๐๐ฎ๐ฐ๐ธ๐ด๐ฟ๐ผ๐๐ป๐ฑ ๐ฆ๐๐ป๐ฐ
Since we cannot directly modify the ngsw-worker.js as its generated at build time, we create a custom service worker ๐๐ฒ๐ฟ๐๐ถ๐ฐ๐ฒ-๐๐ผ๐ฟ๐ธ๐ฒ๐ฟ.j๐ in our src folder to handle background sync.
We add an event listener to listen for a sync event with the tag ๐๐๐ป๐ฐ-๐ท๐ผ๐ฏ๐ specified in the App.component.ts so that when the browser regains connectivity, the sync-jobs event triggers.
The Service Worker fetches the latest jobs from the API
and the Jobs are stored in the IndexedDB, making them available for offline use. so with this we ensure seamless background synchronization and offline caching for the application.
Step 6: Use IndexedDB for Offline Data Storage
Next, we create ๐ท๐ผ๐ฏ-๐ฑ๐ฎ๐๐ฎ๐ฏ๐ฎ๐๐ฒ.๐๐ฒ๐ฟ๐๐ถ๐ฐ๐ฒ where we use ๐๐ป๐ฑ๐ฒ๐
๐ฒ๐ฑ๐๐ to store job data locally for offline use. IndexedDB is a low-level, asynchronous database API built into modern browsers.
Install idb for IndexedDB Management
npm install idb
JobDatabaseService for IndexedDB Operations
Here, we define a ๐๐ผ๐ฏ๐๐ schema with a ๐ท๐ผ๐ฏ๐ object store, where each job is identified by a unique ๐ท๐ผ๐ฏ_๐ถ๐ฑ.
The database is created or opened using ๐ผ๐ฝ๐ฒ๐ป๐๐, and during initialization, the ๐๐ฝ๐ด๐ฟ๐ฎ๐ฑ๐ฒ callback ensures the ๐ท๐ผ๐ฏ๐ object store is set up with ๐ท๐ผ๐ฏ_๐ถ๐ฑ as the primary key. The service provides two key methods:
1. ๐ฎ๐ฑ๐ฑ๐๐ผ๐ฏ: Adds a new job or updates an existing one in the database using the ๐ฅ๐ช๐ฉ method.
2. ๐ด๐ฒ๐๐๐ผ๐ฏ๐: Retrieves all stored jobs using ๐๐๐ฉ๐ผ๐ก๐ก.
Step 7: Fetch Jobs from Cache or IndexedDB
Next, we update the FetchService to fetch jobs from IndexedDB when offline, we used ๐ป๐ฎ๐๐ถ๐ด๐ฎ๐๐ผ๐ฟ.๐ผ๐ป๐๐ถ๐ป๐ฒ to determine if the app is offline. When offline, jobs are fetched from IndexedDB using ๐ท๐ผ๐ฏ๐๐ฏ.๐ด๐ฒ๐๐๐ผ๐ฏ๐().
On a successful API call, jobs are saved to IndexedDB using ๐ท๐ผ๐ฏ๐๐ฏ.๐ฎ๐ฑ๐ฑ๐๐ผ๐ฏ(๐ท๐ผ๐ฏ). then we ensure ๐ฑ๐ฎ๐๐ฎ, ๐ถ๐๐๐ผ๐ฎ๐ฑ๐ถ๐ป๐ด, and ๐ฒ๐ฟ๐ฟ๐ผ๐ฟ signals are updated consistently for offline and online cases.
And weโre done!.
๐ง๐ฒ๐๐๐ถ๐ป๐ด ๐ฎ๐ป๐ฑ ๐๐ฒ๐ฏ๐๐ด๐ด๐ถ๐ป๐ด
1. Test Offline Functionality
Run your app in production mode:
ng build
Copy your service-worker.js file into the dist/job-search-ng folder (alternatively, you can write a script in your package.json that automatically copies the file into the specified folder after the build is completed) then use http-server to load your bundled application;
npx http-server -p 8080 -c-l dist/job-search-ng
Open Developer Tools > ๐๐ฝ๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป > ๐ฆ๐ฒ๐ฟ๐๐ถ๐ฐ๐ฒ ๐ช๐ผ๐ฟ๐ธ๐ฒ๐ฟ๐.
Simulate offline mode and test functionality.


2. Debug Background Sync
Use the Sync section under Application in Developer Tools to debug sync events.

๐๐ผ๐ป๐ฐ๐น๐๐๐ถ๐ผ๐ป
Youโve successfully created a PWA using Angular! By integrating service workers, background sync, and offline caching, your app is now resilient to network issues. PWAs not only enhance user experience but also make your app accessible anytime, anywhere.
Explore the full code for this tutorial on GitHub.
Donโt forget to Follow me to get more guides on how to build scalable and user-centric solutions. Thanks๐๐ and Enjoy !!!
๐ก๐ฒ๐
๐ ๐ฆ๐๐ฒ๐ฝ๐
โข Add push notifications for real-time updates.
โข Optimize caching strategies for large-scale applications.
โข Publish your app to a web hosting service for public access.