Skip to content

Instantly share code, notes, and snippets.

@enyo
Last active June 23, 2023 22:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save enyo/cf5e31d822338f979cb7a85b86a1a8fb to your computer and use it in GitHub Desktop.
Save enyo/cf5e31d822338f979cb7a85b86a1a8fb to your computer and use it in GitHub Desktop.
Svelte Web Components
import HeaderMenu from './lib/components/HeaderMenu.svelte'
import type { SvelteComponent } from 'svelte'
customElements.define(
// I recommend prefixing your custom elements, but for this example
// I'm keeping it simple.
'header-menu',
class extends HTMLElement {
_element: SvelteComponent;
constructor() {
super()
// Create the shadow root.
const shadowRoot = this.attachShadow({ mode: 'open' })
// Instantiate the Svelte Component
this._element = new HeaderMenu({
// Tell it that it lives in the shadow root
target: shadowRoot,
// Pass any props
props: {
// This is the place where you do any conversion between
// the native string attributes and the types you expect
// in your svelte components
items: this.getAttribute('items').split(','),
},
})
}
disconnectedCallback(): void {
// Destroy the Svelte component when this web component gets
// disconnected. If this web component is expected to be moved
// in the DOM, then you need to use `connectedCallback()` and
// set it up again if necessary.
this._element?.$destroy();
}
}
)
@vish01
Copy link

vish01 commented Apr 16, 2022

Is it possible to make these web components shareable via route API endpoint so another SvelteKit app can use it in it's DOM?

@elron
Copy link

elron commented Jun 23, 2023

when I try to use this, I get this browser error:

alert-this.customElement.js:1 Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
at new e (alert-this.customElement.js:1:3647)

I'm using sveltekit 4

this is my rollup.config.js file:

import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import terser from '@rollup/plugin-terser';
import svelte from 'rollup-plugin-svelte';
import sveltePreprocess from 'svelte-preprocess';

const production = !process.env.ROLLUP_WATCH;

export default {
	input: 'export.customElement.ts',
	output: {
		sourcemap: !production,
		format: 'iife',
		name: 'app2',
		// We output it to public. This way, our svelte kit
		// app will also host the web components.
		file: 'public/alert-this.customElement.js'
	},
	// Normal rollup svelte configuration. Nothing fancy
	// happening here.
	plugins: [
		typescript({
			tsconfig: false
		}),
		svelte({
			preprocess: sveltePreprocess({
				sourceMap: !production,
				postcss: true
			}),
			// We just make sure that no global CSS is injeced
			// into the page that imports this script.
			emitCss: false,
			compilerOptions: {
				dev: !production
			}
		}),
		resolve(),
		commonjs(),
		// Minify the production build (npm run build)
		production && terser()
	]
};

--- edit:

Found a solution

// replaced this:
// import typescript from '@rollup/plugin-typescript';
// with this:
import typescript from 'rollup-plugin-typescript2';

(https://github.com/ezolenko/rollup-plugin-typescript2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment