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

Sveltekit server components #12123

Open
CurltureCo opened this issue Apr 14, 2024 · 2 comments
Open

Sveltekit server components #12123

CurltureCo opened this issue Apr 14, 2024 · 2 comments

Comments

@CurltureCo
Copy link

CurltureCo commented Apr 14, 2024

Describe the problem

Until now I havnt found a way to get server components similar to htmx. One possible way is to put components in the router and use them like a route but it produces a large response size.

Describe the proposed solution

This javascript function kindof works
first I setup a components directory in routes, for example "routes/components/counter/+page.svelte"
then when I want to update the component I pass the destination element and request path to the function below and it successfully grabs the component and places it

    const getComponent = async (componentPath: string, target: HTMLElement) => {
        const res = await fetch(componentPath, {
            method: 'GET',
            headers: {
                // html content type
                'Content-Type': 'text/html'
            }
        });
        if (res.ok) {
            const parser = new DOMParser();
            const doc = parser.parseFromString(await res.text(), 'text/html');

            const scriptTags = doc.getElementsByTagName('script');
            const lastScriptTag = scriptTags[scriptTags.length - 1]!;

            const script = document.createElement('script');
            script.innerHTML = lastScriptTag.innerHTML;

            const teleportContent = () => {
                div.querySelector('#svelte-announcer')?.remove();
                target.replaceWith(...div.childNodes);
            };

            // create a div in body to hold the component with id of the component path
            const div = document.createElement('div');
            div.id = componentPath;
            document.body.appendChild(div);

            // wait for the component to be hydrated
            const observer = new MutationObserver((mutations) => {
                if (mutations[0].removedNodes.length > 0) {
                    observer.disconnect();
                    teleportContent();
                }
            });
            observer.observe(div, { childList: true });

            div.appendChild(script);
            div.remove();
        } else {
            console.error('Fetch error:', res.status);
        }
    };

The issue with this is that although it does support the use of stores and imports in the component (which is great!) it produces a large response for a relatively small component.
It would be great if the sveltekit team would add a more native and convenient solution that produces a smaller request. There are many directions this could go, I would love to see any of them happen.

Alternatives considered

I also tried setting htmx up, it worked but it was very clunky and not ideal for sveltekit in my opinion

How do I get it going?
do
npm install htmx.org && npm install -D typed-htmx

add this script in your app.html head

<script src="node_modules/htmx.org/dist/htmx.min.js"></script>

add this in tsconfig

"strict": true,
"types": [ "typed-htmx" ]

and this inside global in app.d.ts

declare namespace svelteHTML {
    interface HTMLAttributes extends HtmxAttributes {}
}

Importance

nice to have

Additional Information

No response

@brunnerh
Copy link
Member

Why do you want or need this?

@MahmoodKhalil57
Copy link

MahmoodKhalil57 commented Apr 14, 2024

Why do you want or need this?

There are a lot of reasons to want to get html as a response
https://htmx.org/essays/when-to-use-hypermedia/

For me it is to make specific components accessible only under authentication like +page.server.ts

edit:
I am OP from a different account

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

3 participants