Can a Svelte component be embedded in a non-Svelte app?

Viewed 2898

I work in a group that has several projects, and each one is written in a different framework. We would like to have some self-contained widgets whose behavior and appearance are standard, but can be used in any of the systems. I thought Svelte sounded like a good option, because it doesn't require adding a framework on the front end. But I can't find anything that says Svelte is usable within other systems; it has to be an all-Svelte app to have Svelte components.

Is that correct? Or is there some way to embed a Svelte component into another system?

2 Answers

You can include a Svelte component anywhere as soon as you have the reference to the DOM element you want to append your Svelte component.

const container = document.querySelector('.container');

//MyComponent is the compiled component
new MyComponent({
  target : container
});

See the Svelte docs: https://svelte.dev/docs#run-time-client-side-component-api

But then you have some limitation on how you can handle the state if you have multiple components included like that.

If you want even wider compatibility and just include the component with a script tag, you can use the document.currentScript property and compile the Javascript into standalone script with rollup.js or webpack:

import MyComponent from './MyComponent.svelte';

var div = document.createElement('DIV');
var script = document.currentScript;
script.parentNode.insertBefore(div, script);

const myComponent = new MyComponent({
    target: div,
    props: { propname: 'some value' },
});

You can compile a nice package with rollup if you have rollup-plugin-svelte and @rollup/plugin-node-resolve packages installed into your project. Below is a suitable rollup.config.js for this, added further notes into comments:

import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';

export default {
    input: 'embed.js',
    output: {
        format: 'iife',
        file: 'dist.js',
    sourcemap: false,
    },
    plugins: [
        svelte({ emitCss: false, }),
        resolve({ browser: true, dedupe: ['svelte'] }),
    ],
}
Related