Last active
March 8, 2025 07:50
-
-
Save ryuheechul/8bfa44574e96a80fdda1c9de7bb1c57b to your computer and use it in GitHub Desktop.
Revisions
-
ryuheechul revised this gist
Mar 8, 2025 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -102,6 +102,8 @@ import Layout from '../layouts/Layout.astro'; </Layout> ``` _`<span>` above is not important but to demonstrate what I learned from https://blog.jim-nielsen.com/2023/html-web-components/._ #### But why client side `<script>` is required here? Why not just `import SvelteCounter from '../components/SvelteCounter.svelte';` at the top between `---` and `---`? -
ryuheechul revised this gist
Mar 8, 2025 . 1 changed file with 4 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -94,7 +94,10 @@ import Layout from '../layouts/Layout.astro'; <details open> <!-- ... --> <svelte-counter message="as custom element"> <!-- You can also (pre) render something before the custom element is rendered like this ... --> <span>initializing...</span> </svelte-counter> </details> </Layout> ``` -
ryuheechul revised this gist
Mar 8, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -153,7 +153,7 @@ import Layout from '../layouts/Layout.astro'; </Layout> ``` ### Svelte config (via astro.config.mjs) ```mjs // astro.config.mjs -
ryuheechul revised this gist
Mar 8, 2025 . 1 changed file with 11 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -20,23 +20,22 @@ There is a demo shows you the minimal code and working example of how to set up <svelte:options customElement={{ tag: "svelte-counter" }} /> <script> let count = $state(0); function handleClick() { count += 1; } let { message = 'default message' } = $props(); </script> <details open style="margin: 1rem;"> <summary> { message }: </summary> <button style="margin-left:1rem;" on:click={handleClick}> clicks: {count} </button> </details> ``` -
ryuheechul revised this gist
Mar 8, 2025 . 1 changed file with 7 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -142,7 +142,7 @@ import Layout from '../layouts/Layout.astro'; } </script> <details open> <!-- ... --> <div style="margin: 1rem;" x-data="{list:[randomAnimal()]}"> <button @click="list.push(randomAnimal())">click to add more</button> @@ -172,6 +172,12 @@ export default defineConfig({ }, }), ], // this section is not necessary but could be helpful to see authored source code with the production build (it's already available at development build though) vite: { build: { sourcemap: true, }, }, }); ``` -
ryuheechul revised this gist
Mar 8, 2025 . 1 changed file with 12 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -100,6 +100,18 @@ import Layout from '../layouts/Layout.astro'; </Layout> ``` #### But why client side `<script>` is required here? Why not just `import SvelteCounter from '../components/SvelteCounter.svelte';` at the top between `---` and `---`? Anything in between `---` and `---` at the top of `.astro` files is processed in compiling time. The code here will not be directly embeded into an html. In the case of `mixed.astro`, it was a happy coincedence that astro processed the svelte renderer when a svelte client island is hydrated which happens to run the code of registering the custom element as well as hydraing. If you simply import between `---` and `---` and not actually embed `<SvelteCounter>`, it is simply ignored. Adding `<script>import {} from '../components/SvelteCounter.svelte';</script>` will basically do a similar thing without hydrating since there is none to hydrate but to register a CE. Also this code runs as `type="module"` by default as that's how Astro works which means it's automatically `defer`ed. ### with AlpineJS This usage is why I was interested in utilizing Svelte's custom element compiling in the first place. -
ryuheechul revised this gist
Mar 8, 2025 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -89,7 +89,7 @@ import Layout from '../layouts/Layout.astro'; <Layout> <script> // unlike the case with ./mixed.astro, we will need to import this on the client side to register the custom element import {} from '../components/SvelteCounter.svelte'; </script> @@ -114,7 +114,7 @@ import Layout from '../layouts/Layout.astro'; <Layout> <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script> <script> // unlike the case with ./mixed.astro, we will need to import this on the client side to register the custom element import {} from '../components/SvelteCounter.svelte'; </script> -
ryuheechul created this gist
Mar 8, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,166 @@ # Svelte Custom Element on Astro There is a demo shows you the minimal code and working example of how to set up a astro project to make use of [Svelte compiles to Custom Element feature](https://svelte.dev/docs/svelte/custom-elements) at https://stackblitz.com/edit/svelte-ce-on-astro-demo?file=README.md. ## And here is the gist - Svelte allow you to compile its component to a custom element (aka Web Component) - https://svelte.dev/docs/svelte/custom-elements - Astro doesn't have a guide on how to do this but I figured out how to and thus the sharing - https://stackblitz.com/edit/svelte-ce-on-astro-demo?file=README.md ## Tour of the main code ### The component ```svelte <!-- SvelteCounter.svelte --> <!-- this one file transforms into a regular svelte component and a custom element thanks to the line below --> <svelte:options customElement={{ tag: "svelte-counter" }} /> <script> let count = $state(0); function handleClick() { count += 1; } let { message = 'default message' } = $props(); </script> <details open style="margin: 1rem;"> <summary> { message }: </summary> <button style="margin-left:1rem;" on:click={handleClick}> clicks: {count} </button> </details> ``` ### Good old Astro client island from a Svelte component ```astro --- // pages/regular.astro import Layout from '../layouts/Layout.astro'; import SvelteCounter from '../components/SvelteCounter.svelte'; --- <Layout> <details open> <!-- ... --> <SvelteCounter client:load message="regular hydration" /> </details> </Layout> ``` ### Mixed usage that lets you think it just works ```astro --- // pages/mixed.astro import Layout from '../layouts/Layout.astro'; import SvelteCounter from '../components/SvelteCounter.svelte'; --- <Layout> <SvelteCounter client:load message="regular hydration" /> <details open> <!-- ... --> <svelte-counter message="as custom element" /> </details> </Layout> ``` ### Standalone usage reveals the extra import required ```astro --- // pages/as-web-comp.astro import Layout from '../layouts/Layout.astro'; --- <Layout> <script> // unline the case with ./mixed.astro, we will need to import this on the client side to register the custom element import {} from '../components/SvelteCounter.svelte'; </script> <details open> <!-- ... --> <svelte-counter message="as custom element" /> </details> </Layout> ``` ### with AlpineJS This usage is why I was interested in utilizing Svelte's custom element compiling in the first place. ```astro --- // pages/with-alpine.astro import Layout from '../layouts/Layout.astro'; --- <Layout> <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script> <script> // unline the case with ./mixed.astro, we will need to import this on the client side to register the custom element import {} from '../components/SvelteCounter.svelte'; </script> <script is:inline> const animals = ["pig", "cow", "lion", "elephant"]; function getRandomInt(max) { return Math.floor(Math.random() * max); } function randomAnimal() { return animals[getRandomInt(animals.length)]; } </script> <details open>> <!-- ... --> <div style="margin: 1rem;" x-data="{list:[randomAnimal()]}"> <button @click="list.push(randomAnimal())">click to add more</button> <template x-for="(item, i) in list"> <svelte-counter x-bind:message="'' + (i+1) + '-' + item" /> </template> </div> </details> </Layout> ``` ### Svelte config ```mjs // astro.config.mjs // @ts-check import { defineConfig } from 'astro/config'; import svelte from '@astrojs/svelte'; // https://astro.build/config export default defineConfig({ integrations: [ svelte({ compilerOptions: { customElement: true, // this is the one that what should tell Svelte to compile components to CEs }, }), ], }); ``` There are a bit more code you can take a look and also get to interact with the demo at https://stackblitz.com/edit/svelte-ce-on-astro-demo?file=README.md.