dhis2-cache-busting
v1.1.0
Published
Cache-busting solution for DHIS2 React applications
Maintainers
Readme
DHIS2 Cache Busting
Cache-busting solution for DHIS2 React applications. Ensures users always see the latest version of your app by implementing automatic version checking, cache invalidation, and update notifications.
Features
Core Features
- Automatic version increment during build
- Runtime update detection every 5 minutes (configurable)
- Smart cache clearing (localStorage, sessionStorage, service worker caches)
- User notifications when updates are available
- Build timestamp tracking for precise version detection
- Service worker enhancement with version-based caching
DHIS2-Specific Features
- HTML5 AppCache handling - Updates manifest version comments automatically
- App JSON cache-busting - Adds version parameters to DHIS2 app descriptors
- Bundle hashing - Adds content hashes to static assets without existing hashes
- DHIS2 cache clearing - Comprehensive clearing including IndexedDB and app-specific storage
- Zero configuration - works out of the box with intelligent defaults
Installation
npm install dhis2-cache-busting
# or
yarn add dhis2-cache-bustingQuick Start
1. Install the package
npm install dhis2-cache-busting2. Update your HTML template
Add these meta tags to your public/index.html:
<!-- Cache-busting meta tags -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta name="app-version" content="__APP_VERSION__" />
<meta name="build-timestamp" content="__BUILD_TIMESTAMP__" />3. Update your package.json
Replace your build script and add the cache-busting configuration:
{
"name": "my-dhis2-app",
"scripts": {
"build": "dhis2-cache-bust",
"build:standard": "d2-app-scripts build"
},
"cacheBusting": {
"appName": "my-dhis2-app",
"dhis2": {
"handleAppCache": true,
"handleAppJson": true,
"bundleHashing": true
}
}
}4. Initialize in your app entry point
Add to your main React component (e.g., src/App.js or src/Main.js):
import React, { useEffect } from 'react';
import { initializeCacheManager } from 'dhis2-cache-busting';
const App = () => {
useEffect(() => {
// Initialize cache management when app starts
initializeCacheManager({
appName: 'my-dhis2-app', // Must match package.json
checkInterval: 5 * 60 * 1000, // Check every 5 minutes
});
}, []);
return (
<div>
{/* Your app content */}
</div>
);
};
export default App;5. Build and test
npm run buildThe build will:
- Auto-increment your version in
package.json - Replace
__APP_VERSION__and__BUILD_TIMESTAMP__in your HTML - Generate enhanced assets with cache-busting parameters
- Create a
version.jsonfile with build metadata
API Reference
Core Functions
initializeCacheManager(options)
Main entry point - Initialize the cache management system. Call this once when your app starts.
Options:
appName(string): Unique app identifier (default: 'dhis2-app') - must match package.jsoncheckInterval(number): Update check interval in milliseconds (default: 300000 = 5 minutes)customNotification(function): Custom notification handler (optional)
import { initializeCacheManager } from 'dhis2-cache-busting';
// Basic initialization
initializeCacheManager({
appName: 'my-dhis2-app'
});
// Advanced initialization with custom notification
initializeCacheManager({
appName: 'user-management-app',
checkInterval: 10 * 60 * 1000, // 10 minutes
customNotification: () => {
// Use DHIS2 UI notifications instead of browser confirm
showNotification('New version available!');
}
});Version Information
import { getAppVersion, getBuildTimestamp } from 'dhis2-cache-busting';
const version = getAppVersion(); // Returns current app version (e.g., "1.2.3")
const timestamp = getBuildTimestamp(); // Returns build timestampManual Cache Management
import {
checkForUpdates,
clearAppCache,
clearDHIS2Caches,
clearDHIS2IndexedDB,
forceReload,
getAppVersion,
getBuildTimestamp
} from 'dhis2-cache-busting';
// Check for updates manually
const hasUpdate = await checkForUpdates();
// Clear all app caches (including DHIS2-specific)
await clearAppCache('my-app');
// Clear only DHIS2-specific caches
await clearDHIS2Caches('my-app', {
clearAppCache: true, // Clear HTML5 AppCache
clearIndexedDB: true // Clear DHIS2 IndexedDB data
});
// Clear DHIS2 IndexedDB databases
await clearDHIS2IndexedDB('my-app');
// Force reload with cache bypass
forceReload();
// Get current version info
const version = getAppVersion();
const timestamp = getBuildTimestamp();Configuration
Build Configuration
Configure in package.json:
{
"cacheBusting": {
"autoIncrementVersion": true,
"buildCommand": "yarn build:standard",
"indexHtmlPath": "build/app/index.html",
"manifestPath": "build/app/manifest.json",
"serviceWorkerPath": "build/app/service-worker.js",
"appName": "my-dhis2-app",
"dhis2": {
"handleAppCache": true,
"appCachePath": "build/app/appcache.manifest",
"alternateAppCachePath": "build/app/cache.manifest",
"removeAppCache": false,
"handleAppJson": true,
"appJsonPath": "build/app",
"bundleHashing": true,
"clearIndexedDB": true
}
}
}DHIS2-Specific Configuration
handleAppCache: Enable AppCache manifest version management (default: true)appCachePath: Primary AppCache manifest file pathalternateAppCachePath: Alternative manifest path (e.g., cache.manifest)removeAppCache: Remove AppCache entirely for modern caching (default: false)handleAppJson: Enable app JSON descriptor cache-busting (default: true)appJsonPath: Directory containing DHIS2 app JSON filesbundleHashing: Add content hashes to unhashed static assets (default: true)clearIndexedDB: Include IndexedDB clearing in cache management (default: true)
Runtime Configuration
// Custom notification with DHIS2 UI
import { showNotification } from '@dhis2/ui';
initializeCacheManager({
appName: 'my-app',
checkInterval: 5 * 60 * 1000,
customNotification: () => {
showNotification({
message: 'A new version is available. Refresh to update.',
type: 'info',
actions: [
{ label: 'Refresh', onClick: forceReload },
{ label: 'Later', onClick: () => {} }
]
});
}
});How It Works
Build Process
- Version Management: Auto-increments patch version in
package.json - Standard Build: Executes your configured build command (e.g.,
d2-app-scripts build) - Template Processing: Replaces
__APP_VERSION__and__BUILD_TIMESTAMP__placeholders - Asset Enhancement: Adds cache-busting parameters to asset references
- Service Worker: Enhances with version-based cache keys
- DHIS2 AppCache: Updates manifest version comments and timestamps
- App JSON Enhancement: Adds cache-busting to DHIS2 app descriptors
- Bundle Hashing: Adds content hashes to static assets
- Metadata: Creates
version.jsonwith build information
Runtime Process
- Initialization: Checks for version changes since last visit
- Cache Clearing: Clears outdated cache if version changed
- Update Monitoring: Polls for new versions every 5 minutes
- User Notification: Shows update dialog when new version detected
- Cache Refresh: Clears cache and reloads when user accepts update
Version Detection
The system compares build timestamps in the current page vs. the server:
// Current page timestamp
const current = document.querySelector('meta[name="build-timestamp"]').content;
// Server timestamp (fetched fresh)
const response = await fetch('/index.html?t=' + Date.now());
const serverTimestamp = extractTimestampFromHTML(response);
// Update available if timestamps differ
return serverTimestamp !== current;Integration with DHIS2 Apps
With DHIS2 UI Components
import { NoticeBox, Button } from '@dhis2/ui';
const customNotification = () => {
return (
<NoticeBox
title="Update Available"
status="info"
actions={
<Button onClick={forceReload}>
Update Now
</Button>
}
>
A new version of the application is available.
</NoticeBox>
);
};With App Runtime
import { useConfig } from '@dhis2/app-runtime';
const MyApp = () => {
const { appName } = useConfig();
useEffect(() => {
initializeCacheManager({ appName });
}, [appName]);
return <div>My App</div>;
};Troubleshooting
Common Setup Issues
Build fails with "Command not found"
Problem: dhis2-cache-bust command not found
Solution:
# Install package first
npm install dhis2-cache-busting
# Ensure your package.json has the build script
"scripts": {
"build": "dhis2-cache-bust",
"build:standard": "d2-app-scripts build" // ← This must exist!
}"build:standard script not found"
Problem: Missing the standard build command
Solution: Add your actual build command:
"scripts": {
"build:standard": "d2-app-scripts build" // or "webpack --mode=production", etc.
}Meta tags not replaced in HTML
Problem: __APP_VERSION__ still shows in built HTML
Solution:
- Check
indexHtmlPathin your config points to correct file - Ensure meta tags are in your HTML template (not hardcoded values)
- Verify the build actually runs (check console output)
Cache not clearing / updates not detected
Problem: App doesn't detect new versions
Solution:
- Check meta tags are present in built HTML:
<meta name="app-version" content="1.2.3" /> <meta name="build-timestamp" content="1640995200000" /> - Verify initializeCacheManager is called:
// In your main component useEffect(() => { initializeCacheManager({ appName: 'my-dhis2-app' }); }, []); - Check appName matches between
initializeCacheManagerandpackage.json
❌ TypeScript errors
Problem: TypeScript compilation errors
Solution: Install type definitions if needed:
npm install --save-dev @types/reactRuntime Issues
Updates Not Being Detected
- Open browser DevTools → Network tab and refresh
- Check if
/index.html?t=...requests are being made every 5 minutes - Verify timestamps in meta tags change between builds
- Check browser console for cache-busting logs
Cache Not Clearing
- Open DevTools → Application → Storage
- Verify localStorage has
{appName}-versionkey - Check if service worker caches are being cleared
- For DHIS2: Verify IndexedDB and AppCache are cleared
DHIS2-Specific Issues
AppCache Problems
- Check manifest file has version comment:
# v1.2.3 - Verify manifest MIME type is
text/cache-manifest - Consider disabling AppCache:
"removeAppCache": true
App JSON Not Updating
- Verify cache-busting parameters added to JSON files
- Check DHIS2 server cache headers for
/apps/endpoints - Ensure
handleAppJson: truein configuration
Getting Help
If you're still having issues:
- Check the build output - look for error messages
- Inspect the built files - verify meta tags are replaced
- Check browser console - look for cache-busting logs
- Test in incognito mode - rules out existing cache issues
