Skip to content

Conversation

@Hugos68
Copy link
Contributor

@Hugos68 Hugos68 commented Feb 27, 2025

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

A better version of #15302

After discovering that $props.id returns the same value when used in isolation (for example Astro islands) you will get ID collisions, the users of the render API need to be able to influence the generated ID. This PR adds a uidPrefix option to influence the resulting ID from $props.id(), while still utilizing Svelte's internal UID generator to ensure that $props.id are always unique (in normal situations).

Discussed with @dummdidumm here: https://discord.com/channels/457912077277855764/750401468569354431/1344716129268011098

See withastro/astro#13327

  • 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

@changeset-bot
Copy link

changeset-bot bot commented Feb 27, 2025

🦋 Changeset detected

Latest commit: e549829

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

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

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

@svelte-docs-bot
Copy link

@github-actions
Copy link
Contributor

Playground

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

@dummdidumm
Copy link
Member

The test brought up a good point - we should have that prefix option for mount/hydrate aswell.

@paoloricciuti
Copy link
Member

The test brought up a good point - we should have that prefix option for mount/hydrate aswell.

Uh you are right...I thought we didn't need that because but it could conflict for that too in astro case

@Hugos68
Copy link
Contributor Author

Hugos68 commented Feb 28, 2025

Will attempt, although I only see id_generator being used on the server side? Where are client id's generated? And why isn't there a shared function for this?

@paoloricciuti
Copy link
Member

It seems to work! 😄

We paired on it so I'l let @dummdidumm review it!

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.

Looks good to me! Maybe @Rich-Harris can have a final quick look regarding the API

@paoloricciuti
Copy link
Member

Ugh I just realized that we called it prefixUid for render and uidPrefix for mount and hydrate

@dummdidumm
Copy link
Member

oh yeah that should be aligned

@Hugos68
Copy link
Contributor Author

Hugos68 commented Feb 28, 2025

I'll do that real quick, I think uidPrefix makes more sense correct?

@paoloricciuti
Copy link
Member

I'll do that real quick, I think uidPrefix makes more sense correct?

For me yes

@paoloricciuti
Copy link
Member

While looking at #15409 it occured to me that we should probably add the option to asClassComponent too

@Hugos68
Copy link
Contributor Author

Hugos68 commented Mar 1, 2025

@paoloricciuti Could you do that? I have no idea what that means.

@paoloricciuti
Copy link
Member

@paoloricciuti Could you do that? I have no idea what that means.

Sure I'll do it later

@Hugos68 Hugos68 requested a review from dummdidumm March 1, 2025 21:06
@paoloricciuti
Copy link
Member

@Rich-Harris I suggested to put the prefix on the context because this way if you hydrate a component within a component that had a different prefix it will break no?

@dummdidumm
Copy link
Member

yeah pretty sure you can't make it global, that won't work with multiple mount/hydrate with different prefixes

@Rich-Harris
Copy link
Member

It's synchronous, so it should be fine, no?

@dummdidumm
Copy link
Member

Yeah was just editing my post to say that - it works because it's synchronous. On subsequent updates they won't have the same prefix anymore, but that's also fine because they share one counter. Could use a comment explaining that nuance but otherwise good to go 👍

@Rich-Harris
Copy link
Member

On subsequent updates they won't have the same prefix anymore, but that's also fine because they share one counter.

Now that you mention it, what is the purpose of the prefix in the browser, given that the counter is shared globally?

@Rich-Harris
Copy link
Member

(or are we concerned about multiple copies of Svelte running in the same environment?)

@dummdidumm
Copy link
Member

yes, that could happen. It's unlikely but better to be safe than sorry.

@dummdidumm
Copy link
Member

dummdidumm commented Mar 3, 2025

Thinking further here - should we just create a random string ourselves, both on the server and the client? Assuming we find something that's sufficiently unlikely to clash, do we even need people to add this option manually when we can deduplicate automatically? @Hugos68 would there anything speaking against that?

@Rich-Harris
Copy link
Member

I'm not sure about randomising it — that would e.g. prevent SvelteKit from serving 304s.

Gah, this is more complicated than I thought. Was really hoping to avoid adding an extra field to component context since those objects are potentially created in their thousands. Hmm

@Rich-Harris
Copy link
Member

It's dirty but could we use globalThis in the browser, and just keep the idPrefix option on the server?

@dummdidumm
Copy link
Member

Gah, this is more complicated than I thought. Was really hoping to avoid adding an extra field to component context since those objects are potentially created in their thousands. Hmm

Not sure I follow? Why would we need that? Your solution right now works. Between mount/hydrate within one runtime it's unique since they share the same counter, and across runtimes you gotta make sure not to use the same prefix anyway.

In other words this is good to go IMO

Comment on lines +403 to +407
// we need to put the `$props.id` after the `$.push` because the `component_context` will be properly initialized
if (analysis.props_id) {
// need to be placed on first line of the component for hydration
component_block.body.unshift(b.const(analysis.props_id, b.call('$.props_id')));
}
Copy link
Member

Choose a reason for hiding this comment

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

if we don't use context we can revert this change too

Copy link
Member

@paoloricciuti paoloricciuti left a comment

Choose a reason for hiding this comment

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

Just asking for changes to prevent merging with the fix to move props id after context (and also needs_context = true

}

context.state.analysis.props_id = parent.id;
context.state.analysis.needs_context = true;
Copy link
Member

Choose a reason for hiding this comment

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

We can also revert this if we don't use context anymore

@paoloricciuti
Copy link
Member

paoloricciuti commented Mar 3, 2025

Btw this was the problem i was talking about with the global value

https://svelte.dev/playground/e11bb6e7c46245f3aac2815180d301d1?version=pr-15403

I guess we can fix this if we revert to the old value after mounting the component?

@dummdidumm
Copy link
Member

That would not help for subsequent updates of the mounted thing.
But I also don't think that this is a problem anyway, because yes the prefix is not what you declared but it's still unique across instances, which is the main point. (this is why I said a comment explaining that nuance might be good)

@paoloricciuti
Copy link
Member

That would not help for subsequent updates of the mounted thing. But I also don't think that this is a problem anyway, because yes the prefix is not what you declared but it's still unique across instances, which is the main point. (this is why I said a comment explaining that nuance might be good)

Ohhh gotcha...well it could be a problem if you are filtering IDs based on the prefix. But I suppose is niche enough to not add runtime for this case

@Hugos68
Copy link
Contributor Author

Hugos68 commented Mar 3, 2025

I'm all for a better solution, the main use case for me opening this PR and use case is so that individual islands created by Astro can still have unique ID's (so calling render or mount/hydrate in completely different contexts). So if you want, two completely seperate Svelte apps should be able to produce non colliding ID's.

@Rich-Harris Rich-Harris mentioned this pull request Mar 4, 2025
6 tasks
@Rich-Harris
Copy link
Member

Opened #15428 as an alternative

@dummdidumm
Copy link
Member

Closing in favor of #15428, which I'll merge now - thank you everyone!

@dummdidumm dummdidumm closed this Mar 4, 2025
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.

4 participants