Skip to content
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

Sass with non-ASCII characters can lead to unexpected/invalid @charset in output CSS #566

Open
alecglassford opened this issue Dec 16, 2022 · 0 comments

Comments

@alecglassford
Copy link
Contributor

Describe the bug

When SCSS input contains any non-ASCII characters, Sass adds @charset: "UTF-8"; to CSS output (see discussion in sass/dart-sass#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 thgh/rollup-plugin-css-only#54. (As a counterpoint, Vite correctly deduplicates and hoists @charset produced by intermediate outputs: see vitejs/vite#7678 and vitejs/vite#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 the charset: false option to Sass1 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.)

Footnotes

  1. e.g.

    preprocess: sveltePreprocess({
        scss: {
            charset: false,
        },
    })
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant