remotefunctioncache
v0.1.0
Published
A powerful caching library for SvelteKit's remote functions that provides intelligent client-side caching with multiple storage backends, automatic expiration, and cross-tab synchronization.
Readme
Remote Function Cache
A powerful caching library for SvelteKit's remote functions that provides intelligent client-side caching with multiple storage backends, automatic expiration, and cross-tab synchronization.
Features
- 🚀 Intelligent Caching: Automatically caches remote function results
- 💾 Multiple Storage Options: localStorage, sessionStorage, IndexedDB, and memory support
- ⏰ Automatic Expiration: Configurable timeout with automatic cleanup
- 🔄 Cross-tab Synchronization: Share cache updates across browser tabs
- 📱 Reactive Arguments: Automatically handles reactive argument changes
- 🎯 Loading States: Built-in loading, error, and refreshing states
- 🔧 Manual Control: Programmatic cache management and refresh capabilities
- 📊 Type Safe: Full TypeScript support with proper type inference
- 🔄 Auto-Sync: Automatically syncs with SvelteKit invalidations and mutations
- 🐛 Debug Mode: Optional debug logging for development and troubleshooting
Installation
npm install remotefunctioncachePrerequisites
This library requires SvelteKit with remote functions enabled. Add the following to your svelte.config.js:
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
experimental: {
remoteFunctions: true
}
},
compilerOptions: {
experimental: {
async: true
}
}
};
export default config;Quick Start
<script>
import { remoteFunctionCache } from 'remotefunctioncache';
import { getUsers } from './data.remote.js';
// Create a cached version of your remote function
const usersCache = remoteFunctionCache(getUsers, () => undefined, {
key: 'users-list',
storage: 'local',
timeoutMinutes: 10,
syncTabs: true,
autoSync: true // Enable automatic sync with SvelteKit
});
</script>
{#if usersCache.loading}
<p>Loading users...</p>
{:else if usersCache.error}
<p>Error: {usersCache.error.message}</p>
{:else if usersCache.value?.current}
<ul>
{#each usersCache.value.current as user}
<li>{user.name}</li>
{/each}
</ul>
{/if}
<button onclick={() => usersCache.refresh()}> Refresh Data </button>API Reference
remoteFunctionCache(fn, argFn, options)
Creates a cached version of a remote function.
Parameters
fn: The remote function to cacheargFn: A function that returns the argument(s) for the remote functionoptions: Configuration object
Options
{
key?: string; // Cache key (defaults to function name)
storage?: 'local' | 'session' | 'indexeddb' | 'memory'; // Storage type
syncTabs?: boolean; // Enable cross-tab synchronization
timeoutMinutes?: number | null; // Cache expiration (null = no expiry)
initialValue?: TReturn; // Initial value before first load
autoSync?: boolean; // Enable automatic sync with SvelteKit invalidations (default: true)
debug?: boolean; // Enable debug logging (default: false)
}Returns
{
loading: boolean; // True during initial load
refreshing: boolean; // True during refresh operations
error: any; // Last error that occurred
value: CustomPersistedState<TReturn>; // Cached value container
updateTime: Date; // Last update timestamp
autoSync: boolean; // Current auto-sync setting
refresh: () => void; // Force refresh from server
setValue: (val: TReturn) => void; // Set cache value manually
destroy: () => void; // Clean up the cache instance
}Usage Examples
Basic Caching
<script>
import { remoteFunctionCache } from 'remotefunctioncache';
import { getPosts } from './data.remote.js';
const postsCache = remoteFunctionCache(getPosts, () => undefined, {
key: 'blog-posts',
timeoutMinutes: 30
});
</script>With Arguments
<script>
import { remoteFunctionCache } from 'remotefunctioncache';
import { getPost } from './data.remote.js';
let postId = $state(1);
const postCache = remoteFunctionCache(getPost, () => postId, {
key: 'single-post',
timeoutMinutes: 15
});
</script>
<select bind:value={postId}>
<option value={1}>Post 1</option>
<option value={2}>Post 2</option>
<option value={3}>Post 3</option>
</select>
{#if postCache.value?.current}
<h1>{postCache.value.current.title}</h1>
<p>{postCache.value.current.content}</p>
{/if}Cross-tab Synchronization
<script>
const sharedCache = remoteFunctionCache(getData, () => undefined, {
key: 'shared-data',
storage: 'local',
syncTabs: true,
timeoutMinutes: 60,
autoSync: true
});
</script>IndexedDB for Large Data
<script>
const largeDataCache = remoteFunctionCache(getBigDataset, () => undefined, {
key: 'large-dataset',
storage: 'indexeddb',
syncTabs: true,
timeoutMinutes: null, // Never expires
autoSync: true
});
</script>Memory for Testing and Temporary Data
<script>
const tempCache = remoteFunctionCache(getTestData, () => undefined, {
key: 'temporary-data',
storage: 'memory',
syncTabs: false, // Memory storage doesn't support cross-tab sync
timeoutMinutes: null, // No expiry (lost on page reload anyway)
autoSync: true
});
</script>Manual Cache Management
<script>
// Set custom data
const setCustomData = () => {
usersCache.setValue([{ id: 1, name: 'Custom User' }]);
};
// Force refresh
const forceRefresh = () => {
usersCache.refresh();
};
// Clean up when component is destroyed
const cleanup = () => {
usersCache.destroy();
};
</script>Storage Types
localStorage
- ✅ Persistent across browser sessions
- ✅ Cross-tab synchronization support
- ⚠️ ~5-10MB storage limit
- ⚠️ Synchronous API (may block UI)
- ⚠️ String-only storage (JSON serialization)
sessionStorage
- ⚠️ Cleared when tab/browser closes
- ❌ No cross-tab synchronization (automatically upgrades to localStorage if syncTabs is enabled)
- ⚠️ ~5-10MB storage limit
- ⚠️ Synchronous API (may block UI)
- ⚠️ String-only storage (JSON serialization)
IndexedDB
- ✅ Persistent across browser sessions
- ✅ Cross-tab sync via BroadcastChannel
- ✅ Large storage capacity (~GB)
- ✅ Asynchronous API (non-blocking)
- ✅ Rich data type support
Memory
- ⚠️ Lost on page reload
- ❌ No cross-tab synchronization
- ✅ No storage limit (RAM-based)
- ✅ Fastest access (synchronous)
- ✅ Rich data types (native JavaScript objects)
- 🔧 Ideal for testing and temporary data
Performance Benefits
The cache provides significant performance improvements:
- Network Request: ~500ms average
- Cache Hit: ~0.1ms average
- Improvement: 99.98% faster for cached data
Load testing shows exponential performance gains with concurrent requests:
| Concurrent Requests | Uncached | Cached | Improvement | | ------------------- | -------- | ------ | ----------- | | 10 | 2.1s | 0.3s | 85% faster | | 50 | 8.5s | 0.8s | 90% faster | | 100 | 15.2s | 1.2s | 92% faster |
Development
To run the demo and develop the library:
# Install dependencies
npm install
# Start development server
npm run dev
# Build the library
npm run build
# Run tests
npm test
# Package for distribution
npm packDemo Pages
The library includes comprehensive demo pages:
- Basic Usage (
/): Core functionality and basic examples - Advanced Features (
/advanced): Cross-tab sync, multiple instances, search - Storage Comparison (
/storage-comparison): Compare all storage backends (localStorage, sessionStorage, IndexedDB, Memory) - Performance Analysis (
/performance): Load testing and performance metrics
Browser Support
- localStorage/sessionStorage: All modern browsers
- IndexedDB: All modern browsers (IE 10+)
- BroadcastChannel: Chrome 54+, Firefox 38+, Safari 15.4+
For cross-tab synchronization with IndexedDB, a BroadcastChannel polyfill may be needed for older browsers.
TypeScript Support
Full TypeScript support is included with proper type inference:
import type { RemoteQueryFunction } from '@sveltejs/kit';
const typedCache = remoteFunctionCache<void, User[]>(getUsers, () => undefined, {
key: 'typed-users'
});
// usersCache.value?.current is properly typed as User[] | undefinedContributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License
MIT License - see LICENSE file for details.
