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

Question: How does Svelte scale to many components? #203

Closed
ccnokes opened this issue Dec 16, 2016 · 3 comments
Closed

Question: How does Svelte scale to many components? #203

ccnokes opened this issue Dec 16, 2016 · 3 comments

Comments

@ccnokes
Copy link

ccnokes commented Dec 16, 2016

This is just a question, but I figured it was the best place to ask (if not, let me know and I'll ask there and we can close this).

I couldn't find anywhere that addressed this, so: How does Svelte scale to many components while keeping the bundle size manageable? For example, in this starter example's (https://github.com/charpeni/svelte-example) compiled output I see this function repeated 4 times verbatim:

	function dispatchObservers ( group, newState, oldState ) {
		for ( var key in group ) {
			if ( !( key in newState ) ) continue;

			var newValue = newState[ key ];
			var oldValue = oldState[ key ];

			if ( newValue === oldValue && typeof newValue !== 'object' ) continue;

			var callbacks = group[ key ];
			if ( !callbacks ) continue;

			for ( var i = 0; i < callbacks.length; i += 1 ) {
				var callback = callbacks[i];
				if ( callback.__calling ) continue;

				callback.__calling = true;
				callback.call( component, newValue, oldValue );
				callback.__calling = false;
			}
		}
	}

If you have hundreds of components in a medium to large app, you'll hit a point where your app's bundle size now greater than what it would have been with a heavier UI framework like React, ng2, etc. However, it seems like this could be DRYed out somehow by the compiler so that repeated generic functions/classes are defined once and reused.

Maybe I'm missing something though, so I thought I'd ask 😸 . I'm not trying to criticize, I just want to know if that's something that's going to be addressed, or maybe this is actually desirable?

Svelte is a really cool idea, nice work 😄.

@Rich-Harris
Copy link
Member

Perfectly fair question! The initial focus was on creating completely self-contained components and figuring out how to do all the finicky code generation without worrying about all the headaches involved in deduplicating code. It's a good discipline, because it means you can't get lazy about adding non-essential stuff – that's important because it makes it possible for components to be shipped, pre-compiled, as standalone packages.

But the plan has always been to support deduplication as well. It's not just good for bundle size, it's actually good for performance as well, because if you can reuse functions they'll take up less memory and get optimised faster.

The basic idea is that the base code for a component will look something like this...

function MyComponent ( options ) {
  options = options || {};
  this.root = options.root;
  this.yield = options.yield;

  // book-keeping
  this._state = options.data || {};
  this._observers = { pre: Object.create( null ), post: Object.create( null ) };
  this._callbacks = Object.create( null );

  // API
  this.fire = fire;
  this.get = get;
  this.observe = observe;
  this.on = on;
  this.set = set;
  this.teardown = teardown;

  this._mount = _mount;

  this.mainFragment = renderMainFragment( state, this );
  if ( options.target ) this._mount( options.target );
}

...then in standalone mode you'd get this...

function fire ( eventName, data ) {
  var handlers = eventName in this._callbacks && this._callbacks[ eventName ].slice();
  if ( !handlers ) return;

  for ( var i = 0; i < handlers.length; i += 1 ) {
    handlers[i].call( this, data );
  }
}

// ... and so on

...whereas in non-standalone mode you'd get this:

import { fire, get, observe, on, set, teardown, _mount } from 'svelte/helpers/methods';

From there it would be relatively straightforward for a bundler like Rollup or Webpack to generate a compact bundle even with many components, and without you having to add any configuration.

(Reusable components could be distributed in both source and compiled form – a consumer of the component who wasn't using Svelte would use the regular pkg.main compiled build, whereas a Svelte user with a build tool set up could conceivably take advantage of deduplication by importing the source directly, again without any configuration. There's some nuance around versioning etc that we'd need to figure out though.)

I'll close this issue as it's sort of a duplicate of #9, but thanks for prodding me into fleshing this out into a proper answer!

@VenugopalanG
Copy link

Hi Rich,

Has this been addressed in Svelte 3?
Can we do the non-standalone mode described above?

(Sorry for being lazy and not looking at Svelte 3 to check. Thought of also asking here for the benefit of other possible lazy (or time squeezed) fellows like me. Helps if this answer/update is in the same thread when one is on a exploration mode)

Thanks.

@PatrickG
Copy link
Member

#2546

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

4 participants