Skip to content

Conversation

Rich-Harris
Copy link
Member

@Rich-Harris Rich-Harris commented Nov 27, 2024

Fixes #14399

We currently get both false positives (CSS incorrectly assumed to be used) and false negatives (CSS incorrectly assumed to be unused) around render tags at present. We treat render tags as something of a black box, causing false positives which are harmless but undesirable. The false negatives are much worse.

This PR works by linking snippets to render tags. In many cases this is straightforward, because they're identified by name — if we have a {#snippet foo()} and a {@render foo()} in the same component, they are unambiguously linked. Similarly if we have a {@render children()} and children is a prop, we know that the render tag doesn't correspond to any markup inside the component, and so we don't need to consider it while pruning. Imports are treated the same way as props.

Where it gets more complicated is around render tags that can't be trivially statically analysed, and components. In a case like this...

{#each items as item}
  {@render item.snippet()}
{/each}

...or this...

<Thing someprop={fn()} />

...it's impossible to know which snippets will get rendered without more sophisticated static analysis, so in these cases we deopt and assume that the render tag/component could be rendering any locally defined snippets. In practice, this means there will be occasional false positives, but it should eliminate false negatives.

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.
  • If this PR changes code within packages/svelte/src, add a changeset (npx changeset).

Tests and linting

  • Run the tests with pnpm test and lint the project with pnpm lint

Sorry, something went wrong.

WIP

Verified

This commit was signed with the committer’s verified signature.
lunny Lunny Xiao

Verified

This commit was signed with the committer’s verified signature.
lunny Lunny Xiao
WIP

Verified

This commit was signed with the committer’s verified signature.
lunny Lunny Xiao

Verified

This commit was signed with the committer’s verified signature.
lunny Lunny Xiao

Verified

This commit was signed with the committer’s verified signature.
lunny Lunny Xiao

Partially verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.

Partially verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.

Verified

This commit was signed with the committer’s verified signature.
lunny Lunny Xiao

Verified

This commit was signed with the committer’s verified signature.
lunny Lunny Xiao
Copy link

changeset-bot bot commented Nov 27, 2024

🦋 Changeset detected

Latest commit: 8e3a529

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

Playground

pnpm add https://pkg.pr.new/svelte@14456

Verified

This commit was signed with the committer’s verified signature.
lunny Lunny Xiao

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@Rich-Harris Rich-Harris marked this pull request as ready for review November 27, 2024 18:36

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.

let resolved = true;

for (const attribute of node.attributes) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not really relevant, but this iterates over the attributes, and below we're iterating over them again, feels a bit wasteful - but merging them into one probably makes everything harder to reason about

Rich-Harris and others added 4 commits November 27, 2024 16:46

Partially verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
…ag.js

Co-authored-by: Simon H <[email protected]>
Rich-Harris and others added 10 commits November 27, 2024 17:26
Copy link
Member

@dummdidumm dummdidumm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also added handling for :has

@dummdidumm dummdidumm merged commit c4ac0e0 into main Nov 28, 2024
11 checks passed
@dummdidumm dummdidumm deleted the better-pruning branch November 28, 2024 12:02
@github-actions github-actions bot mentioned this pull request Nov 28, 2024
@JonathonRP
Copy link

@Rich-Harris I wonder if you think a children's reference would help this situation or not?

@Rich-Harris
Copy link
Member Author

I don't know what that means?

@JonathonRP
Copy link

I don't know what that means?

What I mean is to make a mechanism to track the children, instead of treating them like black boxes. Similar to how react treats children and allows manipulating them.
@Rich-Harris, does that help? I only ask because it's been a feature request before and thought it could be a useful technique to help with the css pruning in snippets/children.

@Rich-Harris
Copy link
Member Author

No that wouldn't help. You're talking about a runtime-based solution for something that happens at compile time

@JonathonRP
Copy link

No that wouldn't help. You're talking about a runtime-based solution for something that happens at compile time

Oh! Gotcha, thanks for the correction and sorry for the slight derailment.

@fsoft72
Copy link
Contributor

fsoft72 commented Nov 30, 2024

This fix that got into svelte 5.2.11 broke my code.
The error I got is this

Sourcemap for "/home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/@[email protected][email protected]/node_modules/@carbon/charts-svelte/dist/styles.css" points to missing source files
9:04:11 AM [vite] (ssr) Error when evaluating SSR module /src/routes/(admin)/dst/selects/+page.svelte:
|- RangeError: Maximum call stack size exceeded
    at String.replace (<anonymous>)
    at relative_selector_might_apply_to_node (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:420:30)
    at apply_selector (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:158:3)
    at apply_combinator (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:206:10)
    at apply_combinator (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:197:11)
    at apply_combinator (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:197:11)
    at apply_combinator (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:197:11)
    at apply_combinator (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:197:11)
    at apply_combinator (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:197:11)
    at apply_combinator (file:///home/fabio/dev/projects/dst-srm/frontend/node_modules/.pnpm/[email protected]/node_modules/svelte/src/compiler/phases/2-analyze/css/css-prune.js:197:11)

I had to revert to svelte 5.2.10 to continue to work.

The component is huge and with many dependencies, I don't know how to produce a small REPL to reproduce the error.

@Rich-Harris
Copy link
Member Author

I don't know how to produce a small REPL to reproduce the error.

It's very simple: delete some code. Did the error go away? Put it back. Rinse and repeat until you've isolated the problem. This technique applies generally.

@hyunbinseo
Copy link
Contributor

Should this be the case? Or am I missing something?

My existing styles are being pruned, blocking an update.

<!-- src/routes/+page.svelte -->

{#snippet nav()}
  <nav>
    <a href="/">Home</a>
  </nav>
{/snippet}

{@render nav()}

<style>
  /* Unused CSS selector "nav a"(css_unused_selector)eslintsvelte/valid-compile */
  /* Unused CSS selector "nav a"svelte(css_unused_selector) */
  nav a {
    color: red;
  }
</style>

Reproducible in the REPL as well.

@dummdidumm
Copy link
Member

The maximum call stack issue is likely fixed in the latest version, please try again after updating

@hyunbinseo
Copy link
Contributor

This persists on [email protected]. Check by changing the version on the REPL.

Created a separate issue regarding this issue:

@fsoft72
Copy link
Contributor

fsoft72 commented Dec 2, 2024

@dummdidumm now it works (using 5.3.1)

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

Successfully merging this pull request may close these issues.

sibling selectors involving {#key ...}/{@render ...} are incorrectly marked as unused
5 participants