mediamonks / muban-core

The core library and webpack loaders for Muban
MIT License
0 stars 2 forks source link

Facilitate working with the component tree #31

Open skulptur opened 4 years ago

skulptur commented 4 years ago

Components form a tree structure and that should be more deeply explored by the component API.

Some ideas:

This could have a large impact on the API and how we declare and use muban components.

ThaNarie commented 4 years ago

This could have a large impact on the API and how we declare and use muban components.

Indeed, currently components are pretty isolated. It would be good to identify issues that we currently have around this topic (that will be solved by this new approach), or which opportunities these new changes create.

It's fun to create something better, but if it doesn't solve any actual problems, the added complexity might be something to think about :)

Since this ticket is more about the overal concept, I won't go deep into each bullet point. I will go into them lightly to get an idea about the potential changes.

Ideas:

We could make the components reactive/declarative

How would you see that happening? Could you give an example?

Automatically dispose children when parents are disposed.

Disposal normally happens through the cleanElements function, which already clears everything.

DOM addition/removal (initComponents / cleanElements) rarely happens in static projects (afaik), but I'm not against improving this.

It's just that calling dispose on a component doesn't mean the HTML is going to be removed, or that child components should also be disposed/removed? ONLY when a class is created from within a component, should it be the responsibility of the component to clean that up. But "child components" are created from the HTML, and the nesting is mostly coincidental.

Make direct child components available to parents by default.

This should be fairly simple, since component initialisation happens bottom-up, everything is already available in the constructor. We just need to think of how we want to expose them (ideally grouped/namespaced under a specific property).

We just need to think about updating this when child components are added or removed, how we "notify" the parent.

skulptur commented 4 years ago

I've been looking at older libraries/frameworks such as backbone, and reading its docs I think many of the assumptions made there are still largely valid today. https://backbonejs.org/#Getting-started.

It's all too easy to create JavaScript applications that end up as tangled piles of jQuery selectors and callbacks, all trying frantically to keep data in sync between the HTML UI, your JavaScript logic, and the database on your server. For rich client-side applications, a more structured approach is often helpful.

That's exactly what we do, except the jquery part. I agree with you that we should work focused on the actual use-case problems, and I think backbone's docs already do a great job at explaining what some of the issues are.

However with backbone, if I understand correctly, we ultimately end up with a subscription graph. Looking at it from the future, we have learnt from the ideas popularized by React that top-down the tree via props and bottom-up via callbacks makes things a lot easier to reason about. https://reactjs.org/docs/thinking-in-react.html

One of the many great parts of React is how it makes you think about apps as you build them.

As to not reinvent the wheel, I am again looking into other projects that take a framework that already follows those principles and applies to a server side rendering context. Gatsby comes to mind. However Gatsby does not deal with CMS rendering engines like we currently do and instead works with headless CMSs (or any other source of data).

In contrast, it seems that one of the core premises of Muban is that the HTML is out of our control and we have to deal with what is served. For example, components could be wrapped in extra divs. Attributes might be added on the CMS only and we should not care. Blocks can be rendered in any order on the page. And we don't have access to the data that caused the template to be rendered in that particular way. So we're left with sprinkling imperative code on top of what we got and hope for the best.

That is a big issue, as the HTML that is served might be incompatible with what the runtime expects, and we perform 0 validation. Errors will happen only in the CMS environments, and not locally. #24 is an example on why we need to validate, but an element not being there is only one many things that can go wrong.

In Muban we do write the templates, so we do have the knowledge of what their structure should be, therefore we should be able to validate the whole component markup and also collect information back. I believe you looked into the issue before, and I think theoretically we would be able to generate that code automatically.

Those things would impact what the component API looks like and how we can take more advantage of the tree structure. I know that we discussed aspects of this before, but I wanna come down with the most basic requirements before reinventing the wheel:

  1. Is it really true that the HTML is out of our control or could we close the cycle like Gatsby does with its build system and its runtime library?
  2. Do we really want to keep working around CMSs render engines? That is the biggest annoyance and all leading CMS products such as Drupal, WordPress, AEM and Sitecore, Kentico and others can also work in a “headless” mode.. Gatsby or similar would solve our needs if we do not have that requirement.
  3. If we are indeed stuck with number 2, what constraints can we impose on what can/can't differ between frontend templates and CMS generated HTML?
ThaNarie commented 4 years ago

Funny you ask; the only reason muban exists is for those reasons; Make JS+CSS easier for CSM rendered HTML, by making development and integration as easy as possible.

All things you mentioned above (backbone, react, gatsby, headless, etc) don't need muban, they are their own solution for a different problem. Muban is used where those other/existing solutions can't.

The most bare-bones solution for muban is to only write js+css, while doing all the HTML templating in the CMS directly. This is what the core should support. The template/hbs setup is only added for some additional use cases; developing templates when we need to handover HTML to 3rd party developers who pick up the CMS work, or to start local development when the CMS part is not yet ready.

How we solve that JS/CSS part is totally open, as long as it satisfies the above.

Is it really true that the HTML is out of our control?

Depends on how you look at it. We are free to change the CMS templates, so we are in control of those. But not from within JavaScript.

differ between frontend templates and CMS generated HTML

I think it would be clear what you exactly mean by "frontend templates". Are those the development templates (.hbs) that are later converted into CMS templates? Or are that FE-only templates that become part of the JS build for HTML that is never rendered by the CMS?

skulptur commented 4 years ago

Yeah I meant .hbs files.

For example when we start throwing errors for missing elements via this.getElement, that's a constraint we'll be enforcing on the markup rendered by the CMS.

If we were to enforce that the whole markup was the exact same per block/component (hbs vs CMS rendered), would that be violating any common scenarios?

ThaNarie commented 4 years ago

The goal is to have hbs and cms templates 100% equal, at least for the parts that matter.

CMS might add a div here and there around some components, which should be okay as long as it's not breaking anything. And if CMS template changes break something, those changes should be made in the hbs files as well, and the code should be changed to take that into account. If this becomes too much work, remove the hbs template and start developing directly against your CMS templates.

It shouldn't matter if you're rendering local hbs or cms templates, it should all work.

So if an element is required, it should be there in both versions. If it's optional, it can be omitted in both versions.