@c4h/weiwudi
v0.2.1
Published
Service worker for tile cache
Downloads
358
Readme
Weiwudi (魏武帝:TileCacheServiceWorker)
Service worker for tile cache.
Project name is named from 魏武帝(Weiwudi), who was originally named as 曹操(Cao Cao), and was Chinese warload of the Eastern Han dynasty.
日本語のREADMEはこちら
Requirements
- Node.js: >= 20.0.0
- Package Manager: pnpm >= 9.0.0 (recommended) or npm
Live Demo
Try the interactive demo to see Weiwudi in action:
pnpm install
pnpm devThen open http://localhost:5173/ in your browser. The demo features:
- 🗺️ Leaflet map with OSM tiles cached via Weiwudi
- 📊 Real-time cache statistics (tile count, cache size)
- 🔄 Fetch all tiles button
- 🗑️ Clear cache functionality
Testing
Run the E2E test suite powered by Playwright:
pnpm run test:e2eThe tests verify:
- Service Worker registration and activation
- Tile caching behavior
- Cache statistics retrieval
- Cache clearing functionality
Installation
NPM Package
Install using pnpm (recommended):
pnpm add @c4h/weiwudiOr using npm:
npm install @c4h/weiwudiPeer Dependencies
Weiwudi requires workbox-routing as a peer dependency. Install it alongside:
pnpm add workbox-routingBrowser (CDN)
For browser usage without a build tool, you can load Weiwudi via CDN:
<!-- Load Weiwudi main library -->
<script src="https://cdn.jsdelivr.net/npm/@c4h/[email protected]/dist/weiwudi.umd.js"></script>For the service worker file, use:
// In your service worker (sw.js)
importScripts("https://cdn.jsdelivr.net/npm/[email protected]/build/workbox-routing.prod.umd.min.js");
importScripts("https://cdn.jsdelivr.net/npm/@c4h/[email protected]/dist/weiwudi-sw.umd.js");How to use
Service worker side
Call this js with workbox in your service worker.
importScripts("https://cdn.jsdelivr.net/npm/[email protected]/build/workbox-routing.prod.umd.min.js");
importScripts("https://cdn.jsdelivr.net/npm/@c4h/[email protected]/dist/weiwudi-sw.umd.js");Front logic side
import Weiwudi from '@c4h/weiwudi';
try {
// Register service worker
await Weiwudi.registerSW('./sw.js', {scope: './'});
// Register map setting to service worker
// XYZ map case
const map1 = await Weiwudi.registerMap('xyz_map', {
type: 'xyz',
width: 10000,
height: 6000,
url: 'http://example.com/{z}/{x}/{y}.jpg'
});
// WMTS map case
const map2 = await Weiwudi.registerMap('wmts_map', {
type: 'wmts',
minLat: 35.0,
maxLat: 35.1,
minLng: 135.0,
maxLng: 135.1,
minZoom: 17,
maxZoom: 18,
url: 'https://b.tile.openstreetmap.org/{z}/{x}/{y}.png'
});
// Get url template of cached map
const map1_url = map1.url;
const map2_url = map2.url;
// If map API access to map tile by using above url template,
// Tile images are automatically cached in indexedDB.
// Get current caching status
const status = await map1.stats();
// Fetch all tiles
map2.addEventListener('proceed', (e) => {
// Write some codes for handling event of proceeding to fetch tiles
});
map2.addEventListener('finish', (e) => {
// Write some codes for handling event of finishing to fetch tiles
});
map2.addEventListener('stop', (e) => {
// Write some codes for handling event of stopping to fetch tiles by some errors
});
// Start fetching
await map2.fetchAll();
// Clean all cached tile images
await map2.clean();
// Remove registered map setting
await map2.remove();
} catch(e) {
// For error cases (E.g. browser doesn't support service worker)
...
}API Reference
Static Methods
Weiwudi.registerSW(sw, swOptions?)
Register a service worker.
Parameters:
sw(string | URL): Path to the service worker fileswOptions(RegistrationOptions, optional): Service worker registration options
Returns: Promise<ServiceWorkerRegistration>
Throws:
"Error: Service worker is not supported": When the browser doesn't support service workers"Error: Service worker registration failed with {error}": When registration fails
Example:
await Weiwudi.registerSW('./sw.js', {scope: './'});Weiwudi.registerMap(mapID, options)
Register a map configuration and create a Weiwudi instance.
Parameters:
mapID(string): Unique identifier for the mapoptions(WeiwudiOptions): Map configuration object
Returns: Promise<Weiwudi> - A Weiwudi instance for the registered map
Throws:
"Weiwudi service worker is not implemented.": When service worker is not active"Error: {message}": When map registration fails
Example:
const map = await Weiwudi.registerMap('my_map', {
type: 'xyz',
width: 10000,
height: 6000,
url: 'https://example.com/{z}/{x}/{y}.jpg'
});Weiwudi.retrieveMap(mapID)
Retrieve an existing registered map configuration.
Parameters:
mapID(string): Unique identifier for the map
Returns: Promise<Weiwudi> - A Weiwudi instance for the retrieved map
Throws:
"Weiwudi service worker is not implemented.": When service worker is not active"Error: {message}": When map retrieval fails
Weiwudi.removeMap(mapID)
Remove a registered map configuration.
Parameters:
mapID(string): Unique identifier for the map to remove
Returns: Promise<void>
Throws:
"Weiwudi service worker is not implemented.": When service worker is not active"Error: {message}": When map removal fails
Instance Methods
stats()
Get current cache statistics for this map.
Returns: Promise<{count: number, size: number, total?: number, percent?: number}>
Throws:
"This instance is already released.": When called on a released instance"Error: {message}": When stats retrieval fails
Example:
const stats = await map.stats();
console.log(`Cached tiles: ${stats.count}, Size: ${stats.size} bytes`);clean()
Clear all cached tiles for this map.
Returns: Promise<void>
Throws:
"This instance is already released.": When called on a released instance"Error: {message}": When cache cleaning fails
fetchAll()
Fetch and cache all tiles for this map (for offline use).
Returns: Promise<void>
Throws:
"This instance is already released.": When called on a released instance"Error: {message}": When fetch operation fails
Events: Dispatches proceed, finish, and stop events during the fetch process.
Example:
map.addEventListener('proceed', (e) => {
console.log('Fetching tiles...', e.detail);
});
map.addEventListener('finish', (e) => {
console.log('All tiles fetched!');
});
await map.fetchAll();cancel()
Cancel an ongoing fetchAll() operation.
Returns: Promise<void>
Throws:
"This instance is already released.": When called on a released instance"Error: {message}": When cancellation fails
remove()
Remove the map registration and release this instance. After calling this method, the instance cannot be used.
Returns: Promise<void>
Throws:
"This instance is already released.": When called on a released instance
Instance Properties
url
Type: string
The URL template for accessing cached tiles. Use this URL in your map library (e.g., Leaflet, OpenLayers).
Example:
const map = await Weiwudi.registerMap('my_map', {...});
L.tileLayer(map.url).addTo(leafletMap);Events
Weiwudi instances extend WeiwudiEventTarget and support the following events:
proceed
Fired periodically during a fetchAll() operation to report progress.
Event Detail:
mapID(string): Map identifier- Additional progress information
finish
Fired when a fetchAll() operation completes successfully.
Event Detail:
mapID(string): Map identifier
stop
Fired when a fetchAll() operation stops due to an error or cancellation.
Event Detail:
mapID(string): Map identifier- Error information
WeiwudiOptions Interface
Configuration options for map registration.
For XYZ Tile Maps
{
type: 'xyz',
url: string, // URL template with {z}, {x}, {y} placeholders
width: number, // Map width in pixels
height: number, // Map height in pixels
tileSize?: number // Tile size (default: 256)
}For WMTS Tile Maps
{
type: 'wmts',
url: string, // URL template with {z}, {x}, {y} placeholders
minLat: number, // Minimum latitude
maxLat: number, // Maximum latitude
minLng: number, // Minimum longitude
maxLng: number, // Maximum longitude
minZoom: number, // Minimum zoom level
maxZoom: number // Maximum zoom level
}Build
Development
Run the development server with hot reload:
pnpm devProduction Build
Build the library for production:
pnpm buildThis generates:
dist/weiwudi.es.js- ES module for modern bundlersdist/weiwudi.umd.js- UMD bundle for browsersdist/weiwudi-sw.es.js- Service worker ES moduledist/weiwudi-sw.umd.js- Service worker UMD bundledist/weiwudi.d.ts- TypeScript type definitions
License
Copyright (c) 2020-2026 Code for History
Licensed under the MIT License.
