4 ms·
Have >3 years of experience working with web components full time. 1) Their templating library has a learning curve. It's not quite like svelte, nor like JSX.
by nojvek 6y ago
Have >3 years of experience working with web components full time.
1) Their templating library has a learning curve. It's not quite like svelte, nor like JSX. If you have templates as strings that aren't typechecked, it makes it really hard to work on large code bases where the components are built by someone else and you're the consumer. I remember breaking powerbi.com due to missing > in an angular template that ended up in prod that only triggered for non english customers. It was a hard lesson that day never to touch untyped string based templates ever again. It's so easy to miss something. You want strict compile time checks, not run time.
2) Being dependent on slots. It's not easy to watch for changes in attributes to a slotted child. Yes you can add mutation observers but they aren't cheap either. All sorts of bugs poped up because some code does querySelector(x).setAttribute on a slotted child but the parent doesn't rerender and the UI doesn't look right. We ended up going to json strings inside attributes so components take their inputs via attrs rather than reading slotted children. The other avenue is props (like ionic), but props don't show up in dom explorer, so you have to make the tradeoff.
3) the 3rd big gotcha of web components. Attributes are strings. You have to serialize and deserialize from strings. Sure you can listen to when they change via attributeChangedCallback and get immutability for free because of serialization, but that comes at a perf cost. for deeply nested objects, you have to serialize and deserialize from json.
All in all, I love that Microsoft is doing web components. Webcomponents are part of native dom api with simple lifecycle api. They're neat.
- flowerlad 6y agoYou can use JSX to implement as well as consume Web Components. See here: https://github.com/wisercoder/uibuilder https://github.com/wisercoder/uibuilder This gives you compile-time checks, and attributes can be objects.
- CuddleBunny 6y agoThe template strings are sort of typed, using tagged template literals. These even come with editor support using extensions previously built for lit-html and the like.
- flowerlad 6y agoYou get compile-time checks for embedded JavaScript expressions. But you don't get checks for html tags and attributes. With JSX the TypeScript compiler checks JavaScript expressions as well as mismatched tags and attributes, all without any add-ons.
- CuddleBunny 6y agoIf the tagged literal approach takes off I'm sure tooling will keep up. JSX wasn't always as well supported as it is now.
- spankalee 6y agoWith the lit-html TypeScript and VS Code plugins you _do_ get checks (and auto-completion) for HTML tags, attribute, and properties. Yes, it requires a plugin, but JSX required the parser, compiler, and type-checker to explicitly add support for it. They both require an extension to core TypeScript.
- e111077 6y agoHeyo, been working with WCs full time as well: 1. Libraries like lit-html have syntax highlighting and tooling to do type checking. For the developer: https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin https://marketplace.visualstudio.com/items?itemName=runem.li... For node: https://www.npmjs.com/package/lit-analyzer https://www.npmjs.com/package/lit-analyzer For other Web Component libraries: https://www.npmjs.com/package/web-component-analyzer https://www.npmjs.com/package/web-component-analyzer 2. Totally agree on slots. They suck and were hamstringed by Safari in spec talks. Libraries like LitElement have the concept of reflecting a property to an attribute and it's really easy to do so. Also, Chrome had a property explorer in dev tools that just got deprecated which also sucks. 3. Attributes are strings, yes, but you can also set properties on a component. Easy to have a setter and getter for a property (can easily be turned into a TS decorator) that just calls a render method on change, but again, the cost for attributeChangedCallback to serialize a primitive is very low. Passing objects should just be sent as a prop, but also, passing objects to child web components we've found is a bad habit. Often the props of an object should be spread (easy to make a directive of this in lit-html) over the props of the child and arrays typically easier to turn their contents into DOM nodes. Also none of this takes into consideration of a web component using a state library like redux.
- lstamour 6y agoI’ve found that for an object-oriented web component API, you end up with less flexible rendering — yes, redux can one-way bind attributes, etc., but you’re missing half the reason why you’d want to write code that way, how React schedules and renders to make immutable one-way data flows relatively cheap/quick with little to no persistent state. (Note, less code is less work, but caching and diffing DOM can also be less work...) Things might have changed, but it’s easier to recreate web component features in JS than it is to convince people to use a two-way object-oriented API that’s mostly stringly-typed unless using JS. If the problem we’re solving is we want a faster web, bake in and follow top JS libraries such that how they render is part of the spec. I’d be very interested to see what a React scheduler would look like if implemented in C++ on top of the browser’s scheduler. I really like parts of web components, but... I’d also like to see a Chrome experiment where JSX and TS is baked into the browser to natively solve the “stringly-typed” problem the Web Components spec has. Maybe that’s going too far, or maybe we’ll end up shipping these features as “modules” that can be toggled on if compatible. I think it would help the web move to where developers are to include native understanding and support for semi-“proprietary” solutions given widespread adoption. For example, ES Modules are great, yes, until you have to start building your own vendor modules because somebody shipped a Webpack module as dist, for example. Just as Babel lets us try new syntax earlier, so too could third-party libraries popularize new browser-native APIs as loadable modules, maybe? (My assumption being that integrating with existing C++ is cheaper than writing scheduling and DOM update logic in JS, but the JS is cheaper to ship, so some kind of browser-module-loading-with-JS-fallback is the only way we can have performance wins for existing approaches while still shipping new versions of features given how fast JS syntax and preferences change?)
- cdata 6y ago> the 3rd big gotcha of web components. Attributes are strings. You have to serialize and deserialize from strings. Sure you can listen to when they change via attributeChangedCallback and get immutability for free because of serialization, but that comes at a perf cost. for deeply nested objects, you have to serialize and deserialize from json. In practice, most libraries built around web components only use attributes when serializing / deserializing HTML strings. When performing updates to existing DOM, it is very common for a library to use a corresponding property instead. This is very fast, supports all types of values, and many libraries enable users to think in terms of attributes while the library updates properties under the hood (conceptually similar to the React mental model).
- nojvek 6y agoYep that’s why said it’s a gotcha. As a team you have to decide the attribute/prop tradeoff and stick to it in a consistent way. By using attrs, they show up in dom explorer, so it’s neat, don’t need another devtool. attributeChangedCallback will only be called when the attribute changes. For props, it’s a bit more work since HTMLElement itself has a ton of built in props, using a setter means anytime something sets, it will he called, even if the property value isn’t different. the worst thing is when you end up overriding an internal prop and weird things happen.
- spankalee 6y agoAttributes are strings, but web components can have properties like any other object, and you can set properties on elements from JS and almost all template libraries. Properties can be complex objects, do not trigger attributeChangedCallback, and don't need to be serialized. What are you using to build your web components if you think they can only take strings?