[HN Gopher] Building a front end framework - Reactivity, composa...
___________________________________________________________________
Building a front end framework - Reactivity, composability with no
dependencies
Author : 18al
Score : 132 points
Date : 2023-05-14 12:26 UTC (10 hours ago)
(HTM) web link (18alan.space)
(TXT) w3m dump (18alan.space)
| lloydatkinson wrote:
| Lost me at web components. What a miserable DX and inconsistent
| mess that is.
| spankalee wrote:
| What's inconsistent about them?
| grncdr wrote:
| This is extremely similar to https://jhuddle.github.io/ponys/
| which I've been using quite happily. The `data-mark="foo"`
| convention is interesting, similar in spirit to ng:bind or
| knockout attributes.
| joncfoo wrote:
| This is really neat! I'm going to take it for a spin in a
| simple CRUD internal app.
| imbnwa wrote:
| As someone who started out in this profession in their early 30s,
| it was made clear very quickly, both by observation and shared
| wisdom, that it was completely possible to go one's entire career
| never getting below the level of gluing business code together
| with the adhesive of some framework, i.e. never learning how to
| _design_ a system or think from the 'bottom' of a solution.
|
| While its arguably more accessible than ever, you can quickly
| find yourself swimming in a shallow pool if you're not careful
| where your first job is, unless you have the free time and
| comportment to swim towards the deeper end on your own. And the
| larger magnitude that this occurs at, the greater the
| stranglehold of most devs to some well-funded framework and
| tooling.
|
| So I applaud reminders like this that ask to just take a step
| back from time-to-time and maybe provide ourselves a new
| opportunity before reaching for $BIG_FRAMEWORK when the project
| is a few views w/ some buttons and an input on them. There has to
| be some balance between the utter pragmatism and curiosity and
| exploration that builds skills to have a healthy demo of devs.
|
| I routinely see this second-hand classist complaint about
| 'JavaScript devs ruining software' (particularly w/ Electron in
| hand, even though the most used Electron apps are probably worked
| on by high-tier devs) but really the source of that concern is
| the market _desiring_ that devs be more or less replaceable for
| the most part and the skillsets follow that. You can 't break
| that without some disruption to the Framework-Industrial Complex.
| revskill wrote:
| This is good progress. I hate that i can't do progressive
| enhancement on pure html form with Frontend Framework.
|
| Example, RoR already provides powerful good library like
| SimpleForm. Now i want to turn this html form into a React form,
| how ?
| es7 wrote:
| On a recent project, I've just been using JS template strings and
| .innerHTML all over the place.
|
| I don't necessarily recommend it, but it's been a good reminder
| to me that most of the value React provides me is literally just
| html-in-JS. In many cases the complexity that comes from React
| effects and state is unnecessary, and directly mutating DOM nodes
| is sometimes a lot less painful. Sometimes.
| wbobeirne wrote:
| This definitely works until you hit one of a few cases I can
| think of:
|
| * Adding animations to elements. By blowing away the DOM and
| inserting new elements each time, you'll trigger any css
| `animation` for new elements entering.
|
| * Stale data. If your template isn't re-run when some data
| changes for whatever reason, you'll continue to render the old
| data. You've got to manage the lifecycle of state updates
| yourself.
|
| * To counter that, you might just re-run your templates when
| _anything_ changes. This works until you have a significant
| amount of data, then performance starts to become an issue.
|
| This won't come up for many cases though, so for simpler apps
| it's definitely more than enough!
| pkphilip wrote:
| Very interesting. I think this explains a lot of the magic that
| happens under the surface in the frontend frameworks. I quite
| like the approach you are using to avoid a build step and also
| zero dependencies.
| mtlynch wrote:
| This is great! I've been looking for a framework with exactly
| these goals. I've been using vanilla JS and custom elements and
| feeling like I'm writing too much boilerplate, but all the
| frameworks I've tried are too heavyweight.
| spankalee wrote:
| Have you tried Lit yet? It gives you a reactive base class and
| declarative templates. Plain JS and no build step (or you can
| use TypeScript).
| mtlynch wrote:
| I played with it a little bit when you told me a few months
| ago it supports buildless.[0]
|
| The thing that dissuaded me is that it seems like it forces
| me to write my template HTML in strings, so I lose VS Code
| syntax highlighting and Prettier auto-formatting. I tried
| looking for VS Code / Prettier plugins but didn't see
| anything.
|
| Is there a way in Lit to write the templates in regular HTML
| rather than a string?
|
| [0] https://news.ycombinator.com/item?id=34828992
| lolive wrote:
| Yet another people denying React Hooks has won...
| petilon wrote:
| Very thin frameworks can avoid the complexities of React and
| hooks and useEffect and whatnot. Here's an app written with a
| 500-line "framework", notice how readable and maintainable it is:
| https://github.com/wisercoder/eureka
| djbusby wrote:
| Less Framework and more Library it feels like.
|
| Also, wondering if there are other tools for searching code and
| other internal Corp stuff on external services (GitHub/Lab,
| Google Drives, etc)
| ttfkam wrote:
| They literally just described Svelte with that headline.
|
| Front end framework: check
|
| Reactivity: $check
|
| Composability: check
|
| No dependencies: once compiled, check
|
| And pretty sure Svelte (or Qwik or Solid or even React) will
| perform better than the "dependency-free" custom components. The
| open secret in the front end world is that custom components as
| baked into browsers is slower and a major pain in the ass as an
| API. That's why it wasn't adopted widely and why it will likely
| never be adopted widely.
|
| The funny thing about stories like these is that once you write
| the first general use code that isn't based on your specific
| task, you've created a dependency. Only this dependency isn't
| improved and maintained by a community or company; its
| maintenance is handled by you and your team. Maybe you take it on
| because the benefits outweigh the costs for your team. You
| improve and refine "just a few functions". Other folks like what
| you've done and ask to use it. Now they have a dependency on the
| "no dependencies" framework. Eventually you have to give it a
| name, and it gets popular.
|
| A few years later, a developer decides they doesn't want any
| dependencies in their front end code anymore...
| _heimdall wrote:
| Kind of bending definitions to say svelte doesn't have any
| dependencies once compiled. Svelte itself is a dependency, and
| though complex and bundled there are svelte utilities included
| in the app that aren't code directly written by the user.
| Anecdotally, if also be very interested to see any example of a
| production Svelte project that doesn't pull in any other
| dependencies.
|
| The article also calls out no build step, though it's not in
| the title. That's an important factor for the kind of project
| that isn't updated regularly and needs to work without any fuss
| after a year or two of going stale.
|
| I'm a big fan of svelte by the way, been using it since pre-
| release 2.0 and still reach for it whenever I need a more
| complex state management or don't have the time to roll my own
| animation trigger utilities.
| ttfkam wrote:
| Fair points.
| hbroek wrote:
| I love Svelte for all these reasons. But in the end, was turned
| off by the required tooling.
| hbroek wrote:
| Enjoy the process of building your framework. I had similar goals
| when I started my no tooling / no dependencies Reactive framework
| https://reken.dev, 2 years ago. And I loved every bit of it. My
| most complicated problems were reactive DOM elements based on
| nested loops and recursive components. Even though Reken does
| pretty much what I need and grew to 7kb compressed, I am not 100%
| happy with the scope of the application state, and it is simple
| but sometimes confusing. Perhaps your proxy approach can help me
| here.... I'll have to think about it more.
| 18al wrote:
| > My most complicated problems were reactive DOM elements based
| on nested loops and recursive components
|
| Agreed, I've tried solving it by setting an attribute `sb-mark`
| which allows syncing just the branch of DOM elements that maps
| to that particular key in the reactive object.
|
| This removes the need for VDOM diffing, but unless I use a
| `MutationObserver` external updates to marked branches will
| probably mess it up.
|
| Haven't yet tested it for recursive components, it should work
| for nested loops.
|
| > and it is simple but sometimes confusing
|
| I understand what you mean, my approach has the aforementioned
| `sb-mark` attribute/directive which syncs primitives, lists,
| and objects.
|
| I've started feeling that the convenience of having just one
| attribute to remember is supplanted by the confusion of its
| implications not being immediately apparent from context.
| hbroek wrote:
| > This removes the need for VDOM diffing, but unless I use a
| `MutationObserver` external updates to marked branches will
| probably mess it up.
|
| Similar in Reken. It controls all the DOM; DOM updates
| outside Reken will get stuff out of sync. After a model
| change, all managed DOM gets directly updated by a generated
| controller. It does check the DOM first if a textContent or
| attribute change is necessary. Most DOM state checks are
| cheap. Another optimization is that all hidden DOM trees get
| skipped; Great in SPA apps with multiple pages.
| lelanthran wrote:
| Your arrays and buttons example appears broken - after the
| first item is added to the todo list, typing new items in the
| input field leaves the add button looking disabled (although it
| works when you click it).
|
| I think it only gets enabled when focus leaves the input field.
| hbroek wrote:
| Thanks for pointing that out. Yes had rewritten it a will
| need to use a different event to enable the button if there
| is an update in the input field.
| aabbcc1241 wrote:
| I made a similar library [1] using data-* attributes. It also
| supports nesting, looping and conditions. For event handling, I
| use function in object (a.k.a. method) while you support
| writing them inline.
|
| Your way to support inline logic in the text and style is
| interesting.
|
| [1] https://github.com/beenotung/data-template
| hbroek wrote:
| Very cool, it seems we almost came up with the same approach
| of components/templates. In your framework, it is referenced
| with a data-template attribute. In Reken, I use a data-
| component attribute.
|
| One of the design goals for Reken was to not have to context-
| switch while coding, to not lose my train of thought (Guess
| my short-term memory is limited). Hence try to add everything
| inline in the HTML file. Also I'm working on a tailwind-like
| css inlining framework (compatible with Reken). Together
| these give me dynamic DOM and styling inline.
| pier25 wrote:
| Please don't make websites dark mode only. This is terrible for
| accessibility. I have astigmatism and can't read more than a few
| paragraphs.
|
| https://medium.com/@h_locke/why-dark-mode-causes-more-access...
|
| If the issue is not wanting to spend a bit of effort to implement
| prefers-color-scheme then light mode is a much better default
| option.
| vjerancrnjak wrote:
| I do not have astigmatism (or at least I think I don't) but I
| notice that the rows of white letters stay burned in my vision,
| the contrast was so high it's as if I am staring at small
| strong light sources.
|
| So I prefer black letters on light background.
| earthling8118 wrote:
| I have astigmatism with the opposite effects. I wish more sites
| had dark modes. I have to use dark reader to ensure I can have
| a dark page but that doesn't always work.
| geraldwhen wrote:
| Maybe this is why I cannot read dark mode websites at all. Even
| coworkers with dark mode themes on their IDE are completely
| inscrutable to me.
| oblib wrote:
| This is certainly new to me and something I'm going to play with
| a bit. Thank you for sharing this here.
| datadeft wrote:
| Why do we need a frontend framework? I am genuinely interested.
| The last project we used SSR and the sire ended up fast and
| snappy using a lot less energy than the previous similar project
| we used a JS based framework and we had all the functionality we
| needed.
| muspimerol wrote:
| I think the common argument is "complex interactivity". If you
| have sufficiently complex custom client-side interactivity
| (e.g. sending, receiving, manipulating and displaying data in
| the DOM without constantly reloading the page) then something
| like React or Vue is much easier and more maintainable than a
| bunch of custom JS. Logic for mutating and displaying data can
| also live on the backend and use SSR, but it has to live
| somewhere. I think people like SPAs because you can draw a
| convenient boundary at the server level by exposing a JSON API,
| and folks working in HTML, CSS and JS like the component model
| offered by frontend frameworks (I know I do).
|
| There's also something to be said for consistency. When I walk
| into a React or Vue app, I can figure out what's going on and
| build on top of it quickly. Even if they are using a mish-mash
| of libraries (as JS apps do) the majority of the time you will
| see similar libraries and patterns used.
|
| All that said, there are many monstrosities built upon SPA
| frameworks with poor performance that would likely provide
| better user experience if they were using SSR. But there were
| also many SSR monstrosities built before SPAs were in vogue.
| datadeft wrote:
| This is the most useful comment so far. I tend to agree.
| However, I still think that most frontend project are
| perfectly fine with mostly HTML + CSS and a tiny bit of JS.
| whstl wrote:
| Projects that don't need a lot of interactivity after rendering
| definitely don't need one and you can get away with rendering
| everything in the backend.
|
| Other projects need _some_ additional features that must be
| implemented in the frontend, but still don 't need more than
| vanilla JS or jQuery.
|
| Others might need more complex components, such as datepickers,
| carousels, interactive charts, interactive tables, accordions.
| But even those can be consumed from third-party components
| without a framework. A middle ground is writing your own
| encapsulated components.
|
| However there are more complex apps that do benefit from
| frameworks. It's often because they have a lot of custom
| components and a framework really helps; and/or because they're
| not really divided into pages in a traditional web way, so
| rendering on the backend is significantly harder; and/or they
| have a lot of shared state between multiple areas of the
| screen, and not refreshing is easy than caching or re-fetching.
| All those among other reasons. Slack Web can benefit from this.
| Your daily CRUD not so much.
|
| Whether people are using the right tools for each job is up for
| debate. And sometimes you'll have incorrect requirements. But
| there are definitely reasons to use more complex/flexible
| tools.
| _heimdall wrote:
| They were extremely useful before browsers had certain
| features, like web components of the Proxy api mentioned in the
| article.
|
| Today the argument is usually based on highly complex apps,
| think complex dashboards accessible behind a login or browser-
| based apps for recording a podcast. Those are reasonable uses
| for client-side frameworks - the problem is they are often used
| for much more basic sites that just need a mobile menu,
| accordion component, or a dialog modal. All of these can either
| use entirely browser native HTML/CSS or easily built in JS
| without any dependencies.
| wbobeirne wrote:
| I've worked on quite a few projects that would have had
| significantly worse user experiences if they were done in a
| purely SSR driven way:
|
| * Chat applications, or anything where you need to have the UI
| react to incoming events from a socket.
|
| * Applications where sensitive data lives in the client and you
| don't want to be liable for that passing through your servers.
|
| * Anything dealing with video or audio (e.g. video chat, screen
| recordings.)
|
| * Applications that are driven by peer to peer data.
|
| * Applications with high interactivity (e.g. spreadsheets,
| heavy form validation, drag and drop UIs, graphic
| manipulation.)
|
| It really depends on what your application is doing. If you're
| just a blog or an eCommerce site, it's definitely worth asking
| if you need a frontend framework. But for some applications
| it's absolutely worth it.
| datadeft wrote:
| * Applications where sensitive data lives in the client
|
| Isn't JS the worst kind of solution for security related
| things?
| klysm wrote:
| New front end frameworks that claim leaps in simplicity feel like
| the violate some kind of no free lunch principle to me. If
| they're that simple, then I'm willing to bet they make some use
| cases very difficult or impossible
| capableweb wrote:
| I've found that if they brag about how easy it is to get
| started, it usually ends up messy relatively quickly. On the
| other hand, if they brag about being easy to order when you
| have a lot of code, it's usually a bit harder to get started
| with.
|
| It's like you get to chose one of "get started quickly" or
| "remain quick enough on the medium/long term"
| bitL wrote:
| Not always, some can hit the sweet spot of being simple in
| all phases of development and quick to learn. They are super
| rare though and their lessons are forgotten; industry often
| standardizes on inferior things with better marketing.
| karpierz wrote:
| What are some examples?
| arcanemachiner wrote:
| I think Alpine.JS hits this spot pretty well.
|
| https://alpinejs.dev/
| ipaddr wrote:
| jQuery
| balder1991 wrote:
| [deleted]
| balder1991 wrote:
| > industry often standardizes on inferior things with
| better marketing.
|
| It standardizes to what's cheaper on their eyes, sometimes
| in a very short-sided way, but also companies that work for
| profit never know if a project will still be running in the
| next quarter, right? It makes me think that open source and
| for profit companies should have very different
| considerations when it comes to choosing frameworks or
| technologies for their solutions. I should probably gather
| more info on that and expand it into a blog article.
| legulere wrote:
| Web components weren't as widely available as they are now when
| most web frameworks were written.
| spankalee wrote:
| I would argue rather that the amount of complexity that
| frontend web devs put up with is more of a Stockholm Syndrome
| situation. You can be _much_ simpler than most mainstream
| frameworks, using only standard JS, CSS, and HTML, and acheive
| better results.
|
| Using custom elements and shadow DOM like this post is a big
| part of that. Custom elements give you a built-in component
| module, shadow DOM gives you compositions and style scoping.
|
| I think using proxies like this post is a challenging because
| proxies are very hard to get correct when dealing with methods,
| collections, object identity, privacy, etc. but it turns out
| that many applications do just fine with a simple Redux-like
| store / action / subscribe system for data.
|
| I personally think the project I work on (https://lit.dev) hits
| a sweet-spot of simplicity vs complexity because it also gives
| component reactivity, declarative templates, embedded CSS, with
| standard syntax and no build tools required. In more than 400
| LoC, but only by ~3x.
| Freedom2 wrote:
| Do you have an example of a complex widget being implemented
| in a simpler way with better results? I see this sentiment
| often here, but most examples are toy examples or frivolous.
| duxup wrote:
| I feel like the only things that provide " leaps in simplicity"
| as far as web dev goes are basic css frameworks.
|
| Generally they really can save a lot of time / needed
| structure.
| luisgvv wrote:
| The law of leaky abstractions - as systems become more complex
| eventually you rely on more abstractions that try to hide
| complexity.
|
| What makes it worse in the front-end framework world is that
| either:
|
| 1-Projects become convoluted with 3rd party libs to solve a
| problem
|
| 2-The framework maintainers eventually introduce APIs that
| aren't backwards compatible and existing ones stranded or
| deprecated
| balder1991 wrote:
| When discussing this problem with ChatGPT it indeed said the
| best solution for this is for frameworks to be designed in a
| way that encourages extensibility: so a framework should
| stick to its core principles but allow "plugins" to extend
| its functionality for very specific use-cases. But I
| understand there's always a trade off here, as simplicity in
| the framework shifts the complexity to the application.
| austin-cheney wrote:
| Depends on the definition of simplicity. People say they want
| simple, but then really want easy. The most easy is always
| somebody doing the work for you. I got tired of hearing people
| mention _easy_ when really they probably mean some combination
| of fearful and /or lazy, so I chose to define easiness:
|
| https://github.com/prettydiff/wisdom/blob/master/Easiness.md
|
| If developers really wanted simplicity or to be done with work
| faster they would just learn the primitives of their
| environment: DOM, functions, and events. Most of the frameworks
| have APIs that are huge, so clearly simplicity isn't what's
| wanted.
| balder1991 wrote:
| Thanks for sharing this. I've been recently into the concept
| of Digital Gardens where you evolve concepts and expand them
| over time (instead of the traditional chronological blogging
| style) and this is exactly the result that I imagine a page
| should look like when matured enough.
| aabbcc1241 wrote:
| I'm experiencing the trade off between simplicity and
| expressiveness for a lightweight frontend library that doesn't
| involve VDOM.
|
| On one hand, a library [1] can be very concise (update dom from
| object, with looping and nesting supported).
|
| On another hand, a library [2] can be very flexible and reactive
| (update dom from dom events).
|
| However, when double-binding (a.k.a. bi-directional binding) is
| required (update dom from object and update object from dom), it
| seems more complex than I would consider it lightweight.
|
| When double-binding is preferred, I'd rather go for angular /
| vue. Still exploring alternatives.
|
| [1] https://github.com/beenotung/data-template
|
| [2] https://github.com/beenotung/dom-proxy
| adparadox wrote:
| Nice write-up, I look forward to seeing how Strawberry
| progresses. I keep a list of JS front end frameworks where no
| build step is required at https://unsuckjs.com/. I'll add this
| there (and a few of the others mentioned in the comments here).
| aabbcc1241 wrote:
| Would you also add these js library to the list? They don't
| require build step as well.
|
| https://github.com/beenotung/html-template-lite
|
| https://github.com/beenotung/data-template
|
| https://github.com/beenotung/dom-proxy
| adparadox wrote:
| I added `dom-proxy` because that looked like the closest to a
| complete solution from a quick skim. Let me know if you want
| to swap for another one, though.
| spankalee wrote:
| Lit 2.x is compatible with IE11, btw.
|
| We're actually removing that in the upcoming 3.0 branch though.
| adparadox wrote:
| Thanks for the correction. Just updated it to be accurate...
| for now. :)
| dxchester wrote:
| Nice writeup. We're working on a framework with similar goals,
| here: https://github.com/frameable/el
|
| Reactivity, composability, templates, etc with no dependencies,
| in ~150 SLOC.
| dclowd9901 wrote:
| > The second main reason is the ability to define a component and
| reuse it without having to redefine it every time we need to use
| it. This is called composability.
|
| Uhm, this isn't strictly composability. Its reusability.
| Composability is distinct in that you're architecting or
| designing components to be composed with one another. That is,
| they only know what they need to know and isolate domain. Also,
| their composition interface is the same as their output
| interface. A likely outcome is reusable components, but it's not
| the goal necessarily.
___________________________________________________________________
(page generated 2023-05-14 23:00 UTC)