Skip to content

Commit

Permalink
fix: replace version in generateBundle (#12700)
Browse files Browse the repository at this point in the history
In #8957 one of the desired outcomes was that the framework code would have its own chunk with a stable hash for better caching, but that didn't really happen because the client imports something that references version, through __sveltekit/environment for created_updated_store and version hash through __sveltekit/path, which meant that when the developer changes their app code and increments/changes the version it'd also change the above mentioned modules and subsequently most chunks with the framework code

In this PR the version is injected in generateBundle once the chunk hashes have already been calculated so that just changing the version doesn't affect the hashes for chunks without any actual code changes

fixes #12260
  • Loading branch information
gtm-nayan authored Oct 7, 2024
1 parent 7fb1f5c commit 3591411
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/moody-zoos-compare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

fix: ensure a changing `version` doesn't affect the hashes for chunks without any actual code changes
12 changes: 12 additions & 0 deletions packages/kit/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,15 @@ export const GENERATED_COMMENT = '// this file is generated — do not edit it\n
export const ENDPOINT_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];

export const PAGE_METHODS = ['GET', 'POST', 'HEAD'];

/**
* Placeholders for the hash of the app version.
* Later replaced in the generateBundle hook to avoid affecting the chunk hash.
*/
export const APP_VERSION_HASH_PLACEHOLDER_BASE = '__SVELTEKIT_APP_VERSION_HASH__';

/**
* Placeholder for the app version.
* Later replaced in the generateBundle hook to avoid affecting the chunk hash.
*/
export const APP_VERSION_PLACEHOLDER_BASE = '__SVELTEKIT_APP_VERSION__';
66 changes: 60 additions & 6 deletions packages/kit/src/exports/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ import {
sveltekit_server
} from './module_ids.js';
import { resolve_peer_dependency } from '../../utils/import.js';
import {
APP_VERSION_PLACEHOLDER_BASE,
APP_VERSION_HASH_PLACEHOLDER_BASE
} from '../../constants.js';

const cwd = process.cwd();

Expand Down Expand Up @@ -184,7 +188,16 @@ async function kit({ svelte_config }) {
const { kit } = svelte_config;
const out = `${kit.outDir}/output`;

const version_hash = hash(kit.version.name);
const app_version = kit.version.name;
const version_hash = hash(app_version);

// if the app version or hash is longer than the placeholder, we need to pad it to avoid
// source map damage
const app_version_placeholder = APP_VERSION_PLACEHOLDER_BASE.padEnd(app_version.length, '_');
const app_version_hash_placeholder = APP_VERSION_HASH_PLACEHOLDER_BASE.padEnd(
version_hash.length,
'_'
);

/** @type {import('vite').ResolvedConfig} */
let vite_config;
Expand Down Expand Up @@ -384,7 +397,7 @@ async function kit({ svelte_config }) {
const browser = !options?.ssr;

const global = is_build
? `globalThis.__sveltekit_${version_hash}`
? `globalThis.__sveltekit_${browser ? app_version_hash_placeholder : version_hash}`
: 'globalThis.__sveltekit_dev';

if (options?.ssr === false && process.env.TEST !== 'true') {
Expand Down Expand Up @@ -470,10 +483,8 @@ async function kit({ svelte_config }) {
}

case sveltekit_environment: {
const { version } = svelte_config.kit;

return dedent`
export const version = ${s(version.name)};
export const version = ${is_build && browser ? app_version_placeholder : s(kit.version.name)};
export let building = false;
export let prerendering = false;
Expand Down Expand Up @@ -923,7 +934,50 @@ async function kit({ svelte_config }) {
}
};

return [plugin_setup, plugin_virtual_modules, plugin_guard, plugin_compile];
/** @type {import('vite').Plugin} */
const plugin_replace_version_and_hash = {
name: 'vite-plugin-svelte-replace-version-and-hash',
enforce: 'post',

generateBundle(_, bundle, __) {
if (vite_config.build.ssr) return;

for (const file in bundle) {
if (bundle[file].type !== 'chunk') continue;
const chunk = /** @type {import('rollup').OutputChunk} */ (bundle[file]);
let code = chunk.code;
if (
!(code.includes(app_version_placeholder) || code.includes(app_version_hash_placeholder))
)
continue;

// replace the version and version after the chunk hash has already been calculated
// to avoid affecting the chunk hash
const substitutions = [
[app_version_hash_placeholder, version_hash],
[app_version_placeholder, JSON.stringify(kit.version.name)]
];

for (const [placeholder, replacement] of substitutions) {
code = code.replaceAll(
placeholder,
// pad the replacement to mitigate source map changes
replacement.padEnd(placeholder.length, ' ')
);
}

chunk.code = code;
}
}
};

return [
plugin_setup,
plugin_virtual_modules,
plugin_guard,
plugin_compile,
plugin_replace_version_and_hash
];
}

/**
Expand Down

0 comments on commit 3591411

Please sign in to comment.