-
Notifications
You must be signed in to change notification settings - Fork 101
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
svelte "support" lol #154
base: master
Are you sure you want to change the base?
svelte "support" lol #154
Conversation
I'm just playing around with it some more and even with this little code it's already crazy. Like, rendering Svelte inside ejs? WTF?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Page title</title>
</head>
<body>
<%- partial("_hello-world", {name: "Harp"}) %>
</body>
</html>
<script>
export let name;
export let current;
</script>
<h1>Hi {name} and ({current.source})</h1>
<style>
h1 {
color: red;
}
</style> I've missed Harp 😄 Let's go full circle: can I also include Jade inside Svelte? <script>
export let name;
export let current;
export let partial;
</script>
<h1>Hi {name} and ({current.source})</h1>
<div>{@html partial('_not-pug', {nested: "I'm not pug"})}</div>
<style>
h1 {
color: red;
}
</style>
h1 Jade says: #{nested} What a time to be alive. I hope I can infect you with Svelte 😏 I'll play with it some more and see what I come up with. There are some open question, e.g. importing Svelte inside Svelte currently doesn't have access to |
Wow. This is wild! Nice work. I'll circle back to you once I've had the opportunity to run it. |
I'll leave my notes here and let you know when something cool happens. So I've played with
So I'll go back to using Oh well, without registering the require hook importing other Svelte components won't work, e.g. |
nvm, requiring Svelte inside Svelte works now.
<script>
export let current;
import Nav from './_nav.svelte';
</script>
<Nav {current} />
<h1>Hello {current.source}</h1>
<style>
h1 {
color: red;
}
</style>
<script>
export let current;
</script>
<nav>
<ul>
<li>
<a href="/" class:active={current.source === 'index'}>Home</a>
</li>
<li>
<a href="/svelte" class:active={current.source === 'svelte'}>Svelte</a>
</li>
</ul>
</nav>
<style>
nav {
background: yellow;
}
ul {
list-style: none;
}
.active {
font-weight: bold;
}
</style> output with scoped styles <nav class="svelte-1y9xqmb"><ul class="svelte-1y9xqmb"><li><a href="/" class="svelte-1y9xqmb">Home</a></li>
<li><a href="/svelte" class="svelte-1y9xqmb active">Svelte</a></li></ul>
</nav>
<h1 class="svelte-1tb9iu1">Hello svelte</h1><style>h1.svelte-1tb9iu1{color:red}
nav.svelte-1y9xqmb{background:yellow}ul.svelte-1y9xqmb{list-style:none}.active.svelte-1y9xqmb{font-weight:bold}</style> |
Another thought: if a Svelte component uses Also BTW this is my vision for Harp and I hope you share it. For me Harp always "made sense". This is entirely subjective but I haven't seen anything that could replace it. The same goes for Svelte, once I started using it it just made sense, while React no longer makes sense to me at all. So my vision for Harp is to have the same static generator I've always loved, but then I can just sprinkle Svelte components in there and they just work. Nothing to set up. And they are generated in a way that they can even work without JavaScript or at least serve something useful initially. E.g. for a Google Maps integration it's already common to have a "Click here to active the evil Google scripts" overlay. This would be rendered in the static HTML already. And once hydrated the user can click it and the Svelte code takes over. BTW this works already with this PR (having installed
doctype html
html
head
meta(charset="utf-8")
meta(name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui")
body
h1 Some content
div!= partial("_map")
<script>
import { onMount } from 'svelte';
let container;
async function doTheEvil() {
const { Loader } = await import('@googlemaps/js-api-loader');
const loader = new Loader({
apiKey: "",
version: "weekly",
libraries: ["places"]
});
const mapOptions = {
center: {
lat: 0,
lng: 0
},
zoom: 4
};
const google = await loader.load();
const map = new google.maps.Map(container, mapOptions);
}
</script>
<div bind:this={container}>
<button on:click={doTheEvil}>Active the evil Google scripts</button>
</div>
<style>
button {
color: red;
}
</style> esbuild really changes the game |
Current progress (locally, uncommitted): client side scripts are now only generated when the component is marked as progressive via <script context="module">
export const progressive = true;
</script> This means by default Svelte only behaves like a templating language but you can opt into the magic. For progressive components you also won't be able to use Man this is fun. There's also an <script context="module">
export const progressive = true;
</script>
<script>
export let enhanced;
import { onMount } from 'svelte';
let container;
async function doTheEvil() {
const { Loader } = await import('@googlemaps/js-api-loader');
const loader = new Loader({
apiKey: "",
version: "weekly",
libraries: ["places"]
});
const mapOptions = {
center: {
lat: 0,
lng: 0
},
zoom: 4
};
const google = await loader.load();
const map = new google.maps.Map(container, mapOptions);
}
</script>
<div bind:this={container}>
<button type="button" on:click={doTheEvil} disabled={!enhanced}>
{#if enhanced}
Active the evil Google scripts
{:else}
You need JavaScript to use the evil Google scripts
{/if}
</button>
</div>
<style>
button {
color: red;
}
</style> |
…t I need to use async eslint for svelte
I'm done for today. I'm not sure what's missing exactly. For server rendering you can now use Svelte and also import One open problem: the client side bundle will contain the styles again, even though we already rendered them on the server. Need to figure out how to disable that properly. TODO:
|
I also added prettier and eslint because I just couldn't work without it. We can of course remove this from the PR in the future. But they are related to an open question: what about modern js? E.g. I've kept using |
I just ported my SvelteKit project over in about 20 minutes. What I learned:
Other than that it worked perfectly and is so much smoother and simpler than SvelteKit. Less files, no config. Nice. I'm sure there is more, but I'm tired. If you wonder |
scriptBlock = `<script>${clientScript}</script>`; | ||
} | ||
|
||
return `<div style="display: contents;">${rendered.html}</div>${scriptBlock}${styleBlock}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW this is probably still open to XSS because the devalue
above in the inline script will run through esbuild making it kind of pointless. Depending on what esbuild does this might re-enable </script>
inside any string. So either we need to replace that here or if we go 100% external scripts then no worries
Replace sync-rpc with https://github.com/un-ts/synckit |
@sintaxi do you have any plans to get back into Harp? I'd really love to create some static pages again and don't know of anything that comes close to Harp. And with Svelte support I'd be so happy. I think a logical step would be a rewrite of terraform/harp in ESM and also make the processors async, so that I can remove the esbuild hack (using a subprocess or Worker to make something async sync, because esbuild plugins cannot be sync). If I remember correctly an ESM rewrite would also make the Svelte compilation easier. |
Hi @Prinzhorn sorry for the delay. First of all thank you! You have done some really amazing work here. Im sorry for the lack of feedback. I think Harp is in a great position to take new direction and I really like your ideas. Harp wen't though a huge exorcism this past year and I'm happy with a lot of things regarding its current state. It's stable, small, and simple. I think what exists now could make a good I agree with you terraform likely needs and overhaul and a paradigm shift to ESM. You seem to have have a good grasp on its current limitations and it would be great to see what we can come up with together. |
Thanks!
Maybe the first step would be to migrate terraform to use eslint/prettier/esm/async/await without changing any functionality (not sure in what shape harp itself is). Then we could clean this Svelte PR up and maybe we're good for a first v1-rc1 and see how it goes? Depending on what else you have planned for esbuild, maybe we also need to find some common API that we can share between the Svelte support and other parts. But I think with SSR it's quite different from regular bundling where you want Harp to serve your entry point as a bundle. Oh that also reminds me that I wanted a way to inject CSS/JS into the head from within a transform. I guess that's something we need for JS bundling too, when using code splitting? Because you would no longer have a 1:1 relationship between the file you include and what you actually get served. Anyway, I'm getting side-tracked. I have other stuff on my mind right now and would need to sort my thoughts and get back into this PR. But feel free to ping me when you need some input. From the perspective of a Harp user all I really want is the Harp I used for the past >8 years but with Svelte support. I personally don't really need the plain JavaScript bundling support anymore (back then I was running Browserify in parallel to Harp), but I'm sure I will run into situations where I don't want to use Svelte. But it's hard to imagine honestly. Maybe for some really small stuff. It's just too easy to abstract your code in components. |
Looking at my wall of text, maybe you can formulate a road map? An updated version of sintaxi/harp#664 ? I'd be more than happy to comment on it when you draft something. |
I was just thinking if a template like Svelte can emit additional css/js, we need a special path prefix for them. Or else these would then cause another request to the transform pipeline. E.g. let's say Svelte emits an additional "components.106b693f.js" and we include it in the main template like this
Then loading this page would cause a request to But then when compiling (and not serving), these files will actually be copied to the dist folder and served without |
function init() { | ||
return function (options) { | ||
var plugin = sveltePlugin({ | ||
// TODO: This will cause CSS to be generated that we don't need (the server already served it). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Svelte just merged support for css: 'none'
sveltejs/svelte#7914
Listen, this "works" but I just wanted to get something working.
The following
index.svelte
works as expected:The amazing thing about having Svelte support in Harp (besides using Svelte syntax, duh) would be scoped CSS. None of the other template languages give you that. The generated HTML for the above is currently this
Two open questions, if we solve those we got ourselves the first Svelte iteration:
compile
call returns (among other things) the JavaScript code (a string) for a CJS module. So there must be a better way. There issvelte/register
, need to check how that works internally because it gives us the compiled component straight away.<style>
tag. It "works" but it would probably nicer to write out a CSS file? But that would need to make it's way into the main root HTML file's head. There is<svelte:head>
, need to look into that as wel.I also noticed your JSX "implementation" is copy and paste of EJS without editing it, I assume you didn't commit what you tried?
I tried working with SvelteKit and the adapter-static but I'm just not happy with it. I don't like the UX of a client side router (it feels like nothing is happening, the browser doesn't show any indication), I just want static HTML pages and I'm good. I'd even accept the inline
<style>
for now.Also the second iteration would obviously be to turn on hydration and see where that leads. Can literally spit out a inline
<script>
same way I'm doing with style for now.I do have a website completely done in SvelteKit that I'd love to migrate, so we have a real world test case already.