Skip to content

Commit f12e3f0

Browse files
dominikgtrueadmConduitry
authored
feat(svelte5): enable hmr (#836)
* feat(svelte5): enable hmr * Update package.json Co-authored-by: Conduitry <[email protected]> * typo * previous was right * add version check * add guard to other site * bump version * link to version 96 --------- Co-authored-by: Dominic Gannaway <[email protected]> Co-authored-by: Dominic Gannaway <[email protected]> Co-authored-by: Conduitry <[email protected]>
1 parent 69ac505 commit f12e3f0

File tree

6 files changed

+73
-49
lines changed

6 files changed

+73
-49
lines changed

.changeset/shiny-drinks-dress.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': minor
3+
---
4+
5+
feat(svelte5): enable hmr option in dev

packages/vite-plugin-svelte/src/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ export function svelte(inlineOptions) {
178178
},
179179

180180
handleHotUpdate(ctx) {
181-
if (!options.hot || !options.emitCss) {
181+
// @ts-expect-error svelte4 does not have hmr option
182+
if ((!options.hot && !options.compilerOptions.hmr) || !options.emitCss) {
182183
return;
183184
}
184185
const svelteRequest = requestParser(ctx.file, false, ctx.timestamp);

packages/vite-plugin-svelte/src/utils/compile.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ export const _createCompileSvelte = (makeHot) => {
203203
* @returns {Function | undefined}
204204
*/
205205
function buildMakeHot(options) {
206-
const needsMakeHot = options.hot !== false && options.isServe && !options.isProduction;
206+
const needsMakeHot =
207+
!isSvelte5 && options.hot !== false && options.isServe && !options.isProduction;
207208
if (needsMakeHot) {
208209
// @ts-ignore
209210
const hotApi = options?.hot?.hotApi;

packages/vite-plugin-svelte/src/utils/log.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,6 @@ export function isDebugNamespaceEnabled(namespace) {
263263

264264
export function logSvelte5Warning() {
265265
const notice = `You are using Svelte ${VERSION}. Svelte 5 support is experimental, breaking changes can occur in any release until this notice is removed.`;
266-
const wip = [
267-
'svelte-inspector is disabled until dev mode implements node to code mapping',
268-
'hmr for .svelte files is disabled until hmr api is implemented'
269-
];
266+
const wip = ['svelte-inspector is disabled until dev mode implements node to code mapping'];
270267
log.warn(`${notice}\nwork in progress:\n - ${wip.join('\n - ')}\n`);
271268
}

packages/vite-plugin-svelte/src/utils/options.js

+57-43
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
import { isCommonDepWithoutSvelteField } from './dependencies.js';
2727
import { VitePluginSvelteStats } from './vite-plugin-svelte-stats.js';
2828
import { VitePluginSvelteCache } from './vite-plugin-svelte-cache.js';
29-
import { isSvelte5 } from './svelte-version.js';
29+
import { isSvelte5, isSvelte5WithHMRSupport } from './svelte-version.js';
3030

3131
const allowedPluginOptions = new Set([
3232
'include',
@@ -194,17 +194,24 @@ export function resolveOptions(preResolveOptions, viteConfig, cache) {
194194
const css = preResolveOptions.emitCss ? 'external' : 'injected';
195195
/** @type {Partial<import('../public.d.ts').Options>} */
196196
const defaultOptions = {
197-
hot: viteConfig.isProduction
198-
? false
199-
: {
200-
injectCss: css === 'injected',
201-
partialAccept: !!viteConfig.experimental?.hmrPartialAccept
202-
},
203197
compilerOptions: {
204198
css,
205199
dev: !viteConfig.isProduction
206200
}
207201
};
202+
if (isSvelte5) {
203+
if (isSvelte5WithHMRSupport) {
204+
// @ts-expect-error svelte4 does not have hmr option
205+
defaultOptions.compilerOptions.hmr = !viteConfig.isProduction;
206+
}
207+
} else {
208+
defaultOptions.hot = viteConfig.isProduction
209+
? false
210+
: {
211+
injectCss: css === 'injected',
212+
partialAccept: !!viteConfig.experimental?.hmrPartialAccept
213+
};
214+
}
208215
/** @type {Partial<import('../types/options.d.ts').ResolvedOptions>} */
209216
const extraOptions = {
210217
root: viteConfig.root,
@@ -231,45 +238,52 @@ export function resolveOptions(preResolveOptions, viteConfig, cache) {
231238
*/
232239
function enforceOptionsForHmr(options) {
233240
if (isSvelte5) {
234-
// TODO add hmr options for svelte5 once it is supported and update utils/log.js#logSvelte5Warning
235-
options.hot = false;
236-
}
237-
if (options.hot) {
238-
if (!options.compilerOptions.dev) {
239-
log.warn('hmr is enabled but compilerOptions.dev is false, forcing it to true');
240-
options.compilerOptions.dev = true;
241+
if (options.hot && isSvelte5WithHMRSupport) {
242+
log.warn(
243+
'svelte 5 has hmr integrated in core. Please remove the hot option and use compilerOptions.hmr instead'
244+
);
245+
delete options.hot;
246+
// @ts-expect-error hmr option doesn't exist in svelte4
247+
options.compilerOptions.hmr = true;
241248
}
242-
if (options.emitCss) {
243-
if (options.hot !== true && options.hot.injectCss) {
244-
log.warn('hmr and emitCss are enabled but hot.injectCss is true, forcing it to false');
245-
options.hot.injectCss = false;
246-
}
247-
const css = options.compilerOptions.css;
248-
if (css === true || css === 'injected') {
249-
const forcedCss = 'external';
250-
log.warn(
251-
`hmr and emitCss are enabled but compilerOptions.css is ${css}, forcing it to ${forcedCss}`
252-
);
253-
options.compilerOptions.css = forcedCss;
249+
} else {
250+
if (options.hot) {
251+
if (!options.compilerOptions.dev) {
252+
log.warn('hmr is enabled but compilerOptions.dev is false, forcing it to true');
253+
options.compilerOptions.dev = true;
254254
}
255-
} else {
256-
if (options.hot === true || !options.hot.injectCss) {
257-
log.warn(
258-
'hmr with emitCss disabled requires option hot.injectCss to be enabled, forcing it to true'
259-
);
260-
if (options.hot === true) {
261-
options.hot = { injectCss: true };
262-
} else {
263-
options.hot.injectCss = true;
255+
if (options.emitCss) {
256+
if (options.hot !== true && options.hot.injectCss) {
257+
log.warn('hmr and emitCss are enabled but hot.injectCss is true, forcing it to false');
258+
options.hot.injectCss = false;
259+
}
260+
const css = options.compilerOptions.css;
261+
if (css === true || css === 'injected') {
262+
const forcedCss = 'external';
263+
log.warn(
264+
`hmr and emitCss are enabled but compilerOptions.css is ${css}, forcing it to ${forcedCss}`
265+
);
266+
options.compilerOptions.css = forcedCss;
267+
}
268+
} else {
269+
if (options.hot === true || !options.hot.injectCss) {
270+
log.warn(
271+
'hmr with emitCss disabled requires option hot.injectCss to be enabled, forcing it to true'
272+
);
273+
if (options.hot === true) {
274+
options.hot = { injectCss: true };
275+
} else {
276+
options.hot.injectCss = true;
277+
}
278+
}
279+
const css = options.compilerOptions.css;
280+
if (!(css === true || css === 'injected')) {
281+
const forcedCss = 'injected';
282+
log.warn(
283+
`hmr with emitCss disabled requires compilerOptions.css to be enabled, forcing it to ${forcedCss}`
284+
);
285+
options.compilerOptions.css = forcedCss;
264286
}
265-
}
266-
const css = options.compilerOptions.css;
267-
if (!(css === true || css === 'injected')) {
268-
const forcedCss = 'injected';
269-
log.warn(
270-
`hmr with emitCss disabled requires compilerOptions.css to be enabled, forcing it to ${forcedCss}`
271-
);
272-
options.compilerOptions.css = forcedCss;
273287
}
274288
}
275289
}

packages/vite-plugin-svelte/src/utils/svelte-version.js

+6
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ export const isSvelte4 = VERSION.startsWith('4.');
99
* @type {boolean}
1010
*/
1111
export const isSvelte5 = VERSION.startsWith('5.');
12+
13+
/**
14+
* @type {boolean}
15+
*/
16+
export const isSvelte5WithHMRSupport =
17+
VERSION.startsWith('5.0.0-next.') && Number(VERSION.slice(11)) > 96;

0 commit comments

Comments
 (0)