-
Notifications
You must be signed in to change notification settings - Fork 180
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
Relationship to Lit / Polymer? #439
Comments
@dakom the two are rather difficult to compare, because they are so different in their approach.
now, in contrast,
Honestly, where bottlenecks are concerned, I would imagine Soy/idom not to be one of them. It is a small, tuned package driven by a compiler, so, it really depends how your templates use it. I would expect idom to be more performance out of the box compared to Shadow DOM, though, because there is much less overhead to render the same thing. Hope this helps. FWIW we absolutely love idom. If you are performance-oriented, you won't be disappointed. But prepare yourself for some real tooling challenges. |
Thanks - great breakdown! Though I'm still not totally clear on the comparison to lit-html (as opposed to lit-element). For example let's say we re-render the entire page every tick. My understanding is that lit-html will also only make updates to the parts that changed, without vdom diffing... so it sounds similar to idom, but I'm sure there is some major difference I don't quite see yet... |
AFAIK because for example, a html`<div id='some-id' class='some class list here'><b>${salutation}</b></div>` that's leveraging JS template tags to interpret and construct the template. idom also operates in JS, so they both incur the JS overhead, but a compiled idom template looks more like this:
the template has been serialized by idom into direct instructions, rather than needing to assemble those instructions when |
@dakom ive borrowed from our /**
* @param {!incrementaldomlib.IncrementalDomRenderer} idomRenderer
* @param {!$noticeDialog.Params} opt_data
* @param {?goog.soy.IjData=} opt_ijData
* @return {void}
* @suppress {checkTypes}
*/
var $noticeDialog = function(idomRenderer, opt_data, opt_ijData) {
/** @type {string} */
var title = soy.asserts.assertType(goog.isString(opt_data.title), 'title', opt_data.title, 'string');
/** @type {null|string|undefined} */
var message = soy.asserts.assertType(opt_data.message == null || goog.isString(opt_data.message), 'message', opt_data.message, 'null|string|undefined');
/** @type {!goog.soy.data.SanitizedHtml|!google3.javascript.template.soy.element_lib_idom.IdomFunction|function(!incrementaldomlib.IncrementalDomRenderer): undefined|null|undefined} */
var content = soy.asserts.assertType(opt_data.content == null || (goog.module.get('google3.javascript.template.soy.soyutils_directives').$$isIdomFunctionType(opt_data.content, SanitizedContentKind.HTML) || opt_data.content instanceof goog.soy.data.SanitizedContent), 'content', opt_data.content, '!goog.soy.data.SanitizedHtml|!google3.javascript.template.soy.element_lib_idom.IdomFunction|function(!incrementaldomlib.IncrementalDomRenderer): undefined|null|undefined');
/** @type {!goog.soy.data.SanitizedHtml|!google3.javascript.template.soy.element_lib_idom.IdomFunction|function(!incrementaldomlib.IncrementalDomRenderer): undefined|null|undefined} */
var actions = soy.asserts.assertType(opt_data.actions == null || (goog.module.get('google3.javascript.template.soy.soyutils_directives').$$isIdomFunctionType(opt_data.actions, SanitizedContentKind.HTML) || opt_data.actions instanceof goog.soy.data.SanitizedContent), 'actions', opt_data.actions, '!goog.soy.data.SanitizedHtml|!google3.javascript.template.soy.element_lib_idom.IdomFunction|function(!incrementaldomlib.IncrementalDomRenderer): undefined|null|undefined');
/** @type {boolean|null|undefined} */
var selectableText = soy.asserts.assertType(opt_data.selectableText == null || (goog.isBoolean(opt_data.selectableText) || opt_data.selectableText === 1 || opt_data.selectableText === 0), 'selectableText', opt_data.selectableText, 'boolean|null|undefined');
idomRenderer.elementOpenStart('div', xid('bloombox.ui.base.notice.noticeDialog-0'), $noticeDialog_statics_0 || ($noticeDialog_statics_0 = ['class', goog.getCssName('mdl-card') + ' ' + goog.getCssName('mdl-shadow--2dp')]));
if (goog.DEBUG && soy.$$debugSoyTemplateInfo) {
idomRenderer.attr('data-debug-soy', 'bloombox.ui.base.notice.noticeDialog bloombox/ui/templates/base/notice.soy:16');
}
idomRenderer.elementOpenEnd();
idomRenderer.elementOpen('div', xid('bloombox.ui.base.notice.noticeDialog-1'), $noticeDialog_statics_1 || ($noticeDialog_statics_1 = ['class', goog.getCssName('mdl-card__title') + ' ' + goog.getCssName('no-select')]));
idomRenderer.elementOpen('h2', xid('bloombox.ui.base.notice.noticeDialog-2'), $noticeDialog_statics_2 || ($noticeDialog_statics_2 = ['class', '' + (goog.getCssName('mdl-card__title-text'))]));
// ...
} when compiled with Closure Compiler, the above is very tightly optimized. here's an example of the final, non-debug output: so, i guess, if you hate shipping string templates to be interpreted at runtime, Soy is your solution. |
With Incremental DOM, you still need to walk through everything to see what changed. The DOM updates are only applied where things are changed, but it still needs to take all the data in, walk the DOM nodes and check if things changed one by one. My understanding of lit-html is that it looks at the data, sees what changed, and then applies each change to the appropriate place in the DOM, without walking the tree. To do this, it does a bit of work the first time it renders something to map where things need to go. I think as far as update speed, that probably isn't too much of a difference. There is a minor difference where Incremental DOM prefers to optimize performance for the worst case (rendering something new from scratch) and lit-html prefers to optimize for best case (doing a single, small update). I think the bigger differences are in the different aims of the projects and how the influences the different models. Incremental DOM is more focused on supporting a template compilation which is useful for server-side rendering (as @sgammon mentioned) which can be a very large performance improvement. The model of how things work (e.g. how you can do control flow with if-statements) is very much suited for that, especially for Closure Templates aka Soy. Depending on the scale you are operating at, there are other things to consider, such as message translations, which Closure Templates supports. By breaking things up into instructions as Incremental DOM does, you can handle such translated strings in a first class way when doing rendering. For example, you might have some content like: <a href="example.com/learn-more.html">Learn more</a> about our thing. In general, for these kinds of things you cannot split this up into two separate strings for localization since you need the whole sentence to make sense and be localized as a unit. Other approaches usually require you to insert the translated strings using |
It seems to me that lit-html (or lit-element, polymer, etc.) Are addressing roughly the same space.
Can someone please summarize the difference in terms of performance?
(I get that it's a different API, more thinking about raw bottleneck issues.)
Thanks!
The text was updated successfully, but these errors were encountered: