I have a SvelteKit 2/Svelte 5 app with out-of-the-box configuration - what you get by running npx sv create my-app
. I want to build my app normally with adapter-node
, but I also want to build a single .svelte file as a web component that I can reuse in other projects.
Currently my setup is this:
// $lib/widget/MyComponent.svelte<svelte:options customElement={{ tag: 'my-component', }}/><script lang="ts"> let counter = $state(0)</script><button onclick={() => (counter += 1)}> Clicked {counter} times</button>
// svelte.config.jsimport { mdsvex } from 'mdsvex'import adapter from '@sveltejs/adapter-node'import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'const config = { preprocess: [vitePreprocess(), mdsvex()], kit: { adapter: adapter(), }, extensions: ['.svelte', '.svx'],}export default config
// vite.widget.config.tsimport { svelte } from '@sveltejs/vite-plugin-svelte'export default { build: { lib: { entry: 'src/lib/widget/MyComponent.svelte', name: 'MyComponent', fileName: (format) => `my-component.${format}.js`, formats: ['es'], }, rollupOptions: { external: ['svelte'], output: { globals: { svelte: 'svelte', }, }, }, sourcemap: 'inline', }, plugins: [ svelte({ compilerOptions: { customElement: true, }, }), ],}
vite build --config vite.widget.config.ts
<!-- root/my-component.html --><my-component></my-component><script src="./dist/my-component.es.js" type="module"></script>
It works, but I'm not sure if this is the correct way to do it.
I'm getting a warning in my .svelte file that I haven't specified customElement: true
, but that's because I have my compiler options in vite.widget.config.ts
.
I tried looking at the svelte/compiler docs, but I couldn't understand how I'm supposed to use that module.
Any tips are welcome!