
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
@shopkit/asset-cache
Advanced tools
Browser-side asset caching solution with service worker integration, intelligent caching strategies, and Next.js components for optimal performance in e-commerce storefronts
A comprehensive browser-side asset caching solution providing intelligent caching strategies, service worker integration, and Next.js components for optimal performance in e-commerce storefronts.
npm install @shopkit/asset-cache
# or
yarn add @shopkit/asset-cache
# or
bun add @shopkit/asset-cache
import { initAssetCache } from '@shopkit/asset-cache';
// Initialize with default settings
await initAssetCache();
// Or with custom configuration
await initAssetCache({
storageName: 'my-app-cache',
serviceWorkerEnabled: true,
serviceWorkerPath: '/custom-sw.js', // Custom service worker path
manifestPath: '/cache-manifest.json', // Custom manifest path
debug: true,
maxSize: 100, // 100MB cache size
maxAge: 604800 // 7 days TTL
});
The package includes Next.js integration templates in the templates/nextjs-integration/ folder. Copy these files to your project:
# Copy the Next.js integration files to your project
cp -r node_modules/@shopkit/asset-cache/templates/nextjs-integration/* ./src/lib/asset-cache/
Then use the components:
import { AssetCacheInitializer, AssetCacheImage } from './lib/asset-cache';
// In your app layout
export default function RootLayout({ children }) {
return (
<html>
<body>
<AssetCacheInitializer
storageName="my-app-cache"
serviceWorkerEnabled={true}
debug={process.env.NODE_ENV === 'development'}
maxSize={100}
onInitialized={() => console.log('Asset cache ready!')}
onError={(error) => console.error('Cache init failed:', error)}
/>
{children}
</body>
</html>
);
}
// Or with default settings
export default function SimpleLayout({ children }) {
return (
<html>
<body>
<AssetCacheInitializer />
{children}
</body>
</html>
);
}
// In your components
export function ProductImage({ src, alt }) {
return (
<AssetCacheImage
src={src}
alt={alt}
width={300}
height={300}
cacheOptions={{
ttl: 7 * 24 * 60 * 60, // 7 days
tags: ['product-images'],
priority: 'high'
}}
/>
);
}
import { AssetLoader } from '@shopkit/asset-cache';
// Preload an asset
await AssetLoader.preload('/images/hero.jpg', {
ttl: 3600, // 1 hour
tags: ['hero-images']
});
// Load an asset with caching
const result = await AssetLoader.load('/images/product.jpg');
if (result.success) {
console.log('Loaded from:', result.fromCache ? 'cache' : 'network');
// Use result.data (Blob)
}
// Check if an asset is cached
const isCached = await AssetLoader.isCached('/images/product.jpg');
// Invalidate specific assets
await AssetLoader.invalidate('/images/old-product.jpg');
// Invalidate by tag
await AssetLoader.invalidateByTag('product-images');
The main class for loading and managing cached assets.
class AssetLoader {
static async init(config?: AssetLoaderConfig): Promise<void>
static async preload(url: string, options?: CacheOptions): Promise<void>
static async load<T>(url: string, options?: CacheOptions): Promise<CacheResult<T>>
static async isCached(url: string): Promise<boolean>
static async invalidate(url: string): Promise<void>
static async invalidateByTag(tag: string): Promise<void>
}
Manages cache storage and metadata.
class CacheManager {
static async init(cacheName?: string): Promise<void>
static async addToManifest(url: string, metadata: AssetMetadata): Promise<void>
static async getAssetMetadata(url: string): Promise<AssetMetadata | null>
static async removeFromManifest(url: string): Promise<void>
static async getAssetsByTag(tag: string): Promise<AssetMetadata[]>
}
Handles asset versioning and cache invalidation.
class VersionManager {
static init(deploymentId?: string): void
static createVersionedUrl(url: string): string
static hasVersion(url: string): boolean
static extractVersion(url: string): string | null
}
interface AssetCacheConfig {
enabled?: boolean; // Default: true - Enable/disable asset cache
version?: string; // Default: '1.0.0' - Cache version for invalidation
debug?: boolean; // Default: false - Enable debug logging
storageName?: string; // Default: 'asset-cache-v1' - Cache storage name
maxSize?: number; // Default: 50 - Maximum cache size in MB
maxAge?: number; // Default: 86400 - Maximum age in seconds (24 hours)
serviceWorkerEnabled?: boolean; // Default: true - Enable service worker
serviceWorkerPath?: string; // Default: '/sw.js' - Service worker file path
manifestPath?: string; // Default: '/manifest.json' - Cache manifest file path
}
interface CacheOptions {
ttl?: number; // Time to live in seconds
revalidate?: boolean; // Whether to revalidate on access
tags?: string[]; // Cache tags for invalidation
priority?: 'high' | 'medium' | 'low'; // Priority for preloading
}
// Asset Cache Initializer Component
<AssetCacheInitializer
storageName="my-app-cache" // Custom cache name
serviceWorkerEnabled={true} // Enable service worker
debug={false} // Enable debug logging
version="v1.2.3" // Cache version for invalidation
maxSize={100} // Maximum cache size in MB
maxAge={604800} // Maximum age in seconds (7 days)
onInitialized={() => {}} // Success callback
onError={(error) => {}} // Error callback
/>
// Cached Image Component
<AssetCacheImage
src="/image.jpg"
alt="Description"
width={300}
height={200}
cacheOptions={{
ttl: 3600,
tags: ['images'],
priority: 'high'
}}
/>
// Cached Video Component
<AssetCacheVideo
src="/video.mp4"
width={640}
height={360}
cacheOptions={{
ttl: 7200,
tags: ['videos']
}}
/>
// Image caching hook
const { src, loading, error } = useAssetCacheImage('/image.jpg', {
ttl: 3600,
tags: ['images']
});
// Video caching hook
const { src, loading, error } = useAssetCacheVideo('/video.mp4', {
ttl: 7200,
tags: ['videos']
});
// Asset preloading hook
useAssetCachePreload([
{ url: '/image1.jpg', options: { tags: ['hero'] } },
{ url: '/image2.jpg', options: { tags: ['products'] } }
]);
The package includes three built-in caching strategies:
Serves from cache if available, falls back to network.
import { cacheFirstStrategy } from '@shopkit/asset-cache/strategies';
const response = await cacheFirstStrategy(request, cacheName);
Tries network first, falls back to cache if network fails.
import { networkFirstStrategy } from '@shopkit/asset-cache/strategies';
const response = await networkFirstStrategy(request, cacheName);
Serves from cache immediately, updates cache in background.
import { staleWhileRevalidateStrategy } from '@shopkit/asset-cache/strategies';
const response = await staleWhileRevalidateStrategy(request, cacheName);
The package automatically registers and manages a service worker for enhanced caching capabilities:
import {
registerServiceWorker,
isServiceWorkerActive,
sendMessageToSW
} from '@shopkit/asset-cache/core';
// Register service worker
await registerServiceWorker('/sw.js');
// Check if active
if (isServiceWorkerActive()) {
// Send message to service worker
await sendMessageToSW('CACHE_ASSET', { url: '/image.jpg' });
}
await AssetLoader.invalidate('/specific-image.jpg');
// Invalidate all product images
await AssetLoader.invalidateByTag('product-images');
// Invalidate multiple tags
await AssetLoader.invalidateByTag('hero-images');
await AssetLoader.invalidateByTag('banner-images');
Assets are automatically versioned using content hashes, ensuring cache invalidation when content changes.
Requires support for:
The package includes ready-to-use templates for popular frameworks:
templates/nextjs-integration/)Complete Next.js integration with:
AssetCacheInitializer.tsx - Component for app initializationAssetCachedImage.tsx - Drop-in replacement for Next.js Image (AssetCacheImage component, useAssetCacheImage hook)AssetCachedVideo.tsx - Cached video component (AssetCacheVideo component, useAssetCacheVideo hook)usePreloadAssets.ts - Hook for asset preloading (useAssetCachePreload)initializeAssetCache.ts - Initialization utilitiesnextjsConfig.ts - Next.js specific configurationindex.ts - Main exports filetemplates/vanilla-javascript/)Basic implementation examples:
basicAssetCaching.ts - Simple asset caching implementationREADME.md - Usage instructionsimport { AssetLoader } from '@shopkit/asset-cache';
// Preload product images
const productImages = [
'/products/shoe-1.jpg',
'/products/shoe-2.jpg',
'/products/shoe-3.jpg'
];
await Promise.all(
productImages.map(url =>
AssetLoader.preload(url, {
ttl: 24 * 60 * 60, // 24 hours
tags: ['product-gallery'],
priority: 'high'
})
)
);
// When products are updated, invalidate related caches
await AssetLoader.invalidateByTag('product-images');
await AssetLoader.invalidateByTag('product-thumbnails');
// Preload new content
await AssetLoader.preload('/new-product-image.jpg', {
tags: ['product-images']
});
See CONTRIBUTING.md for development setup and contribution guidelines.
MIT License - see LICENSE file for details.
FAQs
Browser-side asset caching solution with service worker integration, intelligent caching strategies, and Next.js components for optimal performance in e-commerce storefronts
We found that @shopkit/asset-cache demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.