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();
}
}
)
@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