[HN Gopher] Isomorphic Web Components
       ___________________________________________________________________
        
       Isomorphic Web Components
        
       Author : Fudgel
       Score  : 58 points
       Date   : 2024-12-14 07:19 UTC (1 days ago)
        
 (HTM) web link (jakelazaroff.com)
 (TXT) w3m dump (jakelazaroff.com)
        
       | Etheryte wrote:
       | I don't really think server-side rendering is an important reason
       | why most people don't use web components. Most web applications
       | that use components of any sort are largely SPAs of some variety
       | and don't care one bit about server-side rendering. In my
       | opinion, the main reason web components aren't widely used is
       | that the alternatives are just better. I'm yet to see a strong
       | case being made where web components are favorable for a reason
       | other than purism.
        
         | afavour wrote:
         | From my personal experience the lack of SSR is one reason I
         | don't use web components. But that said there isn't a
         | particularly persuasive case to use them either, other than it
         | being nice to use standards.
        
         | pier25 wrote:
         | > _Most web applications that use components of any sort are
         | largely SPAs_
         | 
         | How did you get to that conclusion? Honestly asking because my
         | hunch is that it would be the opposite.
         | 
         | > _I 'm yet to see a strong case being made where web
         | components are favorable for a reason other than purism._
         | 
         | IMO it's wrong to see web components as a universal solution to
         | all client-side use cases.
         | 
         | Web components are amazing for distributing widgets to third
         | party users. From users authoring HTML in any number of
         | environments to a way to plug modern JS stuff into SSR backend
         | frameworks.
         | 
         | Back in 2016 I worked in library of widgets for interactive
         | education ebooks. People producing the ebooks could barely
         | write HTML so being able to add interactivity with configurable
         | custom tags was extremely easy for them. Currently I'm working
         | in an embeddable and customizable audio player with web
         | components. Typically you'd use iframes which are quite heavy
         | and have serious limitations. In both use cases, web components
         | were the right choice.
        
           | DrFell wrote:
           | Websites built with JavaScript frameworks need SSR because of
           | SEO. Applications don't, so most are SPAs, because they can
           | be. The fully decoupled SPA is a special architecture.
           | Complexity isn't just lessened, a lot of it vanishes. Poof,
           | bye bye headaches. If you can use it, you do, and most web
           | applications can, so they do.
        
         | ww520 wrote:
         | I'm curious to see a plus and minus comparison of web component
         | vs other techs (I assume those are React, Vue, etc.)
        
         | deergomoo wrote:
         | I read a lot of blog posts from both sides in the most recent
         | big "web components vs frameworks" brouhaha a month or so ago.
         | The conclusion I came to was that both sides' arguments were
         | mostly correct but orthogonal to each other, so neither side is
         | ever going to convince the other because they're not _really_
         | seeking the same goal.
         | 
         | The pro-web-component folks argue that WCs are standardised and
         | will continue to work basically indefinitely regardless of the
         | ebbs and flows of popular libraries, and because it's easier to
         | progressively enhance and therefore more accessible. This is
         | correct, and those points are valuable if what you seek is a
         | way to add resilient islands of interactivity to your document.
         | 
         | The pro-framework folks argue that in their model where the
         | entire UI is a function of state, WCs are incredibly
         | cumbersome, because all you really want from a component is to
         | be a smaller function with which you can compose part of the
         | whole. They are not nearly as concerned with maintaining that
         | component under React vX in five year's time, because _the
         | entire system_ is written in React vX. The components are not
         | maintained or used as individual units unless you are shipping
         | a library. This is also correct, and those points are valuable
         | if what you seek is an effective way to break down complexity
         | in your application UI.
         | 
         | Of course, many (maybe even most?) SPAs _should_ be documents
         | with progressive interactivity--it involves less fighting with
         | the fundamentals of the web (which is, ultimately, still based
         | around documents) and therefore offers better performance and
         | accessibility with less effort. SSR for frameworks is an
         | absurdly complex solution to a problem that doesn 't exist if
         | you can just send a complete document right to the browser.
         | 
         | But, likewise, implementing a genuine high-interactivity web
         | application using web components would be far more difficult
         | than using a framework, and I am certain would result in re-
         | implementing some sort of reactive UI/function-of-state
         | paradigm anyway.
         | 
         | Personally I think it's kind of a pointless debate, until and
         | unless we get something that is close enough to <insert popular
         | JS framework here> + SSR built into the browser. I don't know
         | how that would work or whether it's even possible, but at that
         | point the set of standards would actually cover all of the
         | problems everyone is trying to solve and it would be worth
         | arguing whether or not to use them.
        
           | solardev wrote:
           | Exactly. Good breakdown.
        
           | WA wrote:
           | > SSR for frameworks is an absurdly complex solution to a
           | problem that doesn't exist if you can just send a complete
           | document right to the browser.
           | 
           | So, React is just a view library. It's made to map state to
           | DOM changes. Except it's not just a view library, because if
           | you write an app with React, you are writing a React app. You
           | slice and dice your view up and put them into React
           | components. Now, since you want to use your React components
           | on the server and not slice and dice them up again in another
           | view library, you morph that DOM-manipulating lib into a
           | templating engine that generates static HTML. Except you call
           | it "server side rendering", because "templating engine"
           | sounds so 2010 and "static site generation" is also not the
           | right term, because the output isn't a static HTML page, but
           | can change with every page request. Of course, the "React"
           | part of React is completely ditched in SSR, because you don't
           | need to continuously modify the DOM based on your state.
           | React on the server is what PHP templates have been doing
           | forever. Outputting HTML in PHP is "view = f(state)". We've
           | come full circle.
           | 
           | I sometimes wonder if younger web devs even understand that
           | SSR isn't, like, really rendering a page on the server, but
           | basically means "we produce frickin HTML like we've been for
           | the last 30 years, except our tools are now 10x as complex to
           | such a point that we don't understand them anymore", because
           | 90% of our view library does nothing on the server, because,
           | you know, there is no DOM. There is only HTML as a string
           | send over HTTP.
           | 
           | Having said that: Your analysis is completely correct. The
           | discussion really is orthogonal and I'm not sure I see the
           | point in rendering web components on the server, since most
           | web components benefit from interactivity through JS. If I
           | merely encapsulate a bunch of HTML tags, I can ditch the
           | custom element entirely and send the HTML tags down the wire
           | by themselves.
        
             | MrJohz wrote:
             | I think when trying to understand SSR, it's worth
             | remembering what actually was happening with older systems
             | like PHP. You say that outputting HTML in PHP is `view =
             | f(state)`, and this is to a certain extent true, but it
             | meant that anything on the client side was then `view =
             | f_client(state_client, f_server(state_server))`, and
             | getting applications to remain sane with anything more than
             | the bare minimum of interactivity was painful. I remember
             | this era, and debugging constant state issues was very much
             | the reason that we ended to moving towards client-side web
             | frameworks: you only have to worry about one `f` and
             | (mostly) one `state`.
             | 
             | In my experience, most of the people exploring SSR are very
             | acutely aware of that era, both the benefits and the
             | negatives, and are trying to build systems that allow
             | developers to retain a consistent overall view function
             | without having to maintain that across multiple codebases
             | in multiple languages. That doesn't just mean rendering
             | HTML, but also ensuring that the frontend and backend agree
             | on how to update that HTML if the state ever changes, or
             | ensuring that progressive enhancement is possible while not
             | requiring the entire site to reload every time I update a
             | form field.
             | 
             | Now I think there's a good argument to be made that many
             | applications don't need this additional complexity - they
             | can continue to be rendered entirely server-side, or
             | entirely client-side, and not need to share state at all.
             | But if you do need state to exist in both the server and
             | the client, modern SSR frameworks are typically a pretty
             | good approach.
        
           | nosefurhairdo wrote:
           | > WCs are standardised and will continue to work basically
           | indefinitely regardless of the ebbs and flows of popular
           | libraries
           | 
           | Help me understand; is this suggesting that older
           | frameworks/libraries are expected to stop working at some
           | point? I'm shipping 10+ year old libraries in production
           | without incident. Really don't understand the "resilience"
           | argument for WCs.
        
             | pegasus wrote:
             | 10+ years is nothing compared with a human lifespan. Web
             | standards are more likely to still be around in 50 years
             | than react vX.
        
               | teg4n_ wrote:
               | react uses those same web standards. It will not stop
               | working either. You may not be able to upgrade to the
               | latest React version assuming there are breaking changes,
               | but the same can be said for the various frameworks
               | people use to create web components.
        
           | MrJohz wrote:
           | > The pro-web-component folks argue that WCs are standardised
           | and will continue to work basically indefinitely regardless
           | of the ebbs and flows of popular libraries, and because it's
           | easier to progressively enhance and therefore more
           | accessible. This is correct, and those points are valuable if
           | what you seek is a way to add resilient islands of
           | interactivity to your document.
           | 
           | I'm not sure that's even that correct. If you write code
           | using browser APIs that are currently standardised, your code
           | will work indefinitely, whether or not you use Web
           | Components, React, or jQuery. Hell, we used to have jQuery-
           | based components with the whole $(...).datepicker() system.
           | Yes, it has its flaws, but it'll still work today if that's
           | what your want from it.
           | 
           | Secondly, I don't think Web Components do work well from a
           | progressive enhancement perspective. Progressive enhancement
           | is starting from the bare minimum (i.e. just HTML and some
           | styles, if that), and progressively adding features to that
           | initial state that don't prevent any of the previously-added
           | features from working. So you start with an HTML form
           | skeleton, and you add some validation attributes, you add an
           | event handler that calls fetch instead of reloading the page,
           | you extend the address input so that it suggests real
           | addresses - but the whole time, the HTML form is still there
           | and it still works.
           | 
           | But without Javascript, Web Components are essentially empty
           | holes that can't do anything. They don't progressively
           | enhance anything. You can to a certain extent wrap existing
           | elements, you can take the isomorphic approach described in
           | this post, etc. But even when you do that, the browser will
           | replace the contents of the element with the component's
           | rendered output when the Javascript comes online, potentially
           | deleting any user inputs if they'd interacted with the
           | previous context. If your aim is true progressive
           | enhancement, you should probably look in a different
           | direction.
           | 
           | In fairness, I don't disagree that these claims are often
           | made by Web Component proponents. But I think they're the
           | wrong claims to be making. Web Components seem to be most
           | useful if you're trying to isolate a complex stateful
           | component written by one person or team and ended it into a
           | complex stressful application written by a different person
           | or team. They're essentially like lightweight iframes. This
           | is really useful, and should be promoted more - but it's also
           | quite a specific use.
        
             | throwitaway1123 wrote:
             | > I'm not sure that's even that correct. If you write code
             | using browser APIs that are currently standardised, your
             | code will work indefinitely, whether or not you use Web
             | Components, React, or jQuery.
             | 
             | The most charitable interpretation of this argument is that
             | framework specific component libraries assume for the most
             | part that you're using that specific framework. The
             | documentation for popular React component libraries like
             | shadcn are largely incomprehensible if you're not using
             | React. Libraries like Shoelace (now being renamed to Web
             | Awesome) make no such assumptions. You can just drop a
             | script tag into your page's markup and get started without
             | having to care about (or even be aware of) the fact that
             | Shoelace uses Lit internally.
             | 
             | > But without Javascript, Web Components are essentially
             | empty holes that can't do anything. They don't
             | progressively enhance anything.
             | 
             | This is not true if you're using the new Declarative Shadow
             | DOM API [1]. You literally just add a template tag with a
             | shadowroot mode attribute inside your custom element, and
             | then the component works without JavaScript. When (or if)
             | the JavaScript loads, you simply check for the existence of
             | a server-rendered shadow root using `internals.shadowRoot`.
             | If a shadow root already exists then you don't have to
             | replace anything, and you can attach your event listeners
             | to the pre-existing shadow root (i.e. component hydration).
             | 
             | [1] https://web.dev/articles/declarative-shadow-
             | dom#component_hy...
        
         | egeozcan wrote:
         | Here's one case that I think is strong: At work some teams use
         | JSF, some use React. We need to deliver components to both. We
         | chose lit and we're very happy.
        
       | potsandpans wrote:
       | Only partially related to the blog post, but...
       | 
       | The thing that is lost on me with all of these webcomponents
       | solutions is that they inevitably rely on tagged templates to do
       | the heaviest lifting.
       | 
       | I don't want to write strings, I want to write statically
       | analyzable code. IDEs do some heavy lifting here for visual
       | hints, and there are a few html-in-js linting solutions, but none
       | of them are very compelling.
        
         | Onavo wrote:
         | Well since the letter x is taken, we can use w for web
         | components. So a component file with tagged HTMl strings should
         | have the extension .tsw or .jsw
        
         | madeofpalk wrote:
         | This too was my roadblock in the article
         | 
         | > You'd be forgiven for thinking you were looking at a React
         | component! Frankly, I don't see a fundamental difference
         | between these and frameworks like Svelte or Vue
         | 
         | Regardless of whether you should be forgiven for thinking it's
         | a react component, it omits it's biggest strength - JSX is just
         | JavaScript function calls, and thus can be composed as
         | JavaScript and type checked as java/typescript.
         | 
         | This to me is the fundamental difference between React/JSX and
         | other approaches. Any framework that gives up on type checking
         | for the view layer is a non-starter in my books.
        
           | CharlieDigital wrote:
           | The fundamental differences are quite stark.
           | 
           | Vue, Svelte, web components, and vanilla only execute code
           | that is marked as a callback.
           | 
           | Example:                   let x = 0         var counter =
           | computed(() => ... )
           | 
           | In this Vue snippet of an SFC, the callback in the computed
           | executes in reaction to some change without invoking the
           | assignment of x (obviously a trivial case here).
           | 
           | DOM + JavaScript is the same
           | 
           | React invokes the entire component function and all calls and
           | allocations in the path of the component function. The mental
           | model is inverted in a sense.
           | 
           | This is one of the reasons React generally performs more
           | poorly in both speed and space.
        
         | spankalee wrote:
         | Static analysis works on strings: source code. Similarly, it
         | can, and does work on the strings in a tagged template literal.
         | 
         | Lit's templates are HTML with bindings. They're very
         | analyzable, including checking for valid structure, associating
         | tags with definitions, type-checking bindings. The tools that
         | do this parse template strings, build an AST, and run analysis
         | passes just like other source analysis tools.
         | 
         | Developers get standard intellisense features like jump-to-
         | definition, hover-over docs, errors on invalid properties and
         | events, etc.
         | 
         | But also... templating is an _implementation_ concern.
         | 
         | To build a web component you don't have to use a tagged-
         | template-based system. There are template systems that use JSX.
         | You can use Preact, or React themselves. And your component
         | users don't ever have to know what template system you chose to
         | implement your component.
        
       | sirwhinesalot wrote:
       | Great stuff, but if you are writing your own components just
       | stick to light DOM and do not write code to generate DOM elements
       | for the component to look right.
       | 
       | Let's say you are making a splitter component. Do not do this:
       | <my-splitter>         <div slot="left">         <my-handle
       | slot="handle">         <div slot="right">       </my-splitter>
       | 
       | With some divs on the inside assigned to slots. Instead do this:
       | <my-splitter>         <div data-slot="left">         <my-handle
       | data-slot="handle">         <div data-slot="right">       </my-
       | splitter>
       | 
       | Looks almost the same right? Except the one at the bottom is
       | trivially server-side rendered. *It already is*.
       | 
       | Stay on the light side.
        
       | egeozcan wrote:
       | Lit has an experimental SSR plugin:
       | 
       | https://lit.dev/docs/ssr/overview/
       | 
       | I also sort of made SSR work under next.js (not to be mixed with
       | server-components), but that took a lot of hacks and going off
       | the beaten path:
       | 
       | https://www.npmjs.com/package/@lit-labs/nextjs
        
       | finiteparadox wrote:
       | Why do they have to call it "isomorphic"? that already has a
       | meaning that doesn't really coincide with how web dev people use
       | it..
        
       ___________________________________________________________________
       (page generated 2024-12-15 23:00 UTC)