google / mesop

Build delightful web apps quickly in Python
https://google.github.io/mesop/
Apache License 2.0
4.31k stars 192 forks source link

Support custom web components #95

Closed wwwillchen closed 2 weeks ago

wwwillchen commented 3 months ago

Updated: Proposal doc for supporting custom web components - please leave any feedback either on the doc or on this thread. Thanks!

wwwillchen commented 2 months ago

Prior art:

Streamlit:

Gradio:

justinfagnani commented 1 month ago

BTW, you could just support native web components directly / only and then let Angular (as well as other frameworks) be used via Angular Elements or other web components wrappers / compilers.

There's already a Material 3 web components reference implementation by the Material team here: https://github.com/material-components/material-web

One of the benefits is that you don't have to worry about compilers and syncing framework versions across components, because web components generally are bring-your-own-dependency. You could have multiple versions of Lit, Client-only-Wiz, Angular, etc., on a page (assuming the framework allows. Angular could be a complication here, but won't interfere with other frameworks).

wwwillchen commented 1 month ago

@justinfagnani yeah, good points. I think supporting custom native web components definitely has some merits, especially by being framework agnostic. The part that's not clear to me is how the various frameworks (e.g. React and Angular) support "compiling" their components into custom native web components.

For example, based on my understanding for Angular Elements, it sounds like each time you compile an Angular component into a standalone Angular Element, it's also packing in the core Angular framework runtime. Imagine there's Mesop custom component A from 1 developer and Mesop custom component B from another developer, can these custom components be independently compiled? I think the Angular model (but I could be wrong) is that this would become tricky because it wants to compile all of its components in a single pass. In which case, supporting custom Angular components would involve bringing in the Angular compiler toolchain into Mesop's python package.

How does multiple versions of Lit on the same page work? Does each custom element pack its own Lit runtime? For example, if there's 10 different native custom components, is this loading Lit runtime 10 times?

justinfagnani commented 1 month ago

For Lit, whether or not the Lit libraries are included with elements is entirely dependent on how that element is bundled (or not) and distributed.

Lit is just a library, typically distributed via npm. If multiple elements declare a dependency on the lit package, and are installed into one project with a shared node_modules folder, then they all could share the same copy of lit, just like with any other npm package.

But if the elements are bundled and the bundle includes lit, then that copy will not be shared. This isn't a hug deal with a few elements, since the core Lit modules weight in at ~7kb minzipped, but it will be noticeable with dozens or hundreds of element definitions.

For Angular Elements, I'd hope that the same applies - that the output of the compiler includes a runtime dependency on some Angular npm package that can be shared. It's possible though that the Angular compiler, since it tried to tree-shake away unused parts of the Angular core library, creates a custom a non-shareable copy per separately compiled component definition.

So I think the questions will start with how custom native implementations will be installed, and then whether you run any global build step. For Lit and many other non-compiler-based libraries, I think you could get a working system with npm, Rollup, and a config that just pulls in each element definition file. For the Angular compiler, I suspect you would have to configure and call it somehow.

As for other frameworks, it's not always a compilation step that produces a web component. For React and Preact you would probably use a custom element wrapper helper that could be set up at runtime.

wwwillchen commented 1 month ago

Thanks @justinfagnani, that's very helpful. We will spend some time analyzing this and put up a more detailed proposal later.

wwwillchen commented 3 weeks ago

Hi @justinfagnani just wanted to share our proposal for supporting custom web components in Mesop: https://docs.google.com/document/d/1Nc7Ub8DMNSxAmFuPRdyrlZXh_AoxVjZM-YEeWF8dAyI/edit?usp=sharing. Could you take a look and let us know if you have any comments and suggestions? Thanks.