diff --git a/.changeset/all-colts-dig.md b/.changeset/all-colts-dig.md new file mode 100644 index 000000000..8ce9d9b74 --- /dev/null +++ b/.changeset/all-colts-dig.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/vite-plugin-svelte': minor +--- + +feat(rolldown-vite): enable `optimization.inlineConst` by default to ensure treeshaking works with esm-env in svelte diff --git a/packages/vite-plugin-svelte/__tests__/svelte-version.spec.js b/packages/vite-plugin-svelte/__tests__/svelte-version.spec.js index 29a3d094e..a30530b99 100644 --- a/packages/vite-plugin-svelte/__tests__/svelte-version.spec.js +++ b/packages/vite-plugin-svelte/__tests__/svelte-version.spec.js @@ -2,25 +2,54 @@ import { describe, it, expect } from 'vitest'; import { gte } from '../src/utils/svelte-version.js'; describe('gte', () => { + it('returns false for smaller tag', () => { + expect(gte('1.2.3-next.1', '1.2.3-next.2')).toBe(false); + }); + it('returns false for tag vs no tag', () => { + expect(gte('1.2.3-next.0', '1.2.3')).toBe(false); + }); it('returns false for smaller patch', () => { + expect(gte('1.2.2-next.0', '1.2.3')).toBe(false); expect(gte('1.2.2', '1.2.3')).toBe(false); }); it('returns false for smaller minor', () => { + expect(gte('1.1.4-next.0', '1.2.3')).toBe(false); expect(gte('1.1.4', '1.2.3')).toBe(false); + expect(gte('1.1', '1.2.3')).toBe(false); }); it('returns false for smaller major', () => { + expect(gte('0.3.4-next.0', '1.2.3')).toBe(false); expect(gte('0.3.4', '1.2.3')).toBe(false); + expect(gte('0.3', '1.2.3')).toBe(false); + expect(gte('0', '1.2.3')).toBe(false); }); it('returns true for equal', () => { + expect(gte('1.2.3-next.1', '1.2.3-next.1')).toBe(true); + }); + it('returns true for equal without tag', () => { expect(gte('1.2.3', '1.2.3')).toBe(true); + expect(gte('1.2', '1.2.0')).toBe(true); + expect(gte('1.2', '1.2')).toBe(true); + expect(gte('1', '1.0')).toBe(true); + expect(gte('1', '1.0.0')).toBe(true); + }); + it('returns true for larger tag', () => { + expect(gte('1.2.3-next.2', '1.2.3-next.1')).toBe(true); + }); + it('returns true for no tag vs tag', () => { + expect(gte('1.2.3', '1.2.3-next.0')).toBe(true); }); it('returns true for larger patch', () => { expect(gte('1.2.4', '1.2.3')).toBe(true); + expect(gte('1.2.4-next.0', '1.2.3')).toBe(true); }); it('returns true for larger minor', () => { expect(gte('1.3.1', '1.2.3')).toBe(true); + expect(gte('1.3', '1.2.3')).toBe(true); }); it('returns true for larger major', () => { expect(gte('2.0.0', '1.2.3')).toBe(true); + expect(gte('2.0', '1.2.3')).toBe(true); + expect(gte('2', '1.2.3')).toBe(true); }); }); diff --git a/packages/vite-plugin-svelte/src/plugins/configure.js b/packages/vite-plugin-svelte/src/plugins/configure.js index b5538b06a..531f77df6 100644 --- a/packages/vite-plugin-svelte/src/plugins/configure.js +++ b/packages/vite-plugin-svelte/src/plugins/configure.js @@ -12,6 +12,7 @@ import { } from '../utils/options.js'; import { buildIdFilter, buildIdParser } from '../utils/id.js'; import { createCompileSvelte } from '../utils/compile.js'; +import { gte } from '../utils/svelte-version.js'; // @ts-ignore rolldownVersion const { version: viteVersion, rolldownVersion } = vite; @@ -58,7 +59,39 @@ export function configure(api, inlineOptions) { preOptions = await preResolveOptions(inlineOptions, config, configEnv); // extra vite config const extraViteConfig = await buildExtraViteConfig(preOptions, config); + + if ( + rolldownVersion && + configEnv.command === 'build' && + gte(rolldownVersion, '1.0.0-beta.35') // inlineConst received a critical bugfix in 1.0.0-beta.35 + ) { + extraViteConfig.build ??= {}; + // rename rollupOptions to rolldownOptions + //@ts-ignore rolldownOptions only exists in rolldown-vite + extraViteConfig.build.rolldownOptions = extraViteConfig.build.rollupOptions || {}; + delete extraViteConfig.build.rollupOptions; + // read user config inlineConst value + const inlineConst = + //@ts-ignore optimization only exists in rolldown-vite + config.build?.rolldownOptions?.optimization?.inlineConst ?? + //@ts-ignore optimization only exists in rolldown-vite + config.build?.rollupOptions?.optimization?.inlineConst; + + if (inlineConst == null) { + // set inlineConst build optimization for esm-env + //@ts-ignore rolldownOptions only exists in rolldown-vite + extraViteConfig.build.rolldownOptions.optimization ??= {}; + //@ts-ignore rolldownOptions only exists in rolldown-vite + extraViteConfig.build.rolldownOptions.optimization.inlineConst = true; + } else if (inlineConst === false) { + log.warn( + 'Your rolldown config contains `optimization.inlineConst: false`. This can lead to increased bundle size and leaked server code in client build.' + ); + } + } + log.debug('additional vite config', extraViteConfig, 'config'); + return extraViteConfig; } }, diff --git a/packages/vite-plugin-svelte/src/utils/svelte-version.js b/packages/vite-plugin-svelte/src/utils/svelte-version.js index b716a6bdf..d0ca8f2e0 100644 --- a/packages/vite-plugin-svelte/src/utils/svelte-version.js +++ b/packages/vite-plugin-svelte/src/utils/svelte-version.js @@ -6,15 +6,34 @@ import { VERSION } from 'svelte/compiler'; export const isSvelteWithAsync = gte(VERSION, '5.36.0'); /** - * compare semver versions, does not include comparing tags (-next.xy is ignored) + * split semver string and convert to number, ignores non digits in tag + * @param {string} semver + * @return {number[]} [major,minor,patch,tag] + */ +function splitToNumbers(semver) { + const num = semver + .replace(/[^\d.-]/g, '') + .split(/[.-]+/, 4) + .map(Number); + while (num.length < 3) { + num.push(0); + } + if (num.length < 4) { + num.push(Infinity); + } + return num; +} + +/** + * compare semver versions, tags are compared by their numeric part only * * @param {string} a semver version * @param {string} b semver version * @return {boolean} true if a is greater or equal to b */ export function gte(a, b) { - const aNum = a.split(/[.-]/, 3).map(Number); - const bNum = b.split(/[.-]/, 3).map(Number); + const aNum = splitToNumbers(a); + const bNum = splitToNumbers(b); for (let i = 0; i < aNum.length; i++) { if (aNum[i] < bNum[i]) { return false;