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

Opting for a smaller bundle size by treating dynamic strings as one unit #3760

Closed
carpben opened this issue Oct 21, 2019 · 2 comments
Closed
Labels
compiler Changes relating to the compiler feature request perf

Comments

@carpben
Copy link

carpben commented Oct 21, 2019

Describe the solution you'd like
Currently, for dynamic strings in an element, Svelte breaks the string into it's atomic parts (be it a static string or a variable), and treats each part separately. For a textual element (without other embeded elements in it), changing a part of a string in the element doesn't provide much performance value over changing the entire string. Therefor, perhaps it would be better to opt for bundle size, by treating such a string as one unit.

I'll try to demonstrate the idea with the reactive assignment example from the homepage.

<script>
	let count = 0;

	function handleClick() {
		count += 1;
	}
</script>

<button on:click={handleClick}>
	Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

Lets take a look at the create_fragment function in the compiled JS output.

   function create_fragment(ctx) {
	var button, t0, t1, t2, t3_value = ctx.count === 1 ? 'time' : 'times' + "", t3, dispose;

	return {
		c() {
			button = element("button");
			t0 = text("Clicked ");
			t1 = text(ctx.count);
			t2 = space();
			t3 = text(t3_value);
			dispose = listen(button, "click", ctx.handleClick);
		},

		m(target, anchor) {
			insert(target, button, anchor);
			append(button, t0);
			append(button, t1);
			append(button, t2);
			append(button, t3);
		},

		p(changed, ctx) {
			if (changed.count) {
				set_data(t1, ctx.count);
			}

  // ...
}

It creates various variables, and various operations, just to insert one dynamic string. The basic idea is to treat this string as one unit. Here is a draft of what this could look like.

function create_fragment(ctx) {
   	var button, dispose,
	d1 = (ctx)=>`count ${ctx.count} ${ctx.count === 1 ? 'time' : 'times' + ""}`

	return {
		c() {
			button = element("button");
			t0 = text(d1(ctx));
			dispose = listen(button, "click", ctx.handleClick);
		},

		m(target, anchor) {
			insert(target, button, anchor);
			append(button, t0);
		},

		p(changed, ctx) {
			if (changed.count) {
				set_data(t0, d1(ctx));
			}
		},
   //...
}

This reduces the js output of this component by 20% (from 1418 chars to 1144. )

How important is this feature to you?
I'm excited about Svelte, but new to the framework. I don't currently use it in production.

@benmccann
Copy link
Member

benmccann commented Feb 4, 2022

This is pretty similar to #3898 in a lot of ways though a slightly different solution that could be combined with it. I'd be curious to see some benchmark results to see if this still has value after #3898

@sveltejs sveltejs deleted a comment from stale bot Feb 5, 2022
@Rich-Harris
Copy link
Member

Svelte 5 takes this approach — closing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler Changes relating to the compiler feature request perf
Projects
None yet
Development

No branches or pull requests

6 participants