Making web components in svelte 4
23 Jan 2024I came across this BBC article where they have a scrolly inside a webpage and looking through the DOM, they are using a <template>
and using the template as a web-component which then inserts stuff onto a shadow-root. Here’s a good MDN article about templates and slots. I first heard about web-components when datawrapper said they had a new way of embedding charts using web-components.
When we tried to do a scrolly embedded in an article using an iframe, the page and iframe scrolly separately so was a bit janky and quite an unsatisfying experience. Since we use Svelte as our main framework, I did some exploring and found Svelte can compile components to web components.
There is a way of using the old svelte template and rollup to generate web-components that can be imported as standalone .js files (See phptuts or logrocket for a walkthrough) but this version uses vite and svelte 4.
The how
Svelte can set up projects to be like a component library using npm create svelte@latest
and this is the recommended way from comments.
For library projects, your interesting stuff is in lib
and then how it works is in routes
. I’ve created a svelte component inside lib
and added this line to the to the .svelte file.
<svelte:options customElement="count-er>
Also added compilerOptions
to svelte.config.js
compilerOptions:{customElement:true}
When you run npm run package
, this creates files in a dist
folder.
Following instructions from this recipe you can run vite again on the dist/index.js
to create the standalone iife .js files. See the vite.webcomponents.config.js
and the modified build
command in the package.json file. These standalone files can be then loaded from a webpage and then the web-component can be used. See the test-page
folder for an example.
You may also need to edit the index.js
in the dist
folder so that it has a default export rather than just the svelte component, e.g. export { default as Counter } from './Counter/Counter.svelte';
.
The finished result
Here’s my github repo for svelte 4 web components. I used this template as a good starting point and followed this recipe which I found from a stackoverflow answer.