Dynamically compile .svelte source code to a view (REPL-like component)
I'm building a REPL-like feature in my SvelteKit app, where users can input .svelte code, and it gets dynamically compiled and rendered.
<script lang="ts"> import { onMount } from 'svelte'; import { compile } from 'svelte/compiler'; export let code = ''; // The Svelte source code to compile and render let container: HTMLElement; // Target container for the dynamic component let componentInstance: any; onMount(() => { try { if (code) { // Compile the source code with the existing options const { js, css, warnings } = compile(code, { generate: 'client', runes: true }); console.log(js.code); console.log(css?.code); console.log(warnings); // Inject CSS into the document head if (css && css.code) { const style = document.createElement('style'); style.textContent = css.code; document.head.appendChild(style); } // Dynamically execute the compiled JavaScript code const ComponentConstructor = new Function(`${js.code}; return MyComponent;`)(); console.log(ComponentConstructor); // Render the compiled component into the container componentInstance = new ComponentConstructor({ target: container, }); } } catch (err) { console.error('Failed to compile or render Svelte source:', err); } return () => { // Cleanup the dynamically created component instance if (componentInstance) { componentInstance.$destroy(); } }; });</script><!-- Target container for dynamic component rendering --><div bind:this={container}></div>
I get this error:
[Error] Failed to compile or render Svelte source:
SyntaxError: Unexpected string literal"svelte/internal/disclose-version". import call expects one or twoarguments. — DynamicRenderer.svelte:3
And when I set the discloseVersion CompileOption to false I get an error saying can't import *.
Regarding security concerns I'm aware that I should use an iframe, but it still gives the same error.
I have also searched for svelte REPL code and found a video that suggest importing the compiled code and then using a web worker, however it was posted 4 years ago, so I'm not sure if it'll work.
Any ideas what I'm missing?