From 536717d6c01bd7980ee4af5d6082605fde14b3f0 Mon Sep 17 00:00:00 2001 From: dominikg Date: Mon, 16 Jun 2025 15:40:33 +0200 Subject: [PATCH 1/3] refactor(load-config): remove support for cjs and add support for ts --- .changeset/nasty-ghosts-warn.md | 5 ++ .changeset/tall-rivers-sleep.md | 5 ++ .../__tests__/configfile-custom.spec.ts | 9 ++- .../e2e-tests/configfile-custom/package.json | 4 +- .../svelte.config.custom.cjs | 6 -- .../configfile-custom/svelte.config.custom.ts | 8 ++ .../{svelte.config.cjs => svelte.config.js} | 2 +- .../src/utils/load-svelte-config.js | 78 +++++-------------- .../vite-plugin-svelte/types/index.d.ts.map | 2 +- 9 files changed, 46 insertions(+), 73 deletions(-) create mode 100644 .changeset/nasty-ghosts-warn.md create mode 100644 .changeset/tall-rivers-sleep.md delete mode 100644 packages/e2e-tests/configfile-custom/svelte.config.custom.cjs create mode 100644 packages/e2e-tests/configfile-custom/svelte.config.custom.ts rename packages/e2e-tests/configfile-custom/{svelte.config.cjs => svelte.config.js} (68%) diff --git a/.changeset/nasty-ghosts-warn.md b/.changeset/nasty-ghosts-warn.md new file mode 100644 index 000000000..e671971be --- /dev/null +++ b/.changeset/nasty-ghosts-warn.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/vite-plugin-svelte': major +--- + +remove support for loading commonjs svelte config files diff --git a/.changeset/tall-rivers-sleep.md b/.changeset/tall-rivers-sleep.md new file mode 100644 index 000000000..9efcebcea --- /dev/null +++ b/.changeset/tall-rivers-sleep.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/vite-plugin-svelte': minor +--- + +add support for loading typescript svelte config files in runtimes that support it diff --git a/packages/e2e-tests/configfile-custom/__tests__/configfile-custom.spec.ts b/packages/e2e-tests/configfile-custom/__tests__/configfile-custom.spec.ts index ce2f7e2de..172303b26 100644 --- a/packages/e2e-tests/configfile-custom/__tests__/configfile-custom.spec.ts +++ b/packages/e2e-tests/configfile-custom/__tests__/configfile-custom.spec.ts @@ -1,5 +1,8 @@ import { it, expect } from 'vitest'; import { editViteConfig, isBuild, page, e2eServer } from '~utils'; +import { versions } from 'node:process'; + +const isNodeWithoutTypeStripping = Number(versions.node?.split('.', 1)[0]) < 22; it('should load default config and work', async () => { expect(e2eServer.logs.server.out).toContain('default svelte config loaded'); @@ -11,11 +14,11 @@ it('should load default config and work', async () => { if (!isBuild) { // editing vite config does not work in build tests, build only runs once // TODO split into different tests - it('should load custom cjs config and work', async () => { + it.skipIf(isNodeWithoutTypeStripping)('should load custom ts config and work', async () => { await editViteConfig((c) => - c.replace(/svelte\([^)]*\)/, "svelte({configFile:'svelte.config.custom.cjs'})") + c.replace(/svelte\([^)]*\)/, "svelte({configFile:'svelte.config.custom.ts'})") ); - expect(e2eServer.logs.server.out).toContain('custom svelte config loaded cjs'); + expect(e2eServer.logs.server.out).toContain('custom svelte config loaded ts'); expect(await page.textContent('h1')).toMatch('Hello world!'); expect(await page.textContent('#test-child')).toBe('test-child'); expect(await page.textContent('#dependency-import')).toBe('dependency-import'); diff --git a/packages/e2e-tests/configfile-custom/package.json b/packages/e2e-tests/configfile-custom/package.json index 056ecc3c2..b782a5e0d 100644 --- a/packages/e2e-tests/configfile-custom/package.json +++ b/packages/e2e-tests/configfile-custom/package.json @@ -3,8 +3,8 @@ "private": true, "version": "1.0.0", "scripts": { - "dev": "vite", - "build": "vite build", + "dev": "cross-env NODE_OPTIONS=\"--experimental-strip-types\" vite", + "build": "cross-env NODE_OPTIONS=\"--experimental-strip-types\" vite build", "preview": "vite preview" }, "dependencies": { diff --git a/packages/e2e-tests/configfile-custom/svelte.config.custom.cjs b/packages/e2e-tests/configfile-custom/svelte.config.custom.cjs deleted file mode 100644 index c4ec2aa1d..000000000 --- a/packages/e2e-tests/configfile-custom/svelte.config.custom.cjs +++ /dev/null @@ -1,6 +0,0 @@ -console.log('custom svelte config loaded cjs'); -module.exports = { - vitePlugin: { - emitCss: false - } -}; diff --git a/packages/e2e-tests/configfile-custom/svelte.config.custom.ts b/packages/e2e-tests/configfile-custom/svelte.config.custom.ts new file mode 100644 index 000000000..a2c5bee5c --- /dev/null +++ b/packages/e2e-tests/configfile-custom/svelte.config.custom.ts @@ -0,0 +1,8 @@ +console.log('custom svelte config loaded ts'); +import type { SvelteConfig } from '@sveltejs/vite-plugin-svelte'; +const config: SvelteConfig = { + vitePlugin: { + emitCss: false + } +}; +export default config; diff --git a/packages/e2e-tests/configfile-custom/svelte.config.cjs b/packages/e2e-tests/configfile-custom/svelte.config.js similarity index 68% rename from packages/e2e-tests/configfile-custom/svelte.config.cjs rename to packages/e2e-tests/configfile-custom/svelte.config.js index 237608e9e..e92845e0b 100644 --- a/packages/e2e-tests/configfile-custom/svelte.config.cjs +++ b/packages/e2e-tests/configfile-custom/svelte.config.js @@ -1,2 +1,2 @@ console.log('default svelte config loaded'); -module.exports = {}; +export default {}; diff --git a/packages/vite-plugin-svelte/src/utils/load-svelte-config.js b/packages/vite-plugin-svelte/src/utils/load-svelte-config.js index 1b32ba4fd..2cf2b8e78 100644 --- a/packages/vite-plugin-svelte/src/utils/load-svelte-config.js +++ b/packages/vite-plugin-svelte/src/utils/load-svelte-config.js @@ -1,21 +1,12 @@ -import { createRequire } from 'node:module'; import path from 'node:path'; import process from 'node:process'; import fs from 'node:fs'; import { pathToFileURL } from 'node:url'; import { log } from './log.js'; -// used to require cjs config in esm. -// NOTE dynamic import() cjs technically works, but timestamp query cache bust -// have no effect, likely because it has another internal cache? -/** @type {NodeRequire}*/ -let esmRequire; - -export const knownSvelteConfigNames = [ - 'svelte.config.js', - 'svelte.config.cjs', - 'svelte.config.mjs' -]; +export const knownSvelteConfigNames = ['js', 'ts', 'mjs', 'mts'].map( + (ext) => `svelte.config.${ext}` +); /** * @param {string} filePath @@ -36,56 +27,23 @@ export async function loadSvelteConfig(viteConfig, inlineOptions) { } const configFile = findConfigToLoad(viteConfig, inlineOptions); if (configFile) { - let err; - // try to use dynamic import for svelte.config.js first - if (configFile.endsWith('.js') || configFile.endsWith('.mjs')) { - try { - const result = await dynamicImportDefault( - pathToFileURL(configFile).href, - fs.statSync(configFile).mtimeMs - ); - if (result != null) { - return { - ...result, - configFile - }; - } else { - throw new Error(`invalid export in ${configFile}`); - } - } catch (e) { - log.error(`failed to import config ${configFile}`, e); - err = e; - } - } - // cjs or error with dynamic import - if (!configFile.endsWith('.mjs')) { - try { - // identify which require function to use (esm and cjs mode) - const _require = import.meta.url - ? (esmRequire ?? (esmRequire = createRequire(import.meta.url))) - : // eslint-disable-next-line no-undef - require; - - // avoid loading cached version on reload - delete _require.cache[_require.resolve(configFile)]; - const result = _require(configFile); - if (result != null) { - return { - ...result, - configFile - }; - } else { - throw new Error(`invalid export in ${configFile}`); - } - } catch (e) { - log.error(`failed to require config ${configFile}`, e); - if (!err) { - err = e; - } + try { + const result = await dynamicImportDefault( + pathToFileURL(configFile).href, + fs.statSync(configFile).mtimeMs + ); + if (result != null) { + return { + ...result, + configFile + }; + } else { + throw new Error(`invalid export in ${configFile}`); } + } catch (e) { + log.error(`failed to import config ${configFile}`, e); + throw e; } - // failed to load existing config file - throw err; } } diff --git a/packages/vite-plugin-svelte/types/index.d.ts.map b/packages/vite-plugin-svelte/types/index.d.ts.map index 5d5287027..151f15172 100644 --- a/packages/vite-plugin-svelte/types/index.d.ts.map +++ b/packages/vite-plugin-svelte/types/index.d.ts.map @@ -26,6 +26,6 @@ null, null ], - "mappings": ";;;;aAIYA,OAAOA;;WAETC,mBAAmBA;;;;;;;;;;;kBAWZC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAgGbC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAiDnBC,mBAAmBA;;;;;;;;;;;;;;;;WAgBnBC,oBAAoBA;;;;;;;;;;;;;;;MAezBC,SAASA;;kBAEGC,qBAAqBA;;;;;;;;;;;;;iBC/JtBC,MAAMA;iBCXNC,cAAcA;iBCORC,gBAAgBA", + "mappings": ";;;;aAIYA,OAAOA;;WAETC,mBAAmBA;;;;;;;;;;;kBAWZC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAgGbC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAiDnBC,mBAAmBA;;;;;;;;;;;;;;;;WAgBnBC,oBAAoBA;;;;;;;;;;;;;;;MAezBC,SAASA;;kBAEGC,qBAAqBA;;;;;;;;;;;;;iBC/JtBC,MAAMA;iBCXNC,cAAcA;iBCFRC,gBAAgBA", "ignoreList": [] } \ No newline at end of file From 9c47353c1599d1d6b6caf76ce1aa4d06a0976f1a Mon Sep 17 00:00:00 2001 From: dominikg Date: Mon, 16 Jun 2025 16:08:51 +0200 Subject: [PATCH 2/3] fix: replace svelte.config.cjs in tests --- packages/e2e-tests/hmr/__tests__/hmr.spec.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/e2e-tests/hmr/__tests__/hmr.spec.ts b/packages/e2e-tests/hmr/__tests__/hmr.spec.ts index a7c13152a..9bf83a375 100644 --- a/packages/e2e-tests/hmr/__tests__/hmr.spec.ts +++ b/packages/e2e-tests/hmr/__tests__/hmr.spec.ts @@ -164,10 +164,10 @@ if (!isBuild) { }); test('should work with emitCss: false in svelte config', async () => { - addFile('svelte.config.cjs', 'module.exports={vitePlugin:{emitCss:false}}'); + addFile('svelte.config.js', 'export default {vitePlugin:{emitCss:false}}'); await waitForServerRestartAndPageReload(); expect(await getColor('#hmr-test-1 .label')).toBe('red'); - removeFile('svelte.config.cjs'); + removeFile('svelte.config.js'); }); test('should detect changes in svelte config and restart', async () => { @@ -182,8 +182,8 @@ if (!isBuild) { } }; await addFile( - 'svelte.config.cjs', - `module.exports = { + 'svelte.config.js', + `export default { preprocess:[{markup:${injectPreprocessor.toString()}}]};` ); await waitForServerRestartAndPageReload(); @@ -196,7 +196,7 @@ if (!isBuild) { await updateHmrTest((content) => content.replace('color: red', 'color: green')); expect(await getColor('#hmr-test-1 .label')).toBe('green'); expect(await getText('#hmr-test-1 .counter')).toBe('1'); - await editFile('svelte.config.cjs', (content) => + await editFile('svelte.config.js', (content) => content .replace('preprocess-inject', 'preprocess-inject-2') .replace('Injected', 'Injected 2') @@ -212,7 +212,7 @@ if (!isBuild) { await updateHmrTest((content) => content.replace('color: green', 'color: red')); expect(await getColor('#hmr-test-1 .label')).toBe('red'); expect(await getText('#hmr-test-1 .counter')).toBe('1'); - await removeFile('svelte.config.cjs'); + await removeFile('svelte.config.js'); await waitForServerRestartAndPageReload(); expect(await getEl('#preprocess-inject-2')).toBe(null); expect(await getEl('#preprocess-inject')).toBe(null); From b913534bc4249707e995e2844a35d564f6f0fe85 Mon Sep 17 00:00:00 2001 From: dominikg Date: Mon, 16 Jun 2025 16:47:36 +0200 Subject: [PATCH 3/3] fix: remove --experimental-strip-types flag when testing with node20 --- packages/e2e-tests/vitestSetup.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/e2e-tests/vitestSetup.ts b/packages/e2e-tests/vitestSetup.ts index fe6115786..16efa5c94 100644 --- a/packages/e2e-tests/vitestSetup.ts +++ b/packages/e2e-tests/vitestSetup.ts @@ -145,6 +145,17 @@ beforeAll( if (fs.existsSync(logsDir)) { fs.rmSync(logsDir, { recursive: true, force: true }); } + // remove strip types flag for node < 22, it doesn't work there + // TODO: remove once node20 is no longer part of CI + if (Number(process.versions.node?.split('.', 1)[0]) < 22) { + const pkgFile = path.join(tempDir, 'package.json'); + const pkgContent = fs.readFileSync(pkgFile, 'utf-8'); + const newContent = pkgContent.replaceAll( + 'cross-env NODE_OPTIONS=\\"--experimental-strip-types\\" ', + '' + ); + fs.writeFileSync(pkgFile, newContent, 'utf-8'); + } await fs.mkdir(logsDir); const customServerScript = path.resolve(path.dirname(testPath), 'serve.js'); const defaultServerScript = path.resolve(e2eTestsRoot, 'e2e-server.js');