Hi! I'm running into an issue with island caching behavior that seems different of the expected behavior.
From my understanding, Fresh should cache island JS bundles aggressively (immutable, long max-age) when served from paths like:
/_fresh/js/{BUILD_ID}/chunk-XXXX.js
However, that's not what I'm observing in my app.
What I'm seeing:
- Every page refresh triggers new HTTP requests for all islands
- The number of server requests remains the same between first and subsequent visits
- Each island request includes:
Cache-Control: no-cache
- A new X-Deno-Trace-Id on every refresh
-
- This suggests that nothing is being served from browser cache
In traces, each island appears as a separate request on every reload.

Expected behavior:
- First visit → island chunks fetched and cached
- Subsequent visits → served from browser cache (no network requests)
- After deploy → only changed chunks fetched
Environment:
@fresh/plugin-vite@1.0.8
vite@7.2.7
Using Vite builder (not legacy)
Important detail:
From discussion, it was mentioned that Fresh only applies caching to assets served from:
/_fresh/js/{BUILD_ID}/...
or assets suffixed with:
?__frsh_c=BUILD_ID
In my case, the island assets seem to be served from a different path, assets/fresh-island..., which might explain why caching headers are not applied.
Below there is my vite.config.ts
vite.config.ts
import { defineConfig } from 'vite';
import { fresh } from '@fresh/plugin-vite';
import tailwindcss from '@tailwindcss/vite';
import { initializeRoutes } from '@utils/router.ts';
export default defineConfig({
plugins: [
fresh({
islandSpecifiers: ['@ui/components-loader', '@hooks', '@stores', '@lib/islands/global-config.tsx'],
}),
tailwindcss(),
// Plugin to stub out all core-js imports
{
name: 'initialize-routes',
enforce: 'pre',
buildStart() {
initializeRoutes('painel');
},
},
{
name: 'stub-core-js',
enforce: 'pre',
resolveId(id) {
// Only stub actual core-js module imports, not anything that includes 'core' in the name
if (id.startsWith('core-js/modules/') || id === 'core-js' || id.startsWith('core-js/internals/')) {
return '\0virtual:empty-module';
}
},
load(id) {
if (id === '\0virtual:empty-module') {
return 'export default {};';
}
},
},
],
resolve: {
alias: {
// Rollup (via @fresh/plugin-vite) doesn't apply CJS default interop for these helpers.
// canvg imports the CJS helpers with `import x from ...`, so point to the ESM variants.
'@babel/runtime/helpers/defineProperty': '@babel/runtime/helpers/esm/defineProperty',
'@babel/runtime/helpers/asyncToGenerator': '@babel/runtime/helpers/esm/asyncToGenerator',
// Replace ALL @babel/runtime-corejs3 imports with @babel/runtime (no core-js)
'@babel/runtime-corejs3/helpers/defineProperty': '@babel/runtime/helpers/esm/defineProperty',
'@babel/runtime-corejs3/helpers/asyncToGenerator': '@babel/runtime/helpers/esm/asyncToGenerator',
'@babel/runtime-corejs3/helpers/esm/defineProperty': '@babel/runtime/helpers/esm/defineProperty',
'@babel/runtime-corejs3/helpers/esm/asyncToGenerator': '@babel/runtime/helpers/esm/asyncToGenerator',
// Redirect any core-js module imports to empty module
'core-js/modules/es.regexp.to-string.js': 'data:text/javascript,export default {}',
'core-js/modules/es.array.iterator.js': 'data:text/javascript,export default {}',
'core-js/modules/es.object.to-string.js': 'data:text/javascript,export default {}',
'core-js/modules/es.promise.js': 'data:text/javascript,export default {}',
'core-js/modules/es.string.iterator.js': 'data:text/javascript,export default {}',
'node:module': 'node:module',
},
},
optimizeDeps: {
esbuildOptions: {
treeShaking: true,
},
},
ssr: {
external: [
'jspdf',
'quill',
'quill-magic-url',
'dompurify',
'html2canvas',
'canvg',
'@babel/runtime-corejs3',
],
},
server: {
port: 8000,
},
});
</details> ```
Hi! I'm running into an issue with island caching behavior that seems different of the expected behavior.
From my understanding, Fresh should cache island JS bundles aggressively (immutable, long max-age) when served from paths like:
However, that's not what I'm observing in my app.
What I'm seeing:
Cache-Control: no-cacheIn traces, each island appears as a separate request on every reload.

Expected behavior:
Environment:
@fresh/plugin-vite@1.0.8
vite@7.2.7
Using Vite builder (not legacy)
Important detail:
From discussion, it was mentioned that Fresh only applies caching to assets served from:
/_fresh/js/{BUILD_ID}/...
or assets suffixed with:
?__frsh_c=BUILD_ID
In my case, the island assets seem to be served from a different path,
assets/fresh-island..., which might explain why caching headers are not applied.Below there is my
vite.config.tsvite.config.ts