Skip to content

Commit cb7f03d

Browse files
Rich Harrisdominikg
andauthored
feat: respect user emitCss option (#41) - fixes #9
* respect user emitCss option - fixes #9 * ensure hmr keeps working with emitCss: false option, remove forced values for css and hydratable * add changeset * stabilize hmr test * stabilize hmr test some more Co-authored-by: dominikg <dominik.goepel@gmx.de>
1 parent 76c653e commit cb7f03d

File tree

4 files changed

+52
-20
lines changed

4 files changed

+52
-20
lines changed

.changeset/sharp-laws-leave.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+
Allow emitCss: false for production builds and customizable compilerOptions.css and hydratable - fixes #9

packages/playground/hmr/__tests__/hmr.spec.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
editFileAndWaitForHmrComplete,
66
untilUpdated,
77
sleep,
8-
getColor
8+
getColor,
9+
editFile
910
} from '../../testUtils';
1011

1112
test('should render App', async () => {
@@ -86,8 +87,8 @@ if (!isBuild) {
8687
await updateHmrTest((content) =>
8788
content.replace('<!-- HMR-TEMPLATE-INJECT -->', '<span/>\n<!-- HMR-TEMPLATE-INJECT -->')
8889
);
89-
await expect(await getText(`#hmr-test-1 .counter`)).toBe('1');
90-
await expect(await getText(`#hmr-test-2 .counter`)).toBe('0');
90+
expect(await getText(`#hmr-test-1 .counter`)).toBe('1');
91+
expect(await getText(`#hmr-test-2 .counter`)).toBe('0');
9192
});
9293

9394
test('should preserve state of external store used by HmrTest.svelte when editing App.svelte', async () => {
@@ -99,10 +100,10 @@ if (!isBuild) {
99100
)
100101
);
101102
// counter state is preserved
102-
await expect(await getText(`#hmr-test-1 .counter`)).toBe('1');
103-
await expect(await getText(`#hmr-test-2 .counter`)).toBe('0');
103+
expect(await getText(`#hmr-test-1 .counter`)).toBe('1');
104+
expect(await getText(`#hmr-test-2 .counter`)).toBe('0');
104105
// a third instance has been added
105-
await expect(await getText(`#hmr-test-3 .counter`)).toBe('0');
106+
expect(await getText(`#hmr-test-3 .counter`)).toBe('0');
106107
});
107108

108109
test('should preserve state of store when editing hmr-stores.js', async () => {
@@ -112,10 +113,25 @@ if (!isBuild) {
112113
// update store
113114
await updateStore((content) => `${content}\n/*trigger change*/\n`);
114115
// counter state is preserved
115-
await expect(await getText(`#hmr-test-1 .counter`)).toBe('1');
116-
await expect(await getText(`#hmr-test-2 .counter`)).toBe('1');
116+
expect(await getText(`#hmr-test-1 .counter`)).toBe('1');
117+
expect(await getText(`#hmr-test-2 .counter`)).toBe('1');
117118
// a third instance has been added
118-
await expect(await getText(`#hmr-test-3 .counter`)).toBe('0');
119+
expect(await getText(`#hmr-test-3 .counter`)).toBe('0');
120+
});
121+
122+
test('should work with emitCss: false', async () => {
123+
await editFile('vite.config.js', (c) => c.replace('svelte()', 'svelte({emitCss:false})'));
124+
await sleep(500); // editing vite config restarts server, give it some time
125+
await page.goto(viteTestUrl, { waitUntil: 'networkidle' });
126+
await sleep(50);
127+
expect(await getText(`#hmr-test-1 .counter`)).toBe('0');
128+
expect(await getColor(`#hmr-test-1 .label`)).toBe('green');
129+
await (await getEl(`#hmr-test-1 .increment`)).click();
130+
await sleep(50);
131+
expect(await getText(`#hmr-test-1 .counter`)).toBe('1');
132+
await updateHmrTest((content) => content.replace('color: green', 'color: red'));
133+
expect(await getColor(`#hmr-test-1 .label`)).toBe('red');
134+
expect(await getText(`#hmr-test-1 .counter`)).toBe('1');
119135
});
120136
});
121137
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ const _createCompileSvelte = (makeHot: Function) =>
1818
const finalCompilerOptions: CompileOptions = {
1919
...options.compilerOptions,
2020
filename,
21-
generate: ssr ? 'ssr' : 'dom',
22-
css: !emitCss,
23-
hydratable: true
21+
generate: ssr ? 'ssr' : 'dom'
2422
};
25-
if (options.hot) {
23+
if (options.hot && options.emitCss) {
2624
const hash = `s-${safeBase64Hash(normalizedFilename)}`;
2725
log.debug(`setting cssHash ${hash} for ${normalizedFilename}`);
2826
finalCompilerOptions.cssHash = () => hash;

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

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function buildDefaultOptions(
2323
): Partial<Options> {
2424
const disableCssHmr = !!options?.disableCssHmr;
2525
// emit for prod, emit in dev unless css hmr is disabled
26-
const emitCss = isProduction || !disableCssHmr;
26+
const emitCss = options?.emitCss != null ? options.emitCss : isProduction || !disableCssHmr;
2727
// no hmr in prod, only inject css in dev if emitCss is false
2828
const hot = isProduction
2929
? false
@@ -37,7 +37,8 @@ function buildDefaultOptions(
3737
compilerOptions: {
3838
format: 'esm',
3939
css: !emitCss,
40-
dev: !isProduction
40+
dev: !isProduction,
41+
hydratable: true
4142
}
4243
};
4344
log.debug(
@@ -73,6 +74,23 @@ function enforceOptionsForHmr(options: ResolvedOptions) {
7374
);
7475
options.compilerOptions.css = false;
7576
}
77+
} else {
78+
if (options.hot === true || !options.hot.injectCss) {
79+
log.warn(
80+
'hmr with emitCss disabled requires option hot.injectCss to be enabled, forcing it to true'
81+
);
82+
if (options.hot === true) {
83+
options.hot = { injectCss: true };
84+
} else {
85+
options.hot.injectCss = true;
86+
}
87+
}
88+
if (!options.compilerOptions.css) {
89+
log.warn(
90+
'hmr with emitCss disabled requires compilerOptions.css to be enabled, forcing it to true'
91+
);
92+
options.compilerOptions.css = true;
93+
}
7694
}
7795
}
7896
}
@@ -83,10 +101,6 @@ function enforceOptionsForProduction(options: ResolvedOptions) {
83101
log.warn('options.hot is enabled but does not work on production build, forcing it to false');
84102
options.hot = false;
85103
}
86-
if (!options.emitCss) {
87-
log.warn('you are building for production but emitCss is disabled. forcing it to true');
88-
options.emitCss = true;
89-
}
90104
if (options.compilerOptions.dev) {
91105
log.warn(
92106
'you are building for production but compilerOptions.dev is true, forcing it to false'
@@ -123,7 +137,6 @@ export async function resolveOptions(
123137
viteConfig: ResolvedConfig
124138
): Promise<ResolvedOptions> {
125139
const defaultOptions = buildDefaultOptions(viteConfig, inlineOptions);
126-
// TODO always load from vite root dir or make this configurable?
127140
const svelteConfig = (await loadSvelteConfig(viteConfig, inlineOptions)) || {};
128141
const resolvedOptions = mergeOptions(defaultOptions, svelteConfig, inlineOptions, viteConfig);
129142

0 commit comments

Comments
 (0)