salesforce / lwc

⚡️ LWC - A Blazing Fast, Enterprise-Grade Web Components Foundation
https://lwc.dev
Other
1.62k stars 394 forks source link

Create components programmatically by tag name #914

Open priandsf opened 5 years ago

priandsf commented 5 years ago

SSR There should be a method to retrieve the component constructor based on a tag name. This is used by the client hydration when the VDOM is constructed from of the actual DOM. This is also used by the SSR engine to render a markup fragment, made of an hierarchy of elements including LWC components, without going through a compilation step (for example, markup code generated by a UI builder). The browser custom element registry could be used, but it requires the components to be exposed as custom elements. The StencilJS compiler, as an example, generates a defineCustomElements(window) function that registers the components.

caridy commented 5 years ago

hmm, there are few concepts mixed together here. The server produces a DOM structure, that DOM structure is sorta flatten, it doesn't have the boundaries or anything.

then there is the rehydration process, which assumes (today) that there is nothing there, and they all most be created from scratch, which is the part to be changed. In this particular case, we want to be able to say: for this component that I'm about to create, I have it already from the server, go and use it with this properties. This is the key, the initialization process is the same whether you have the DOM from server or not, and the missing piece here is how to tell the engine that there is a DOM structure at its disposal so it don't have to recreate all those elements, instead, find them from the DOM.

For that, I don't think such mapping is needed, instead, once we have a children collection (in a vnode), you should have almost the same exact elements in the DOM, it is a matter of matching them to fulfill the .elm property of each vnode from the children collection before going into the diff algo. This should be doable without any extra information, the only thing we need to add into the DOM is the internal key used for that vnode in the generated DOM from the server so we can use that to map the element to the corresponding vnode from children before applying the diffing.

priandsf commented 5 years ago

Right, there are different concepts mixed here.

There are other use cases, like server side mail templating or builder generated markup.

tedconn commented 5 years ago

@caridy can you create an SSR tag/label to tag all these SSR related issues?

caridy commented 5 years ago

@tedconn created!

pmdartus commented 5 years ago
  • Server side rendering This is where is it actually used, as SSR not only applies to a component, but actually to a piece of markup (render('<c-a><c-b></c-b></c-a>')). So while it is parsing the markup, it needs to create the component based on their tag name. A compilation step could solve the issue, but as this markup can be dynamic (ex: content slot), this could be inefficient and hard to cache.

I don't think the API to render component on the server would allow to take an HTML fragment. I would prefer an api equivalent to the the current createElement(<tag name>, { is: <component constructor> }) api that we have in the @lwc/engine. For example something like:

import { createElement, renderToString } from '@lwc/ssr';
import App from 'c/App';

const el = createElement('my-app', { is: App });
const html = renderToString(el);

Here are couple of concern that I have with a fragment approach: