Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$$slots empty when using custom elements in raw HTML #7599

Closed
MilesWellsSVT opened this issue Jun 10, 2022 · 3 comments
Closed

$$slots empty when using custom elements in raw HTML #7599

MilesWellsSVT opened this issue Jun 10, 2022 · 3 comments

Comments

@MilesWellsSVT
Copy link

MilesWellsSVT commented Jun 10, 2022

Describe the bug

This has been an issue before: 5594, 6165.

$$slots is an empty object when using custom elements in plain HTML. Using the custom element in a Svelte app results in the correct behavior.

Reproduction

<svelte:options tag="c-input" />

<script>
	console.log($$slots);
</script>

<div>
	<label for="theInput"><slot /></label>
	<input id="theInput" />
	{#if $$slots.description}
		<div class="description">
			<slot name="description" />
		</div>
	{/if}
</div>

Compiled using Rollup into dist/main.js then used in a static HTML file:

<!DOCTYPE html>
<html>
	<head>
		<script src="dist/main.js"></script>
	</head>
	<body>
		<c-input>
			Test label
			<span slot="description">Test</span>
		</c-input>
	</body>
</html>

Console output: Object { }

You can see in the image below the description slot is missing due to the conditional rendering even though the slot is provided in the usage:

image

You can create a new Svelte app and utilize the custom element there and you'll get the correct output:

// In SvelteKit: src/routes/index.svelte
<c-input>
	Test label
	<span slot="description">Test</span>
</c-input>

Console output: Object { default: true, description: true }

description slot appears correctly:

image

Finally, here's the Rollup config:

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

const isDev = process.env.ROLLUP_WATCH !== undefined;

export default {
	input: 'src/main.ts', // simple TS file where svelte components are re-exported
	output: {
		sourcemap: isDev,
		format: 'iife',
		name: 'bundle',
		dir: 'dist',
	},
	plugins: [
		svelte({
			preprocess: sveltePreprocess(),
			compilerOptions: {
				dev: isDev,
				customElement: true,
			},
		}),
		resolve({
			browser: true,
			dedupe: ['svelte'],
		}),
		commonjs(),
		terser(),
	],
	watch: {
		clearScreen: false,
	},
};

Logs

No response

System Info

System:
    OS: macOS 12.4
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 17.04 MB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 8.5.0 - ~/.nvm/versions/node/v16.14.2/bin/npm
  Browsers:
    Chrome: 102.0.5005.61
    Edge: 102.0.1245.39
    Firefox: 101.0.1
    Safari: 15.5
  npmPackages:
    svelte: ^3.44.0 => 3.48.0

Severity

annoyance

Since my organization consumes custom elements in Svelte apps this isn't a huge issue. However, we use raw HTML Storybook to test and document our custom elements so the behavior is not ideal.

@MilesWells
Copy link

MilesWells commented Jun 26, 2022

Reproduction repo

I tried rooting around in the compiler source and tests. I don't understand why this doesn't work but the code in the tests does.

@tytusplanck-8451
Copy link

I'm running into this issue as well.

@MilesWellsSVT
Copy link
Author

MilesWellsSVT commented Jul 13, 2022

I've found that adding defer to script tags solves this issue. In the reproduction repo above, simply add defer to the script tag.

In my case for Storybook I removed my import '../dist/main line from .storybook/preview.js and added a script tag to .storybook/preview-head.html:

<script defer src="main.js"></script>

I also had to update .storybook/main.js to serve my ./dist directory:

module.exports = {
   staticDirs: ['../dist'],
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants