sveltejs / svelte

web development for the rest of us
https://svelte.dev
MIT License
80.15k stars 4.26k forks source link

Improve documentation of the `createRawSnippet` function #14061

Open Serator opened 3 weeks ago

Serator commented 3 weeks ago

Describe the problem

The current description (1, 2) of this feature is rather sparse.

A previous version of the documentation (doc, comment from Pr) revealed more details.

Applying snippets programmatically is currently much less convenient than creating them declaratively. Hopefully, more detailed documentation will smooth out these differences.

Describe the proposed solution

I would like to see more examples of how to use it properly and in what cases.

Importance

nice to have

khromov commented 3 weeks ago

Here is an example that was shared by Pablo and that shows two ways of doing programmatic snippets for rendering a HTML string, and a Svelte component.

https://svelte.dev/playground/ccef09a8880244ffbeed3943cee0c0a0?version=5.1.3

Serator commented 3 weeks ago

It looks pretty confusing. 🀯 In my case I want to have a generic wrapper, where the input is passed a component and its properties, and the output should be a snippet that wraps the component with props.

@khromov In your example the property is known in advance - number, is there any way to do the same without specifying the property?

In other words, an object with arbitrary properties could be passed here (let's say we don't know in advance which component the wrapper will be used with).

image

Accordingly, here we should β€œprint” this object by returning a getter on each of its keys.

image
Serator commented 3 weeks ago

Modified the example above a bit to get what I want.

It gets even more confusing. 😬 With the lack of documentation, it's very difficult to figure this out.

Leonidaz commented 3 weeks ago

Totally agree that documentation is still lacking but from I can tell the team is working hard to remedy this.

This is the simplest example that I came up with to make it more generic based on the work that both of you have done

Playground: Decorated snippet mounting component

paoloricciuti commented 3 weeks ago

In general createRawSnippet is intentionally a pretty low level api. It's meant for framework authors that want to integrate with svelte rather than for normal users of the framework (hence the name createRawSnippet instead of createSnippet).

I think probably a bit more documentation around it could be beneficial but i don't think we should go into details about how everything works (also because most of the things that you would do are just using the svelte client side and server side api.

In general there are three rules to follow around createRawSnippet

  1. you need to return a single element from the render function and if you want it to be hydratable you need to use the server svelte api (for instance, render)
  2. in the setup function you get the element that you returned from the setup function as the first argument and you need to interact with it with raw dom api + svelte client side api (mount, hydrate) but also $effect and $state.
  3. All the rest of the rules that applies to normal functions apply here...so if you want to pass a prop since it needs to cross function boundaries you need to either wrap it in a callback or use a getter.
Leonidaz commented 3 weeks ago

I think probably a bit more documentation around it could be beneficial but i don't think we should go into details about how everything works (also because most of the things that you would do are just using the svelte client side and server side api.

@paoloricciuti my 2 cents regarding documenting would be is to document everything with examples but prefix with warnings about the intended audience (e.g. "Only needed by library developers") and that typically one should never need this.

Incidentally, I created a solution / workaround to define multiple snippets as regular markup and then import them into components that need them. Pretty sure that snippets would only be rendered client side since server side as far as I recall doesn't support reactivity (maybe stores still do...).

Snippets can also take components as input since everything is functions now. I included it in the example.

[This solution is oudated, see below for a much more elegant one] Playground: Workaround to export / import snippets via state reactivity

EDIT

Actually, there is a much more elegant way of importing / exporting snippets once I looked closer at the compiled code. The snippets are actually declared as const's in the component, so they can just be assigned to a module variable and exported.

It's a lot more straight forward:

Playground: Import snippets from a snippet collection

Leonidaz commented 3 weeks ago

Actually, there is a much more elegant solution for importing snippets from a collection of snippets. Once I looked closer at the compiled code, it was clear that snippets are declared as const's client-side or function's server-side and can be exported via the module export. Really enjoying the fact that components are functions now πŸ‘

Here's a quick demo. Playground : Import snippets from a snippet collection

The snippets should now be rendered on the server. I didn't test it though but logically and judging by the output it should work.

Leonidaz commented 3 weeks ago

@paoloricciuti a bit off topic, but would be cool to have scoped styles for snippets. Snippets can have <style> but it's unscoped, and just rendered as is.

Makes me really wonder if having multiple components per file to replace snippets sometime in the future would be a much more flexible approach πŸ˜‚