Support dynamic content of app.html
See original GitHub issueDescribe the problem
While I imagine the current static approach for app.html is acceptable in ~99% of use cases, sometimes it would be useful to make its contents dynamic.
I have a multi-tenant application that loads a customer-provided skin at runtime and wraps my app in it. Hypothetically, let’s say the skin looks like this:
<html>
<head>
<title>APP!</title>
</head>
<body>
<p>some content before the application</p>
{{app}}
<p>some content after the application</p>
</body>
</html>
Achieving this isn’t particularly difficult.
//__layout.js
<script context="module">
//load the skin async based on things like hostname
//and other portions of the URL, then...
return { props: { skin: skinHTML } };
</script>
const [before, after] = skin.split('{{app}}');
// ... some regex magic to strip out the html/head/body tags
{@html before}
<slot />
{@html after}
Indeed, this is exactly what I’m currently doing. But there’s a problem. If the skin wraps the app in a tag, Svelte(Kit?) starts to misunderstand the DOM and the app gets duplicated. Given a skin that contains this: <div>{{app}}</div>
…
The app behaves very oddly, and most of the time results in 2 copies of itself on the page. (To the best of my understanding, sometimes in dev hmr it will clean itself up to a single instance, but not always)
Here’s a video demonstrating why I want to do this, and how it affects the application: https://youtu.be/voYqm2Chu1U
If the contents of app.html were dynamic, it would be trivial for me to replace {{app}}
with <div id="svelte"></div>
.
Describe the proposed solution
I can see that everything is currently hard-coded to read app.html from the file system and use that value.
It would be nice if there were some sort of hook or middleware that I could add that would be called instead that could return the HTML contents currently obtained from app.html. It would need to happen at runtime (server-side) so that I can parse the URL to get the correct skin for the current hostname.
Alternatives considered
The only other thing I can think of is to use Vanilla Svelte and express/etc to set the page contents to the skin at runtime. I’d hate to give up the routing/etc benefits of SvelteKit, though.
I haven’t been able to think of any other alternatives, but I’m open to any current/proposed solution that lets me build the features I need in my app. It doesn’t have to be the solution I proposed.
Importance
would make my life easier
Additional Information
No response
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:10 (5 by maintainers)
I take it the customers need to be able to update the skin “live”, i.e. they expect to be able to update the skins and have their updates take effect immediately. If they would find it acceptable to submit their proposed skins to you and wait for you to update their sites later, then you could insert a manual checking step where you could see what they’ve wrapped
{{app}}
in, and possibly update the regex accordingly. But I’m guessing you need them to be able to update “live”, and therefore you can’t know ahead of time how{{app}}
will be wrapped. Is that right?I think @Mlocik97 meant that instead of asking your customers to put
{{app}}
in their markup, ask them to put in a specific element (or, I would add, an element with a specific ID). I.e. ask them to put<div id="app"></div>
in their markup. Then after you retrieve the skin HTML, you can use existing HTML-parsing tools to find the div you need to replace, and remove the html/head/body stuff, etc. Which is going to be more reliable than regexes: if the customers give you malformed HTML skins, you can have the Java platform return an error saying “Must be valid HTML, here’s the part that was invalid”.I’m afraid I don’t know the guts of the adapter system well enough to answer this, sorry. You’re quite right that the Svelte discord is the right place to ask for help, so that these issue comments can be kept focused on your specific feature request (dynamically selecting the template HTML instead of serving up a static file). Thank you for keeping a good separation between feature requests and associated discussion (which do belong here), and “how do I do this thing?” requests, which belong either in the discord channel or in the GitHub Discussions feature. (I believe the project is planning to move to Discussions, but at the moment the discord channel is more active and you’ll likely get faster responses there).
Part of what’s going on with the
<div>{{app}}</div>
case is that you’re using@html
to render the “before” and “after” portions, and if{{app}}
is wrapped in a div then that will cause@html
to be passed HTML that isn’t valid standalone HTML. (That’s even the example used in https://svelte.dev/docs#html as an illustration of what won’t work). I think if you fix your regex to detect a wrapped{{app}}
and remove that wrapper div (assuming it had nothing else inside it), then you should be able to make progress.Because of that, I’m not yet persuaded that changing Svelte-Kit to load the app.html dynamically is the only way to solve your use case, though I can see where it would have advantages for you (it would certainly be simpler than the regex approach you’re currently using). But as it’s not necessary for most use cases, I suspect the only way you’ll see this feature request implemented is to “scratch your own itch” by submitting a PR.
Alternately, if you don’t want to wait for this feature request to be implemented, one thing you might be able to do for yourself, without needing to submit a PR to the Svelte-Kit project, is to write your own adapter to take the built app and adapt it to load the template dynamically. You’d want to look at these lines of code to see what it’s producing and what you’d want to change.