pimterry/server-components

Convert to Custom Elements spec V1

gilbert opened this issue · 3 comments

Since this area of development is greenfield, it would be good to future-proof from the start. I'm currently working on a V1 conversion based on polymer's polyfill.

The main issue I've run into so far is that there is no more createdCallback. Instead, a constructor is defined. The spect dictates that this constructor "must not gain any attributes or children". Currently server-components relies on createdCallback returning a promise if it needs to block rendering.

The spec suggests that "work should be deferred to connectedCallback as much as possible—especially work involving fetching resources or rendering." Do you think this would be an acceptable replacement to createdCallback? i.e. server-components relying on that callback to return a promise, if needed?

So upon completing the conversion, I realized there is some separation to do with respect to server-side vs client-side component rendering. We have these scenarios:

  1. Server-side only components. For example, a <new-relic> element in the layout page.
  2. Client-side only components. In other words, a component that server-components does not render, but does handle that component's asset dependencies.
  3. Pre-rendered components. A combination of the above; a component that does some work server-side, and leaves behind a component to be run on the client.

It just occurred to be that server-components will run a registered custom element server-side no matter what (# 3). A 3rd party package should be able to define one of the above 3 options, meaning that some code needs to be able to run in both the client or browser.

Ok, thanks for looking at this @mindeavor! Now that v1 has been accepted everywhere I'm definitely keen on including that as the standard here.

I think there's two issues that we're conflating slightly, and I'd like to solve them one at a time. First the move to v1, and second moving to a move substantial and thorough polyfill, rather than a home-grown solution.

Let's leave the polyfill for now (and track on #21), and move to v1 first.

I'm not sure why this move requires us to separate those three scenarios. I'd quite like a solution where we just don't care which of this is happening - the only difference we should need is to wait until a certain point before considering the result as 'rendered'. That's where the portability magic comes in.

I think doing that in the connectedCallback is fine, and fits nicely with the spirit of the spec. If you render an element with only a constructor, we consider it 'done' as soon as the constructor returns. If you render an element with a connectedCallback, we consider it done once we've called the connectedCallback, and it has either returned nothing or a promise that's been fulfilled.

Does that make sense? Is there anything that blocks this with that change alone?

If we're good to do that, I'd like to start by manually making the change in the existing quick implementation, along with tests to cover the essential behaviours, and then we can subsequently look at swapping out the implementation for a polyfill (and keep the tests passing en route).

I think the different scenarios I have in mind are actually a small (but useful!) extension to the original server-components vision; basically, components that are meant to run only on the server and never show up on the client. I will create an issue about and expand on this later.