Skip to content

Commit 4f15d68

Browse files
committed
feat: support experimental.async and dynamicCompileOptions when compiling Svelte modules
1 parent 171fbfb commit 4f15d68

File tree

2 files changed

+101
-6
lines changed

2 files changed

+101
-6
lines changed

.changeset/huge-ideas-nail.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': minor
3+
---
4+
5+
feat: add support for the new experimental.async option and apply dynamicCompileOptions when compiling Svelte modules

packages/vite-plugin-svelte/src/plugins/compile-module.js

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { buildModuleIdFilter, buildModuleIdParser } from '../utils/id.js';
22
import * as svelteCompiler from 'svelte/compiler';
3-
import { logCompilerWarnings } from '../utils/log.js';
3+
import { log, logCompilerWarnings } from '../utils/log.js';
44
import { toRollupError } from '../utils/error.js';
55

66
/**
@@ -16,6 +16,12 @@ export function compileModule(api) {
1616
* @type {import("../types/id.js").ModuleIdParser}
1717
*/
1818
let idParser;
19+
20+
/**
21+
* @type {import('svelte/compiler').ModuleCompileOptions}
22+
*/
23+
let staticModuleCompileOptions;
24+
1925
/** @type {import('vite').Plugin} */
2026
const plugin = {
2127
name: 'vite-plugin-svelte:compile-module',
@@ -25,6 +31,7 @@ export function compileModule(api) {
2531
//@ts-expect-error transform defined below but filter not in type
2632
plugin.transform.filter = buildModuleIdFilter(options);
2733
idParser = buildModuleIdParser(options);
34+
staticModuleCompileOptions = filterNonModuleCompilerOptions(options.compilerOptions);
2835
},
2936
transform: {
3037
async handler(code, id) {
@@ -33,12 +40,52 @@ export function compileModule(api) {
3340
if (!moduleRequest) {
3441
return;
3542
}
43+
const filename = moduleRequest.filename;
44+
/** @type {import('svelte/compiler').CompileOptions} */
45+
const compileOptions = {
46+
...staticModuleCompileOptions,
47+
dev: !this.environment.config.isProduction,
48+
generate: ssr ? 'server' : 'client',
49+
filename
50+
};
51+
const dynamicCompileOptions = await options?.dynamicCompileOptions?.({
52+
filename,
53+
code,
54+
compileOptions
55+
});
56+
if (dynamicCompileOptions && log.debug.enabled) {
57+
log.debug(
58+
`dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`,
59+
undefined,
60+
'compileModule'
61+
);
62+
}
63+
const finalCompileOptions = dynamicCompileOptions
64+
? {
65+
...compileOptions,
66+
...dynamicCompileOptions
67+
}
68+
: compileOptions;
69+
// @ts-expect-error experimental not typed yet
70+
if (dynamicCompileOptions.experimental) {
71+
// @ts-expect-error experimental not typed yet
72+
finalCompileOptions.experimental = {
73+
// @ts-expect-error experimental not typed yet
74+
...compileOptions.experimental,
75+
// @ts-expect-error experimental not typed yet
76+
...dynamicCompileOptions.experimental
77+
};
78+
}
79+
const finalModuleCompileOptions = filterNonModuleCompilerOptions(finalCompileOptions);
80+
if (log.debug.enabled) {
81+
log.debug(
82+
`final ModuleCompileOptions for ${filename}: ${JSON.stringify(finalModuleCompileOptions)}`,
83+
undefined,
84+
'compileModule'
85+
);
86+
}
3687
try {
37-
const compileResult = svelteCompiler.compileModule(code, {
38-
dev: !this.environment.config.isProduction,
39-
generate: ssr ? 'server' : 'client',
40-
filename: moduleRequest.filename
41-
});
88+
const compileResult = svelteCompiler.compileModule(code, finalModuleCompileOptions);
4289
logCompilerWarnings(moduleRequest, compileResult.warnings, options);
4390
return compileResult.js;
4491
} catch (e) {
@@ -49,3 +96,46 @@ export function compileModule(api) {
4996
};
5097
return plugin;
5198
}
99+
100+
/**
101+
*
102+
* @param {import('svelte/compiler').CompileOptions} compilerOptions
103+
* @return {import('svelte/compiler').ModuleCompileOptions}
104+
*/
105+
function filterNonModuleCompilerOptions(compilerOptions) {
106+
/** @type {Array<keyof import('svelte/compiler').ModuleCompileOptions>} */
107+
const knownModuleCompileOptionNames = [
108+
'dev',
109+
'generate',
110+
'filename',
111+
'rootDir',
112+
'warningFilter',
113+
// @ts-expect-error will only be defined after svelte aysnc is released
114+
'experimental'
115+
];
116+
// TODO type /** @type {Array<keyof import('svelte/compiler').ModuleCompileOptions['experimental']>} */
117+
const experimentalModuleCompilerOptionNames = ['async'];
118+
119+
/** @type {import('svelte/compiler').ModuleCompileOptions} */
120+
const filtered = filterByPropNames(compilerOptions, knownModuleCompileOptionNames);
121+
// @ts-expect-error experimental not typed yet
122+
if (filtered.experimental) {
123+
// @ts-expect-error experimental not typed yet
124+
filtered.experimental = filterByPropNames(
125+
// @ts-expect-error experimental not typed yet
126+
filtered.experimental,
127+
experimentalModuleCompilerOptionNames
128+
);
129+
}
130+
return filtered;
131+
}
132+
133+
/**
134+
*
135+
* @param {object} o
136+
* @param {string[]} names
137+
* @returns {object}
138+
*/
139+
function filterByPropNames(o, names) {
140+
return Object.fromEntries(Object.entries(o).filter(([name]) => names.includes(name)));
141+
}

0 commit comments

Comments
 (0)