Skip to content

Svelte 5: {#if} blocks are not tree shaken... shook? #12833

Closed
@brunnerh

Description

@brunnerh

Describe the bug

It can be useful to have parts of a component only render during development, this can be achieved via build-time constants or e.g. SvelteKit's static env variable replacement.

Unfortunately, the structure of Svelte 5's output prevents tools like Rollup from making these optimizations.
This leads to unnecessary code being included in the production build and potentially private internals being leaked.

Reproduction

<script>
	import DebugTools from './DebugTools.svelte';
</script>

Visible text

{#if false}
	DEBUG MODE
	<DebugTools />
{/if}
<!-- DebugTools.svelte -->
[Debug Tools]

Svelte 4

Probably relevant optimizable output:

let if_block = false && create_if_block(ctx);

Rollup output contains neither inline text content nor the import of the debug tools component.

Code
import { SvelteComponent, init, safe_not_equal, text, empty, insert, noop, transition_in, transition_out, detach } from 'svelte/internal';
import 'svelte/internal/disclose-version';

/* App.svelte generated by Svelte v4.2.18 */

function create_fragment(ctx) {
	let t;
	let if_block_anchor;
	let current;
	let if_block = false;

	return {
		c() {
			t = text("Visible text\n\n");
			if_block_anchor = empty();
		},
		m(target, anchor) {
			insert(target, t, anchor);
			insert(target, if_block_anchor, anchor);
			current = true;
		},
		p: noop,
		i(local) {
			if (current) return;
			transition_in(if_block);
			current = true;
		},
		o(local) {
			transition_out(if_block);
			current = false;
		},
		d(detaching) {
			if (detaching) {
				detach(t);
				detach(if_block_anchor);
			}
		}
	};
}

class App extends SvelteComponent {
	constructor(options) {
		super();
		init(this, options, null, create_fragment, safe_not_equal, {});
	}
}

export { App as default };

Rollup REPL

Svelte 5

Probably relevant unoptimizable output:

$.if(node, () => false, ($$anchor) => { ... }

REPL

Rollup output contains both text content and the import (inlined).

Code
import * as $ from 'svelte/internal/client';

var root$1 = $.template(`[Debug Tools]`, 1);

function DebugTools($$anchor) {
	$.next();

	var fragment = root$1();

	$.append($$anchor, fragment);
}

var root_1 = $.template(`DEBUG MODE <!>`, 1);
var root = $.template(`Visible text <!>`, 1);

function App($$anchor) {
	$.next();

	var fragment = root();
	var node = $.sibling($.first_child(fragment, true));

	$.if(node, () => false, ($$anchor) => {
		var fragment_1 = root_1();
		var node_1 = $.sibling($.first_child(fragment_1, true));

		DebugTools(node_1);
		$.append($$anchor, fragment_1);
	});

	$.append($$anchor, fragment);
}

export { App as default };

Rollup REPL

Logs

No response

System Info

REPL / 5.0.0-next.220

Severity

annoyance

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions