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.
Install with your preferred package manager:
# npm
npm install remotefunctioncache
# pnpm
pnpm add remotefunctioncache
# yarn
yarn add remotefunctioncache
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;
<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>
remoteFunctionCache(fn, argFn, options)
Creates a cached version of a remote function.
fn
: The remote function to cacheargFn
: A function that returns the argument(s) for the remote functionoptions
: Configuration object{
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)
}
{
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
}
<script>
import { remoteFunctionCache } from 'remotefunctioncache';
import { getPosts } from './data.remote.js';
const postsCache = remoteFunctionCache(getPosts, () => undefined, {
key: 'blog-posts',
timeoutMinutes: 30
});
</script>
<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}
<script>
const sharedCache = remoteFunctionCache(getData, () => undefined, {
key: 'shared-data',
storage: 'local',
syncTabs: true,
timeoutMinutes: 60,
autoSync: true
});
</script>
<script>
const largeDataCache = remoteFunctionCache(getBigDataset, () => undefined, {
key: 'large-dataset',
storage: 'indexeddb',
syncTabs: true,
timeoutMinutes: null, // Never expires
autoSync: true
});
</script>
<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>
<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>
To run the demo and develop the library:
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Build the library
pnpm build
# Run tests
pnpm test
# Package for distribution
pnpm pack
The library includes comprehensive demo pages:
/
): Core functionality and basic examples/advanced
): Cross-tab sync, multiple instances, search/storage-comparison
): Compare all storage backends (localStorage, sessionStorage, IndexedDB, Memory)/performance
): Load testing and performance metricsFor cross-tab synchronization with IndexedDB, a BroadcastChannel polyfill may be needed for older browsers.
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[] | undefined
MIT License - see LICENSE file for details.