Skip to content

feat(svelte5): enable hmr #836

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

Merged
merged 9 commits into from
Apr 10, 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/shiny-drinks-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/vite-plugin-svelte': minor
---

feat(svelte5): enable hmr option in dev
3 changes: 2 additions & 1 deletion packages/vite-plugin-svelte/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ export function svelte(inlineOptions) {
},

handleHotUpdate(ctx) {
if (!options.hot || !options.emitCss) {
// @ts-expect-error svelte4 does not have hmr option
if ((!options.hot && !options.compilerOptions.hmr) || !options.emitCss) {
return;
}
const svelteRequest = requestParser(ctx.file, false, ctx.timestamp);
Expand Down
3 changes: 2 additions & 1 deletion packages/vite-plugin-svelte/src/utils/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ export const _createCompileSvelte = (makeHot) => {
* @returns {Function | undefined}
*/
function buildMakeHot(options) {
const needsMakeHot = options.hot !== false && options.isServe && !options.isProduction;
const needsMakeHot =
!isSvelte5 && options.hot !== false && options.isServe && !options.isProduction;
if (needsMakeHot) {
// @ts-ignore
const hotApi = options?.hot?.hotApi;
Expand Down
5 changes: 1 addition & 4 deletions packages/vite-plugin-svelte/src/utils/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,6 @@ export function isDebugNamespaceEnabled(namespace) {

export function logSvelte5Warning() {
const notice = `You are using Svelte ${VERSION}. Svelte 5 support is experimental, breaking changes can occur in any release until this notice is removed.`;
const wip = [
'svelte-inspector is disabled until dev mode implements node to code mapping',
'hmr for .svelte files is disabled until hmr api is implemented'
];
const wip = ['svelte-inspector is disabled until dev mode implements node to code mapping'];
log.warn(`${notice}\nwork in progress:\n - ${wip.join('\n - ')}\n`);
}
100 changes: 57 additions & 43 deletions packages/vite-plugin-svelte/src/utils/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import { isCommonDepWithoutSvelteField } from './dependencies.js';
import { VitePluginSvelteStats } from './vite-plugin-svelte-stats.js';
import { VitePluginSvelteCache } from './vite-plugin-svelte-cache.js';
import { isSvelte5 } from './svelte-version.js';
import { isSvelte5, isSvelte5WithHMRSupport } from './svelte-version.js';

const allowedPluginOptions = new Set([
'include',
Expand Down Expand Up @@ -194,17 +194,24 @@ export function resolveOptions(preResolveOptions, viteConfig, cache) {
const css = preResolveOptions.emitCss ? 'external' : 'injected';
/** @type {Partial<import('../public.d.ts').Options>} */
const defaultOptions = {
hot: viteConfig.isProduction
? false
: {
injectCss: css === 'injected',
partialAccept: !!viteConfig.experimental?.hmrPartialAccept
},
compilerOptions: {
css,
dev: !viteConfig.isProduction
}
};
if (isSvelte5) {
if (isSvelte5WithHMRSupport) {
// @ts-expect-error svelte4 does not have hmr option
defaultOptions.compilerOptions.hmr = !viteConfig.isProduction;
}
} else {
defaultOptions.hot = viteConfig.isProduction
? false
: {
injectCss: css === 'injected',
partialAccept: !!viteConfig.experimental?.hmrPartialAccept
};
}
/** @type {Partial<import('../types/options.d.ts').ResolvedOptions>} */
const extraOptions = {
root: viteConfig.root,
Expand All @@ -231,45 +238,52 @@ export function resolveOptions(preResolveOptions, viteConfig, cache) {
*/
function enforceOptionsForHmr(options) {
if (isSvelte5) {
// TODO add hmr options for svelte5 once it is supported and update utils/log.js#logSvelte5Warning
options.hot = false;
}
if (options.hot) {
if (!options.compilerOptions.dev) {
log.warn('hmr is enabled but compilerOptions.dev is false, forcing it to true');
options.compilerOptions.dev = true;
if (options.hot && isSvelte5WithHMRSupport) {
log.warn(
'svelte 5 has hmr integrated in core. Please remove the hot option and use compilerOptions.hmr instead'
);
delete options.hot;
// @ts-expect-error hmr option doesn't exist in svelte4
options.compilerOptions.hmr = true;
}
if (options.emitCss) {
if (options.hot !== true && options.hot.injectCss) {
log.warn('hmr and emitCss are enabled but hot.injectCss is true, forcing it to false');
options.hot.injectCss = false;
}
const css = options.compilerOptions.css;
if (css === true || css === 'injected') {
const forcedCss = 'external';
log.warn(
`hmr and emitCss are enabled but compilerOptions.css is ${css}, forcing it to ${forcedCss}`
);
options.compilerOptions.css = forcedCss;
} else {
if (options.hot) {
if (!options.compilerOptions.dev) {
log.warn('hmr is enabled but compilerOptions.dev is false, forcing it to true');
options.compilerOptions.dev = true;
}
} else {
if (options.hot === true || !options.hot.injectCss) {
log.warn(
'hmr with emitCss disabled requires option hot.injectCss to be enabled, forcing it to true'
);
if (options.hot === true) {
options.hot = { injectCss: true };
} else {
options.hot.injectCss = true;
if (options.emitCss) {
if (options.hot !== true && options.hot.injectCss) {
log.warn('hmr and emitCss are enabled but hot.injectCss is true, forcing it to false');
options.hot.injectCss = false;
}
const css = options.compilerOptions.css;
if (css === true || css === 'injected') {
const forcedCss = 'external';
log.warn(
`hmr and emitCss are enabled but compilerOptions.css is ${css}, forcing it to ${forcedCss}`
);
options.compilerOptions.css = forcedCss;
}
} else {
if (options.hot === true || !options.hot.injectCss) {
log.warn(
'hmr with emitCss disabled requires option hot.injectCss to be enabled, forcing it to true'
);
if (options.hot === true) {
options.hot = { injectCss: true };
} else {
options.hot.injectCss = true;
}
}
const css = options.compilerOptions.css;
if (!(css === true || css === 'injected')) {
const forcedCss = 'injected';
log.warn(
`hmr with emitCss disabled requires compilerOptions.css to be enabled, forcing it to ${forcedCss}`
);
options.compilerOptions.css = forcedCss;
}
}
const css = options.compilerOptions.css;
if (!(css === true || css === 'injected')) {
const forcedCss = 'injected';
log.warn(
`hmr with emitCss disabled requires compilerOptions.css to be enabled, forcing it to ${forcedCss}`
);
options.compilerOptions.css = forcedCss;
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions packages/vite-plugin-svelte/src/utils/svelte-version.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ export const isSvelte4 = VERSION.startsWith('4.');
* @type {boolean}
*/
export const isSvelte5 = VERSION.startsWith('5.');

/**
* @type {boolean}
*/
export const isSvelte5WithHMRSupport =
VERSION.startsWith('5.0.0-next.') && Number(VERSION.slice(11)) > 96;