Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: replace version in generateBundle #12700

Merged
merged 11 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading