Since svelte-preprocess runs Sass on each component separately, this can cause @charset to be generated multiple times (once per component with non-ASCII characters) or in the "wrong" place (intermediate CSS output that does not wind up at the beginning of the final CSS bundle).
Still, I figured I'd file a bug in this repo because anyone else using sass + svelte-preprocess + rollup together are likely to encounter this problem (and the docs in this repo do point users toward this combo of tools!). It would probably be fair to close out this bug, since the most problematic behavior is the responsibility of rollup-plugin-css-only (and probably other downstream CSS handlers, I would guess!) But since this problem can be subtly introduced during the svelte-preprocess stage, it might be worth considering some mitigation (see "Expected behavior" section for suggestions).
svelte-preprocess documentation could caution users about this problem. Tell users they can work around this issue by making sure their CSS bundler handles it or by passing the charset: false option to Sass^1 in order to avoid outputting @charset.
If any intermediate output from Sass preprocessing starts with a @charset statement, svelte-preprocess could warn the user in the console of the potential for bad concatenation. (e.g. "At least one of your components with SCSS contains non-ASCII characters. You might need to verify that your CSS bundler handles the resulting @charset statement properly.")
Make it the default to pass charset: false to Sass. (Since browsers should fall back to UTF-8 if the charset is not explicit, this seems low risk. I am not an expert on this so please verify that this won't cause greater problems for users before doing it!)
Stacktraces
N/A
Information about your project:
N/A
Additional context
Users might run into a similar problem if they use plain CSS @import in their SCSS, since this type of statement also must only appear at the top of CSS output.)
Describe the bug
When SCSS input contains any non-ASCII characters, Sass adds
@charset: "UTF-8";
to CSS output (see discussion in https://github.com/sass/dart-sass/issues/567).@charset
in CSS has very specific rules: it should only appear at the beginning of a CSS file and only once. (https://developer.mozilla.org/en-US/docs/Web/CSS/@charset, https://drafts.csswg.org/css-syntax-3/#charset-rule)Since svelte-preprocess runs Sass on each component separately, this can cause
@charset
to be generated multiple times (once per component with non-ASCII characters) or in the "wrong" place (intermediate CSS output that does not wind up at the beginning of the final CSS bundle).Ultimately, it's the responsibility of downstream tools to ensure the CSS generated by each component gets bundled together in a valid way. In the case I've encountered, it's
rollup-plugin-css-only
that can cause a problem when concatenating the CSS from each Svelte component, so I've filed https://github.com/thgh/rollup-plugin-css-only/issues/54. (As a counterpoint, Vite correctly deduplicates and hoists@charset
produced by intermediate outputs: see https://github.com/vitejs/vite/pull/7678 and https://github.com/vitejs/vite/pull/7691).Still, I figured I'd file a bug in this repo because anyone else using sass + svelte-preprocess + rollup together are likely to encounter this problem (and the docs in this repo do point users toward this combo of tools!). It would probably be fair to close out this bug, since the most problematic behavior is the responsibility of
rollup-plugin-css-only
(and probably other downstream CSS handlers, I would guess!) But since this problem can be subtly introduced during the svelte-preprocess stage, it might be worth considering some mitigation (see "Expected behavior" section for suggestions).Logs N/A
To Reproduce See this minimal reproduction: https://gist.github.com/alecglassford/e95ccb506089f76479bf170a0e96f270
Expected behavior
svelte-preprocess
documentation could caution users about this problem. Tell users they can work around this issue by making sure their CSS bundler handles it or by passing thecharset: false
option to Sass^1 in order to avoid outputting@charset
.@charset
statement,svelte-preprocess
could warn the user in the console of the potential for bad concatenation. (e.g. "At least one of your components with SCSS contains non-ASCII characters. You might need to verify that your CSS bundler handles the resulting@charset
statement properly.")charset: false
to Sass. (Since browsers should fall back to UTF-8 if the charset is not explicit, this seems low risk. I am not an expert on this so please verify that this won't cause greater problems for users before doing it!)Stacktraces N/A
Information about your project: N/A
Additional context Users might run into a similar problem if they use plain CSS
@import
in their SCSS, since this type of statement also must only appear at the top of CSS output.)