[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)