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

CSS minification broken in 3.13 #3977

Closed
Conduitry opened this issue Nov 22, 2019 · 9 comments
Closed

CSS minification broken in 3.13 #3977

Conduitry opened this issue Nov 22, 2019 · 9 comments
Labels

Comments

@Conduitry
Copy link
Member

Describe the bug
The simple CSS minification that the compiler once performed on component styles seems to have largely stopped working.

Logs
N/A

To Reproduce

<div>Hey</div>

<style>
	div {
		font-size: 200%;
		color: red;
	}
</style>

Expected behavior
The styles this produces should continue to be lightly minified - whitespace should be removed, semicolons right before closing braces should be removed, etc. This stopped working between 3.12.1 and 3.13.0.

Stacktraces
N/A

Information about your Svelte project:
3.15.0, but present since 3.13.0.

Severity
Fairly low, as this doesn't result in any bad behavior, just unnecessary bytes.

Additional context
None.

@Conduitry Conduitry added the bug label Nov 22, 2019
@Conduitry
Copy link
Member Author

Wow this is way more insidious than I thought it was going to be. It's somehow related to the compiler getting into a bad state from previous components that it had compiled. As best as I can tell: If the very first thing you do with the compiler is to compile a component with component styles, they will be properly minified. But if you compile a component with no component styles, and then later compile a component that does have component styles, the second component's styles will not be minified.

@Conduitry
Copy link
Member Author

More precisely: It looks like all that matters is whether the very first component that's compiled has component styles. If it does, all is well - it doesn't matter how many component without styles there are later down the line. If the first one does not, there are problems.

This issue is actually what was causing the weird test failures I noticed in #3945 - and those test failures made me notice that it's not just that a failure to minify that happens - it also causes media queries to be dropped. For example:

const svelte = require('./compiler');
svelte.compile('');
console.log(svelte.compile('<div></div><style>@media(min-width: 1px) { div { color: red; } }</style>').js.code);

This results in styles of @media(min-width: 1px){}, and the .svelte-xyz class isn't added to the div.

This actually does mean incorrect results, not just suboptimal results, so the priority is probably more than 'fairly low'.

@Conduitry
Copy link
Member Author

It looks like this was broken by #3870. I'm seeing the issue in commit 4ffa6fc but not in de80ae7.

@Conduitry
Copy link
Member Author

It's related to code-red's handling of multi-line /* comments */, apparently. Of all things.

If I remove the /* ${banner} */ from the generated code, this works, even if I'd previously compiled a component with no styles. The single-line // ${this.comment} we're generating elsewhere seems to not be an issue.

@Conduitry
Copy link
Member Author

If I install the latest version of code-red (which is 0.0.26), the issue persists. If I symlink the current master branch of code-red (which is also 0.0.26), the issue goes away. The versions of the various dependencies that code-red has in its repo seem to be the same as the ones that are in svelte's package-lock.json, so I'm currently guessing that this issue is masked by having two instances of some or code-red's dependencies in the final bundle.

@mrkishi
Copy link
Member

mrkishi commented Nov 23, 2019

Alright, this is definitely being caused by estree-walker's childKeys cache. If I export childKeys from the compiler and do this, the problem goes away:

const svelte = require('./compiler');
svelte.compile('');
for (const key in svelte.childKeys) delete svelte.childKeys[key];
console.log(svelte.compile('<div></div><style>@media(min-width: 1px) { div { color: red; } }</style>').js.code);

@mrkishi
Copy link
Member

mrkishi commented Nov 23, 2019

So, it turns out there's a node called Block with children in the styles' ast, but there's also Block without children for block comments from estree.

Seems like the short-term fix is just adding childKeys.Block = ['children'];, but that doesn't sound optimal.

@Conduitry
Copy link
Member Author

The relevant confusion about the shape of the AST seems to be resolved by adding

childKeys.Block = ['children'];

when we're initing the walker.

@Rich-Harris
Copy link
Member

heroic efforts 🙇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants