You know where vanilla JS still has a legitimate usecase in the era of SPAs? Landing pages.
- Mostly static HTML, time to first render is critical, all you want is a little bit of (progressively added) flair
- Can be inlined for instant loading/execution, no bundle download (or SSR) necessary
- Code has low volume and scope so structure / spaghetti isn't a concern
- You can separate it out from the rest of your SPA bundle(s), so shipping changes is completely decoupled from your SPA CI/CD process and can be done as frequently as you like and very quickly
Interesting. Can you elaborate on this. What do you use this vanillaJS framework for? How do you do DOM manipulation? How much traffic do you get from what you've built using this?
I've heard doing document.getElement... and then modifying the DOM is costly.
> I've heard doing document.getElement... and then modifying the DOM is costly.
So, manipulating the DOM uses more memory than, say, manipulating strings.
But assuming you're going to change something on the DOM anyway, the framework has the exact same API's to manipulate the DOM that you do. And they have their own overhead to figure out what operations they want to run.
Almost by definition, vanilla will always be faster.
That doesn't mean it's always better. If you need the DOM to reflect changing states in complex ways (think Trello or Notion) I'll be the first to admit it's simpler to let someone else's algorithm morph the DOM. And that's okay.
The main performance gotcha to watch out for with hand rolled DOM manipulation is causing a reflow.
Pretty much if you make changes to a DOM element and then read a computed value from it before a new frame renders (like dimensions etc), the browser has to recalculate the page layout before it can return an answer.
Fast: Read -> Modify -> Paint
Slow: Modify -> Read (reflow!) -> Paint
This generally isn’t an issue but if you’re seeing hiccups it’s either GC run wild, synchronous code chewing up the frame budget or frequent reflows.
It helps when one uses Java and .NET server side rendering frameworks, which offered component libraries before nodejs was even an idea, which also allow to package JavaScript and CSS.
Then only use JavaScript where it makes sense.
For example, using Angular, React, Vue to display text or encapsulate three.js is probably not the best use case of customers CPU and bandwidth.
Yes, landing pages are places where you can use static HTML, CSS, and JS. However, React (and similar frameworks) might still be better, especially with a landing page with multiple parts. This is because React combines two different paradigms, one of creation and one of distribution.
In creation, React breaks up large parts into smaller components. In distribution, it renders them at runtime, not build time (with a standard create-react-app app). However, there is no reason to have both at once. Components make the page easy to reason about, and they can be used to compile a site at build time, as Svelte does. React also has its own libraries for this, like Gatsby and Next JS. You do say that the landing pages have low volume but they can certainly grow to encompass a larger amount of things, such as multiple feature pages or a blog, so I'd rather not rewrite everything later on.
You could also use Web Components but they don't have as much support and are generally not as good as React (one can disagree of course), so I like to use React + Gatsby to build the pages at compile time and use them without any Javascript whatsoever [0] but still have the developer experience of creating a page via components.
I really feel like React and components in general, or almost any framework is probably overkill for most basic websites and even apps can make things harder to reason about than previous architecture styles. Especially so if there is a tendency to decouple at a very granular level.
I recently decided to, for the sake of practice, build some single page apps using Vanilla JS. It was such a pain. Maybe some of it is due to my relative lack of front-end JS experience, but I found it nearly impossible to avoid duplicate code. I’m interested to know how people architected apps like that before. I was under the impression that SPAs were not nearly as common before frameworks like React.
There where other toolkits before react, Dojo, MooTools, YUI each had their pros and cons. The problem was they where all fiefdoms similar to how Angular is. Where React really hit while the iron was how was that the whole JavaScript build and packaging system was moving to npm and react was one of the first sane component models available in that ecosystem. Unlike the previous attempts React did not try to be all things to all people, it was laser focused on being a component model and life-cycle. You got the rest via a plethora of options via npm install.
As a side not React also bucked what was the sage wisdom of the time which was, don't mix templates with code via the introduction of JSX. This came from the very real and sage pattern of separation of concerns but somewhere along the way we confused separations of technologies with separations of concerns. If a piece of CSS, a piece of HTML and a piece of JS are all dealing with the same black box concern and are not reusable outside of that black box, separation of technologies (i.e separate files for each) only serves to add complexity to the solution as it abstracts them away from each other, forces the need to resolve their interdependence and obfuscates the ability to quickly get an entire overview of the black box.
I wasn't thinking necessarily about pure vanilla JS, though that's certainly an interesting experiment that would lead to a better understanding of what something like React actually does. I was thinking about choosing the right tool for the job or scale of the job. If what you're definitely doing is an SPA, then you should probably assess how the nature of the application relates to the tools you'll choose. For many smaller things though, I'd doubt the necessity for an SPA at all, and vanilla JS would likely suffice. Considering that React is largely just one piece of the puzzle, it can easily be replaced in most cases by vanilla JS I'd think.
Do you think duplicate code bad, no matter the case? I'd like to hear your thoughts.
Personally, I don't mind a bit of duplication and difficult coding if I can avoid a juggernaut like React, but I also don't mind simpler visual UIs. I actually prefer them over the complicated SPA that tries to look and feel like a native application, because it never works. There's this "uncanny valley" between native application UIs and SPA web apps which try.
Sure they were, you just organize the code in components in server side frameworks.
You get a way to organize your server side code, CSS, JavaScript and flavour of Web API of the month (SOAP, REST, gRPC, WebSocket, ...).
Naturally reusing components across frameworks isn't that easy, but the same problem also happens across React, Angular and what have you, unless you make use of WebComponents, but that only works if targeting the most recent browsers.
Not to the same extent though. Usually they're provided as mixins which can be useful but aren't as powerful because there is programmaticity to them, they simply output HTML without consideration for the life cycle of a site, if any. Again, useful if your site is simple, but anything more and it gets complicated, even for a landing page as these days landing pages have a lot more dynamic parts.
they simply output HTML without consideration for the life cycle of a site, if any.
If you don't mind, as someone who is not familiar with react can you elaborate on the difference? What do you mean by life cycle of a site? In the template I use, I can organize all parts of a site as functions and compose/reuse them freely.
you can get all these benefits by pre-rendering and hydrating using a system like react-snap. this means static rendered html is served and the react control is then re-added, or ‘hydrated’ into the DOM content
- You can separate it out from the rest of your SPA bundle(s), so shipping changes is completely decoupled from your SPA CI/CD process and can be done as frequently as you like and very quickly
I mean sure I guess I could do a lot of extra work to separate it out, it's true. But the real benefit of a vanillajs landing page is stuff is simple, and getting all the benefits by pre-rendering and hydrating using a system like react-snap sounds difficult.
If we follow the old saying Simple things (to say) should be simple (to do) it implies to me that Difficult things to say will be (relatively) difficult to do.
This site is a real gem. Clean, simple, and minus the excessive complexity and obfuscation caused by frameworks. Doing & Learning things in plain JS we can learn fundamentals.
The MDN docs are from my experience the best browser frontend reference available.
This site however covers a different need: guide/howto oriented documentation, which is often what you want.
> Doing & Learning things in plain JS we can learn fundamentals.
To this I have to add that I often do write plain JS supported by only a few, small libraries such as is.js, axios, json-schema and so on. This is regarding small to medium sized projects and/or features.
This can easily save time, setup and mental energy, as long as one follows a consistent, simple structure. And on top of that, the fewer dependencies you have, the less friction.
But it also means that one has to have a bit of a deeper knowledge of the available frameworks and tools, which can manage complexity with growing features, because you add them incrementally and only when needed and so on.
MDN is great as if you're reading the manual with all the details and etc.
But like a lot of raw manuals sometimes you read it and wonder "Wait.. why would I want to do this again? Does this even do the thing I started looking for?"
Some of their examples have actually evolved to be a bit more akin to more usage based rather than raw specs.
I do appreciate the other sites that are more "You want to..." as a complement to MDN and such.
Honestly, while axios is nice to have on the server side, the websocket API in the browser is very simple to use. Which IMO is a consistent theme with modern browser APIs.
Agreed: on our current front end project at work I’m having a lot of fun teaching the team the amazing browser APIs that subsume the need for a lot of the third party dependencies we used to reach for
In this project, simple: we don't have to. Despite being a decade old application, it was entirely AJAX-driven and front-end focused even back in 2010, and IE support was dropped entirely a few years ago by the business. Works in Edge just fine, as to be expected
Agreed.
But the reason I asked because I am assuming they are making changes to a long-standing project that previously relied on third-party libraries (for browser compat?). I'm interested in that specific situation, not all projects in general.
Firstly, it doesn't tell the reader that every method of selecting elements listed is available on both a Document and an Element. document.getElementsByClassName selects everything in the page with that class name. Element.getElementsByClassName selects every child of an element with that class name. If you're wrangling a huge page using one is better than the other. Chaining calls is really useful eg document.getElementById('users').getElementsByClassName('admin').[1]
"Select an element by given ID" using getElementById() does select a single element on the page with that ID, which is right, but browsers don't enforce ID uniqueness so you're only getting the first element with that ID. That's a very common gotcha for devs who are new to this. (React would tell you if you've not got a unique key.)
.querySelectorAll() does not return a list of elements. It returns a NodeList, which is different to the HTMLCollection that the other methods return. For a start, NodeLists aren't iterable in the same way as HTMLCollections. You can use forEach but you can't use map. That's going to throw a lot of devs a curve ball.
Worst of all though, it doesn't mention .querySelector() for picking individual elements. Why would you miss that out?
[1] The page that does talk about selecting children (https://htmldom.dev/select-the-children-of-an-element) of an element suggests using an element's childNode array. That's horrible. There could be all manner of strange things in there. Just use an element.querySelector() call.
Just about everything on the Element node type is available directly on the Document. The document is actually a node type in the DOM. In JavaScript the DOM methods are populated on the global objects Element and Document and that is visible in the browser console with:
Document.prototype
You can see that the prototypes are almost but not exactly identical and both inherit from the global Node object. The page could have dived into that level of detail, but I think that largely misses the point. Most JavaScript developers are irrationally scared to death of the DOM and that page is trying to be a friendly low friction reference. If somebody were really looking for that level of granularity they could go to MDN or the DOM spec.
> but browsers don't enforce ID uniqueness
Actually, the browsers do. This isn't a browser shortcoming. It is an HTML shortcoming. If the code were parsed as XML the browser would point to the location of this violation.
> .querySelectorAll() does not return a list of elements. It returns a NodeList
Same thing. Node lists are iterable lists but are not a form of Array where the only practical difference is that a node list does not have the Array.prototype methods.
> The page that does talk about selecting children (https://htmldom.dev/select-the-children-of-an-element) of an element suggests using an element's childNode array. That's horrible. There could be all manner of strange things in there. Just use an element.querySelector() call.
Suggesting reliance on the convenience of the querySelector method is bad advise, especially from a learning and reference perspective. The querySelector method executes thousands of times slower than the other more specific methods because it requires a parse step. Also I see no danger of using the childNodes property. Simply don't make the blanket assumption that everything in the DOM is limited to element and text node types.
>.querySelectorAll() does not return a list of elements. It returns a NodeList, which is different to the HTMLCollection that the other methods return. For a start, NodeLists aren't iterable in the same way as HTMLCollections. You can use forEach but you can't use map. That's going to throw a lot of devs a curve ball.
querySelectorAll does return a list of elements. While technically a NodeList, you can't select non-element nodes with selectors which is why querySelectorAll never returns such.
Further, neither NodeList nor HTMLCollection implement methods like map, but both are quite iterable and in a similar fashion (by converting them to Arrays or using Array methods with them, like with other Array-like objects which JavaScript is full of). But if anything, NodeList is a "more" iterable type than HTMLCollection, as it does implement forEach itself, too.
I would certainly not recommend using querySelector for accessing an elements first child node or child element.
Too bad this site doesn't remember your scroll position when you go to a page and hit the back button. For a site promoting vanilla Javascript, it didn't really need to be built with React.
I love the idea, but the very first example on there ("How to add a class to an element") comes with the disclaimer "isn't supported in IE 11". Everyone likes to support only modern browsers, but completely dropping support for IE is unlikely to be acceptable for most users.
For my own sites I conditionally include a shim for IE users so I can use vanilla JS and only IE is bothered by the longer load time, using <!--[if lte IE 10]> ... <![endif]-->
The problem with vanilla JS is not APIs, API is the easy thing. The problem is building proper architecture, so code won't quickly turn into spaghetti. With frameworks like Angular or React, it's much easier, as the general structure is dictated by framework and developer just have to follow good practice. With vanilla JS it's the wild west.
In my experience in the corporate world it's just as much the wild west even with using popular frameworks. Frameworks aren't a substitute for discipline or organization.
I wonder if those chaotic corporate experiences would've been far worse if not for the frameworks. They're just so useful for significantly constraining the solution space that you can't get too far into the weeds even when lacking discipline/organization.
My experience is that velocity slows because devs get so lost in all the accidental complexity of these frameworks and their hidden lifecycles (that they only barely grasp from their 1 tutorials worth of experience) that their velocity of delivering real business value plummets. We are much less productive than a decade ago.
Did you ever work on a JQuery codebase? (JQuery was an almost 1:1 mapping to browser APIs, do it's more or less equivalent to vanillaJS). Codebases based on modern frameworks, especially React, are much less complex than codebases based on the old approach. Back then you'd get lost in the weeds of DOM manipulation, and it'd be hard to see the big picture at all.
In my experience most of the incidental complexity in modern apps comes from inexperienced devs doing things that simply didn't need to be done in the first place. Very little of it comes from the frameworks.
This completely matches my experience. I've worked on a 200k+ line javascript codebase that originally used just vanilla HTML DOM management and jQuery for everything, and I've helped introduce React into it over the years.
Every time the old code needed to place a view inside of another view, it was a fresh adventure in the exact way that sort of extremely common routine operation shouldn't be. Understanding a module always meant understanding its approach to managing its DOM elements before you even got to its business logic. Modules often chose between having simple-but-janky code that re-created DOM elements from scratch every time anything in the view changed, or having more-efficient-but-complex-and-buggy code that intelligently updated only the changed elements but often had inconsistencies with the first-render code causing some values to not work if they got set while the view was already mounted. People tried to establish some conventions across a few modules, but the chosen conventions often had significant drawbacks or only worked in specific cases because the people making the conventions didn't have the experience of library/framework authors.
I remember working with a coworker sketching out an idea of a convention we could develop and use for updating text and substituting in translations and live values. One of my main goals was to allow our modules to have the same code for the first-render and subsequent renders without having to replace all the module's elements with new ones. It was originally intended for just updating text, but I started to realize it would have to handle arbitrary HTML and embedding views from other modules to really be useful. The idea felt like it would need special cases to handle that, and I couldn't get the idea further. Then I later found React, and I realized it was a generalized approach to accomplish exactly what we were trying to design. I got the green light to use it in a few new modules, and even coworkers who weren't yet familiar with React could see how the modules were much more focused on the actual business logic rather than being absolutely filled with so much unique DOM-manipulation code. Everyone was sold on it within a few months, and people that needed to make changes to old modules would often choose to move the code over to React first to make it simpler to work on.
I also feel modern web apps are just much more complex than those from the jQuery era. So codebases have to do a lot more. It's hard to find a 1:1 mapping, as we just didn't expect as much out of the web in those days.
Complete BS. Not true at all. the jquery era had ajax with dynamic dom updates, dynamic svg, css, and many things we have today except for websockets, web usb, mic, camera, and other devices. the difficulty was more around each browser implementing things differently. and css was a nightmare. just to center something horizontally or vertically (or both) took patience.
It’s not “Complete BS.” — just because we had those features does not mean most businesses used them to the same extent we do today. I was deep in the front-end weeds in 2007 and onwards, and while I may have been doing some neat stuff then, the complexity pales in comparison to the sheer amount of business logic that now lives client-side.
jQuery is constantly tested with all of its supported browsers via unit tests. However, a web page using jQuery may not work in the same set of browsers if its own code takes advantage of (or falls prey to) browser-specific behaviors.
That quote says that if you attempt to solve for a cross browser conflict using a standards based approach it will likely conflict with jQuery code in the page. Either your approach will fail due to changes imposed by jQuery or your approach will break something supplied by jQuery. That is bad mojo.
Another problem I have with jQuery is that it encourages extremely inefficient practices in exchange for convenience. For example consider jQuery's closest method, which looks great if you don't consider the steps that execute under the hood to make that happen. In contrast using a non-jQuery approach generally meant event handlers that more directly target specific nodes in the page without all the necessary DOM walking.
I also remember jQuery frequently breaking IE back in the day. IE uses instruction count to determine if there is too much code in the page, whereas other browsers use a 20 second clock to warn on long executing code. Since jQuery does a bunch of unnecessary things and encourages method chaining those instructions counts would quickly add up and IE would stop executing code.
I have also found for many developers that jQuery is/was more of a live or die crutch they cannot live without opposed to a time saving convenience which was very off putting because developers were unreliable when things broke or when things needed to execute faster.
It's 10x the code now. 10x = 10x more space for bugs and bad design.
Use to be I might setup a handler on an input element to update a value. Now I have to write an action factory to generate an action to get reduced into a function that updates the value. From simple data.prop = elem.value to 4+ functions and a bunch deep deep overhead.
Now I'm not saying all that structure doesn't have benefits but it's also a large amount of rope in which to hang yourself.
I honestly think it's about a quarter of the code. Yes, there's a bit of ceremony around state management (but you are also free not to use Redux). But it's mostly boilerplate with a prescribed structure, so IMO it's pretty difficult to get it wrong.
On the other hand, most of the code has always been DOM manipulation, and having that declarative rather than imperative is a huge win. The alternative used to be using a template engine like handlebars, but that did a complete re-render every time any state changed, so for anything moderately complex that was too slow and you had to fallback to manual DOM manipulation, and manually keeping the DOM in sync with your state. And that was a large amount of rope in which to hang yourself
Yet we all managed to write complex web applications without much trouble that performed better than React ever can. DOM manipulation was needed rarely actually - usually you replace subtrees anyways (switch tabs, etc).
If DOM manipulation is rarely needed then your web app isn't complex, it's at most a collection of CRUD pages. UI Frameworks like React are for building UI's that accomplish a lot more than that through frequent DOM manipulation. If all you need is CRUD then templating frameworks still exist, are well maintained, and widely in use.
That's not true as soon as your UI contains conditional logic or a list of elements, at least one of which will be present in almost every web application.
> ... and having that declarative rather than imperative is a huge win. The alternative used to be using a template engine like handlebars
While React markets itself as a declarative DOM manipulation library, any kind of HTML templating system is declarative out of necessity. Why? Because they all produce HTML in the end, which is itself a declarative markup language.
In my experience, a framework atleast provides some ropes to hold onto while traversing the mess. Currently I'm stuck with a codebase with almost no documentation of a mess of legacy and new code with layers and layers of developers' opinions on top. The only way I'm able to figure anything is out is by tracing remnants of a light framework that's in place. I'm able to read the framework documentation and slowly unravel it, without it it'd be an even more monumental task!
I googled/linkedin developers that have worked on this codebase for the past decade and most of them appear to have this "rockstar developer" thing going on. They are opinionated, had heated debates (from what I'm told), and often rolled their own solutions whenever possible. Now we see the result of these geniuses doing their thing.
Just use a framework please, your homegrown solution is sucks. I guarantee it.
> Currently I'm stuck with a codebase with almost no documentation of a mess of legacy and new code with layers and layers of developers' opinions on top.
If it was originally built using a framework, what framework do you think that would be? And would it still be in active development and evolving today? How do you integrate new code in a legacy or evolving framework? My experience of this says it is not really a framework vs no-framework problem, but a problem of how to keep an applications code base healthy in a world of ever changing and evolving features, developers, frameworks and technologies. I think thats the real problem you are dealing with here, and not "hot-shot developer from 10 years back didn't use the coolest stack of that time".
And it is the problem you were hired to solve. If everything was working perfectly with no new features required to be added to the legacy code base, they simply wouldn't need you.
Yeah. But they got selected by the ecosystem because they were GREAT homegrown solutions. While Angular was an accidental success, it seems that Facebook really grasped early on what was happening with React, (we all benefited from the Angular experience, warts and all) and really put in the resources necessary to make React successful, for the benefit of all.
The only way I benefited from Angular was when all the companies who let the front-end dev come lately's talk them into using it; realized they had been sold a bill off goods and needed someone to get them out of their Angular mess. I made a good living off of getting people out of Angular 1's mess. The reality is Angular 1 was poor, it was so poor that the developers decided that they has missed the mark so much that they needed a complete rewrite to make a good product. Why people stuck with them after that is beyond me. I can still vividly remember taking over my first angular project and realizing that the devs that built it where so green that they had misused common concepts and terminology like what scope means and what state means and had conflated the two into a mess.
Angular was bad and it's ashamed that it's hype pretty much relegated better toolkits like Dojo and MooTools to the dustbin of history.
> they got selected by the ecosystem because they were GREAT homegrown solutions
While React has lots of great ideas, good marketing and the facebook brand is really what boosted its popularity. Popular does not necessarily mean great. There must be some other great homegrown frameworks out there, but we have never heard of them, since they did not start out as a facebook or google homegrown framework.
> it seems that Facebook really grasped early on what was happening with React,
This just is not accurate. React has also evolved a lot since its inception, they've just been careful about maintaining backwards compatibility compared to angular.
Ja 100% ! Ppl will argue with you and they will argue the exception not the average experience. Sure there are code messes with frameworks. I feel that ppl argue Jquery with multiple ppl and a good size project is better, just havent had enough pain. You can x my argument by 2 if its a project you join and didnt start.
> (that they only barely grasp from their 1 tutorials worth of experience)
If you're going to staff your entire corporate dev team with a bunch of green developers, yeah, things will be nasty. That's not the frameworks' fault though, that's just a straw man.
I don't think frameworks make any difference in this regard. The most important thing to remember is that developers are people. Most everyone benefits from direction and guidance without regard for their seniority. Some of that guidance can be automated by applying appropriate limits or certain safeguards to the process, but is generally not something that can be outsourced directly to a tool. I think of that as something akin to letting a television parent your child.
They do though, frameworks are just an amalgamations of patterns and practices codified. If you go Vanilla JS you are going to build abstractions on top of it to make your patterns and practices reusable and structured. Given enough time you are going to build a framework that enforces your patterns and practices. So why not just adopt proven ones out of the gate. But verify that they are indeed proven ones before just jumping on a bandwagon.
An example I would highlight is, Redux it's great and it has helped a lot of developers that don't know state patterns learn to deal with state, but it only taught them half of what they need to know. The other part of state is not allowing applications to fall into an inconstant state that it should not be in. Redux intentionally ducked this one because state management is a complex task and building a state machine makes the cognitive overhead much more complex but that is what developers following correct patterns should be doing, they should be using a state machine and it is the reason I use XState in my projects over using Redux as it is a full state management solution, that gives me a guarantee that my state is both preserved and consistent.
> Given enough time you are going to build a framework
I have heard this argument countless times over the last decade and its not based on anything. I suppose if you have never written code without a framework and for the first time attempt to write some new application it would make sense that your application ends up looking that thing you are familiar with. Beyond that this entire position is absolutely meritless.
What I find most frustrating about this sentiment is the lack of originality it codifies. Many JavaScript developers I speak with online are absolutely certain the language is limited to building static pages and SPAs. That's it. And, it absolutely blows my mind that their imagination is so immediately limited. Logically, though, since there is nothing else to build but SPAs and frameworks are great at building SPAs it must not make sense to even not use a framework. That line of thinking leaves me speechless, literally. I just spot responding and walk away.
I started with Motorola 68000 assembly in the late 70's early 80's (hobbyist not old enough at that time to work) while their where frameworks of sorts back then there really was not what we have to day. I can assure you though when you built stuff of enough abstraction you ended up with your own frameworks that helped you build new applications. Patterns of the way you do things and tried and true methods. Packaged up into reusable libraries.
You see it in every discipline, game programmers use game engines which are frameworks almost nobody is writing their engine from scratch because they don't need frameworks.
Enterprise programmers have saleforce, SAP etc. Hardly anyone is writing an ERP from scratch.
It's not that a lot of people that use frameworks don't know how to go it alone, I certainly do and most of the caliber of developers I work with certainly do. It's just that we realize we will, in the end, end up with something that looks like a framework. Because there was a day and time when that's exactly what we did and it was common practice. But that practice came with the additional overhead of training people on an internal framework, as well as maintaining documentation and the codebase of said custom framework.
It was more common and more acceptable before the internet and opensource that a developer or team would roll their own framework, create their own patterns and procedures and it was a very common practice to roll your own framework. But their where commercially available frameworks at the time for things like computer graphics, UI etc. Frameworks are a natural evolution of code reuse. The difference is today people tend to agree on third party frameworks as a standard way to develop as opposed to internally develop them. IN a effort to externalize, training, support and documentation of the framework.
I understand your frustration with developers conflating a simple page with SPA's. I only build large SPA applications I am not a web page developer, but if all I needed to do was provide a landing page, I would not use a framework because 90% of the deliverable is HTML and CSS. It's a lot of overhead to bring in something like React and the NPM build ecosystem because you have one tiny component of an otherwise static page.
Oh, but you can. It can go anywhere from realizing that your extensive enzyme-based test suite turned out to be garbage because nobody really grasped the value proposition of snapshots at the beginning of the project, to the entire application aging extremely poorly because it's written in Angular 1 that is a mix of needless directives and jQuery call hacks (both true stories).
You’re write. I’m a tech lead in an ‘enterprise’ team, and the fight against spaghetti is so real.
I feel a lot of enterprise devs are older, and more set in their ways. It’a not just teaching them new technology any more - I have to fundamentally shift their approach.
All the while being 20 years younger and less ‘experienced’ than them.
It’s slow progress. Every time I relax control within a few hours I have to bring it back. One guy today tried to set up a deployment of a prepackaged service that involved building the service (in debug configuration), then running that. I had to explain that deployments out of /bin/Debug is a bit of a red flag. I’m not sure how you can miss that myself, but here we are.
I have to explain to "senior" developers why a deployment process involving keeping the source code on the prod server and building it with Visual Studio on the prod server is not a great idea.
Ofcourse they are, I know a good bit of React and I can get a good understanding of any reasonably sized React project within a short amount of time _because_ it's a React project. People may still be people and do weird stuff, but that's a given in anything you do.
Maybe this is just a problem where I work (large enterprise SV company) but a big issue is that a lot of engineers know better but they do a shit job because they are looking to deliver ASAP so they get brownie points for finishing a task quickly. These people are just looking to get promoted fast and they will have jumped ship long before they are held responsible for the maintenance burden of their spaghetti code. At the same time, people who actually take the time to write maintainable code get the shaft because they appear to be unproductive and are "blocking" progress. Of course, a good manager can see through this but good managers are rare where I work.
This could be read the other way too.
In my experience there is a spectrum from reckless to needlessly perfectionist, neither of which approaches are very helpful.
Being focused on delivery is not necessarily a bad thing. But then I've mostly worked in small startups, so perhaps it's different elsewhere.
In my experience this is not the case if you have experienced leads and architects. Just using a framework for the sake of using a framework can be just as bad or worse.
In my experience any team anywhere can turn any codebase into soup!
Strong tech leadership that provides good examples, institutes code reviews, establishes & follows standards etc is where nice code bases come from (even in tiny teams)
A framework enforces some organization by its very nature, even the barebone ones. Otherwise they usually break. Plus, the popular ones will have a community that sets some standards, example, off the top of my head: python significant white space
Frameworks are not a substitute for engineering standards but anyone whose really interested in that, pay the bills interested, first thing they do is look for frameworks
The difference now is it's only a "wild west" as far as app structure goes. Developers still need to put a lot of thought into component composition and app state to maintain a quality code base. Previously you had to do all of that AND put a lot of thought into how to update the UI correctly and efficiently. New approaches and frameworks removed the complexity of that last step.
Sometimes I question if people claiming vanilla is spaghetti have actually used vanilla in any meaningful way or if they are just parroting what others have said. I find that a lot of times, it's the latter...
For example, something that I've come to find cumbersome about frameworks is that expressing things in terms of states makes it more convoluted to express mutations. For example: in vanilla, one sensible unit of organization would be something like this:
Expressing `input.value = value` is what frameworks generally shine at, but expressing the method calls is usually clunky, since they represent effects and those can't really be expressed in terms of state snapshots. So, expressing them in a "frameworky" way usually just looks like some variation of this, but on top of some abstraction (think, e.g. React's useEffect nested anonymous functions + refs + probably context and a provider because you're not going to just initialize your sound manager in your component, right?).
I think frameworks are about colocating things in some specific way, and whether the colocation structure is "good" is largely a matter of herd acceptance. W/ older frameworks like Backbone and Angular, the focus was on colocating things to fit a MVC paradigm. And people were totally on board with that. With Redux, one colocates actions for a particular piece of state. And people sing their praises about this structure too.
With reaonably written vanilla JS, it's not that there's no colocation. One colocates mutations related to a single action. It may not be a "cool kid" organization structure, but it _is_ structure.
Of course, one can write bad vanilla JS, but that's also true about any framework.
a) that doesn't do the same thing (button != input)
b) in React, it's extremely bad practice to mutate raw DOM elements programmatically (the idiomatic version is to use some state management mechanism and bind the value via `<input value={value} />`, which incidentally would be broken by this code)
c) setState may be asynchronous, so you can run into nasty surprises (e.g. you can't focus a hidden element). Whereas in vanilla code, unhiding logic could be added in a predictable procedural and explicit manner, in React a naive call to .focus() in the event handler may noop because of React-rendering-pipeline-specific reasons and then we need to get into its more obscure APIs to fix it)
Which is almost identical to how you would do it in vanilla JavaScript except you would grab input by a query selector and be less resilient against DOM mutation and your references becoming stale.
To point b there's nothing wrong with having an uncontrolled input. React allows you to use the raw DOM API if you'd like. You only need to use controlled inputs if they buy you something, and then the rewrite is a small diff:
This is adding a line of code (useState) but in this case it's buying you something -- you have full control of the value and are insulated against DOM updates.
For point c I'm not sure what you're referring to. I can't think of a situation where React would drop your call to `input.focus()` on the floor. I just tried breaking it by spamming state updates and was unable to. The whole point of React is that it handles DOM updates seamlessly and I would be surprised if it didn't in this case.
Sure, if you're using a ref and being careful not to bind `value` in JSX, you're fine. That's not what you were doing though. Here's a simplified demo showing a variation of the issue: https://codesandbox.io/s/react-example-bytg0
As for controlled/uncontrolled inputs and refs/hooks: that's kinda my point. In order to declaratively wire things up in an idiomatic way in React, we've had to introduce a bunch of React APIs to the snippet just to express the equivalent of a "when you click me, focus that guy" action -> effect relationship, because otherwise that relationship is hard to express in terms of declarative state snapshots.
You've misspelled the handler, onClick is the correct casing. Fix that and it works.
Also you don't need to use a ref -- if I were inclined I could have grabbed the element by a query selector. I'm not sure why I would though, as I mentioned using ref is better protection against DOM updates.
> In order to declaratively wire things up in an idiomatic way in React, we've had to introduce a bunch of React APIs
Yes, because declarative programming is the benefit not the cost. As I said, you don't have to do it declaratively -- you can always use built-in DOM APIs -- but most people in the front-end community have agreed that doing things declaratively and architecting a UI as a state machine instead of a giant tree of independently mutating bits is preferable.
One of the biggest sources of bugs in jQuery projects is developers forgetting to keep the DOM in sync with the data. The benefit of doing things declaratively is you don't have to worry about it. Cutting that problem off at the source is an invaluable benefit.
It's a person well-steeped in the theory and benefits of declarative and functional programming taking a step back and looking at the supposed enemy with fresh eyes and a deeper perspective.
Why does everyone seem to be using the first format? Isn't the second version a lot more readable/pretty? Even worse is when doThing is immediately exported and not refferenced anywhere else, but still there is this need to assign it to a const.
1. You can implicitly return things so it provides nice syntactic sugar
2. Using an arrow function results in `this` being bound in the way you'd expect (coming from something like C++) in all cases without having to call .bind(this) anywhere. I'll never forget seeing promise chains starting with `const that = this;` in order to keep the right reference throughout the promises.
3. You use it for the previous 2 reasons and use it everywhere in order to be consistent
I fall into category 3 which is why I list it. It's not a technical reason so much as a code style reason so it is definitely subject to the opinions of each developer.
For example, an arrow function accessing variables outside its scope is much slower, something you will notice when processing a lot of data in nodejs.
And if you're working in the browser and trans-pilling down to ES5, babel needs to do a lot more work.
But as long as people are aware of the trade-offs, they can use whatever works for them.
> Looking at your comment history, seems like anyone who technically differs with you gets downvotes, I'm sure that's not how it supposed to work, bring it on anyway.
Probably a side-effect of what I usually choose to comment on, which are things that are objectively wrong or seriously misleading :) I think the HN voting system is poor, so I don’t use it, myself.
> Remember, an arrow function shares the same scope with [its] parent function
Exactly like a non-arrow function, then?
> Do you have any evidence to the contrary? I have experienced it when processing heaps of textual data in nodejs (the same engine that runs chrome). My script was crashing for no apparent reason, and just changing the arrow functions solved it.
Not only is that not evidence, it doesn’t support what you originally said. Slower ≠ crashing for no apparent reason.
If you mention which version of Node this was, I can go looking for evidence.
> Probably a side-effect of what I usually choose to comment on, which are things that are objectively wrong or seriously misleading :) I think the HN voting system is poor, so I don’t use it, myself.
Do you have any evidence that you do not use it?
> Remember, an arrow function shares the same scope with [its] parent function
>> Exactly like a non-arrow function, then?
No, not exactly. It looks like I need to be more explicit, here goes: Remember, an arrow function's BODY shares the same scope with its parent function
> Do you have any evidence to the contrary? I have experienced it when processing heaps of textual data in nodejs (the same engine that runs chrome). My script was crashing for no apparent reason, and just changing the arrow functions solved it.
>> Not only is that not evidence, it doesn’t support what you originally said.
It is called ANECDOTAL evidence, and yes, it is a thing. If you want SCIENTIFIC evidence, sorry I just do not have the time and energy. If you want to believe that arrow functions are a drop-in replacement for normal functions and that they are always better and faster in all situations, go ahead and believe that. And you'll do just fine, as long as all you are doing with JS is React and basic UI wrangling stuff.
> Slower ≠ crashing for no apparent reason.
My friend, this is a discussion, not a scientific thesis or a legal document. I do not have to explicitly explain every little detail and cover every little phrase so that someone does not misqoute me. Be generous enough to try and understand something someone is saying. So, to rephrase that too, when I say "crashing for no apparent reason" I mean "crashing for no apparent reason that I could find by looking at the code over and over again searching for bugs or typos". And yes, it was crashing due to timeout and memory issues. Please dont start arguing about how crashing and timing out are not technically the same thing.
> No, not exactly. It looks like I need to be more explicit, here goes: Remember, an arrow function's BODY shares the same scope with its parent function
Exactly like a non-arrow function, then?
I don’t mind if you don’t have the energy to support your claim, but I will recommend that you don’t make claims like “arrow functions are slower” if you can’t back them up properly or even provide any detail.
I also get the impression that you don’t know how arrow functions actually differ from non-arrow functions (see above), so your anecdote that you couldn’t figure out the bug doesn’t make a strong case.
> Do you have any evidence that you do not use it?
My browser was crashing for no apparent reason and stopping voting on HN solved it.
It is both method and closure. Which is not universal - io has method and block, ruby has def and block
And it is constructor. So it can be called both with and without `new` with different results. Other can't:
arrow = () => {}
// new arrow()
// TypeError: arrow is not a constructor
object = {
shorthand() {},
['computed']() {},
get getter() {}
}
// new object.shorthand()
// TypeError: object.shorthand is not a constructor
// new object.computed
// TypeError: object.computed is not a constructor
// getter = Object.getOwnPropertyDescriptor(object, 'getter').get
// new getter
// TypeError: getter is not a constructor
class Class {
static staticMethod () {}
method () {}
get getter() {}
}
// Class()
// TypeError: Class constructor Class cannot be invoked without 'new'
// new Class.staticMethod
// TypeError: Class.staticMethod is not a constructor
// klass = new Class
// new klass.method
// TypeError: klass.method is not a constructor
// getter = Object.getOwnPropertyDescriptor(Class.prototype, 'getter').get
// new getter
// TypeError: getter is not a constructor
function* generator() {}
// TypeError: generator is not a constructor
// new generator()
I actually was surprised just how many ways TC39 introduced so we do not use function. The change you observe is not a coincidence - it is carefully crafted.
Let me get this straight: Are you saying all the changes in arrow functions, the class syntax and generator functions were all a carefully planned initiative to get rid of the "function" keyword because it does too much?
>> Yes, <typo>they</typo> replace<typo>d</typo> "function" usage with safe alternatives. And don't forget 'use strict' - it affected "function" too.
> I'm not convinced at all
It could appear I've tried to convince you not to use "function". That never was the case, should have added at least one. And I do not agree with TC39 direction, just making observations. Please check my comment assuming that and typo.
My fix would be different. Prototype based inheritance is awesome http://iolanguage.com/tutorial.html and javascript could be as simple too:
Object
Object.__proto__ === null
object = new Object
object.__proto__ === Object
object.constructor === Object.constructor
object.toString === Object.toString
f = new Function
f.__proto__ === Function
fun.constructor === Function
object.private = function () { return 'hello' }
Object.shared = function () { return 'world' }
Object.constructor.static = function () { return '!' } // we need functions
with just a simple change
Object = Object.prototype
Function = Function.prototype
syntax new = function (ctx) {
let ident = ctx.next().value
return #`new ${ident}.constructor`
}
It looks almost boring (just don't redefine .constructor). Now this one is much harder:
Object.prototype
Object.prototype.__proto__ === null
object = new Object
object.__proto__ === Object.prototype
object.constructor === Object
object.toString === Object.prototype.toString
fun = new Function
fun.__proto__ === Function.prototype
fun.constructor === Function
object.private = function () { return 'hello' }
Object.prototype.shared = function () { return 'world' }
Object.static = function () { return '!' } // we need functions
Anecdotal if you're interested: I can't show it since it belongs to the company, but I just ran a grep in the app I architected and it has exactly 21 instances of the word "function"... some are comments, but most of the ones that aren't are inside a lodash debounce function. Total of 140000 non-blank/non-commented lines of code.
Btw, it's not banned, and I never really enforced it... but since I never use it myself, I guess the others devs picked it up?
It's in Vue.js, and in Vue you rarely see old-style functions anywhere, so there's that.
That's interesting. However, the Vue.js library itself uses the "function" keyword a lot, and the library is part of your applications code. Infact, it uses normal functions almost exclusively.
Furthermore, the official Vue documentation explicitly discourage the use of arrow functions in some places, so whoever set that rule just did not know what they were doing, sorry if that sounds harsh.
Saying all arrows functions are bad and evil or that all normal functions are bad and evil is nothing but dogma. Each has its own place and uses, it seems many JS devs would rather not think of this at all and just use one form everywhere.
We're not using arrow functions for everything. Why are you assuming this?
We're using shorthand syntax in methods inside Vue.js objects [1], they also don't need the "function" keyword. In fact, they are suggested in the second link you posted, please read again. Arrow functions wouldn't even work in this situation.
We're mainly using two forms: shorthand and arrow. That's how we only have 21 instances of the "function" word in our entire JS codebase, and we could remove all of them if we wanted. That's what you asked for: a "JS app that completely bans the 'function' keyword". Well, we don't ban but it's possible.
And please read my comment again: I explicitly mentioned that this is not a rule, and I never enforced it. The team (39 committers ATM) reached that result organically, mostly influenced by my own personal style.
And sorry if this sounds harsh, but it seems that you have extremely limited knowledge of Javascript and ES6, so I'd suggest learning before you make such claims before you make a fool of yourself.
Btw, you're seem to be the one holding on to dogma here, since you seem unable to accept that the keyword is not strictly necessary in a large app.
First of all, are you aware of shorthand methods? Are you aware that you can have non-arrow functions without the "function" keyword :) ES6 has grown :)
And there was no goal intended with the grep. This is what you wrote:
> And I'd love to see the codebase of a JS app that completely bans the "function" keyword
I just grepped "function" to give you a personal anecdote of an app that doesn't need to use the "function" keyword much.
That was the first time I interacted with you, I was trying to be nice then, and you were completely hostile. Some of the replies were completely uncalled for.
---
EDIT: You just edited your message to add the part about shorthand methods. My point still stands. I never claimed to be only using arrow functions (in fact, you're the one who DID claim I was only using arrow functions!). I only claimed we rarely use the "function" keyword.
No, and part of the reasoning is to explicitly avoid the chance you might accidentally refer to the wrong `this`. There's an ESLint rule to enforce this: it will complain if you use a `function` without referring to the prototype this. Makes it handy because if I do use `function` I know it's because there's a reason -- e.g. some libraries still make heavy use of the local this.
The problem with frameworks like React is that the version you’re using and its API will become outdated in no time. We started using React in 2014 and their approach to state management changed at least three times since then. Not to mention build systems, tooling and libraries. In my experience that leads to a large fraction of developer time (10-30 percent I’d say) just going into often pointless refactoring that is necessary to keep up with the framework ecosystem, because you don’t want to run “legacy code”. Most large organizations seem to accept that but for smaller ones it can be quite a burden.
The beauty of the native JS APIs is that they are relatively stable: things that worked 10 years ago still work today, and can be done in the same way. Also, standard adherence in browsers has become much better so if you do not need to support legacy browsers like IE you can get away with writing pure JS without any polyfills or frameworks.
When has React's approach to state management changed?
The only change I know of is the introduction of the useState hook, but you don't have to use it.
The React team has done stellar job of maintaining a stable API with very minimal breaking changes. The only major breaking changes I can think of is the move of React.createClass to react-create-class and replacing the lifecycle methods through a slow and steady push over multiple major versions. I'm sure there were some smaller ones, but nothing that required any significant amount of time to fix.
As far as build systems and tooling, that's only as complex as you want it to be and doesn't have to change with the seasons. I've been using the same Webpack/Babel/React setup on one of my projects for about 7 years now with minimal work on my end (the only major upgrade was Babel 6 > 7, and Webpack 2 to 3, which took about maybe half a day to complete both).
Talking about global state management (not local state/props), when we started working with React their recommended method of state management was via Mixins. Those became deprecated in 2017 (I think). They then recommended to use only higher-order components (HOCs) for state management. Last year they deprecated this in favor of hooks. The context API has changed several times as well, though since that was never meant to be an end-user API I think it's less problematic. They also deprecated a bunch of life cycle methods (e.g. componentWillMount), though that is probably also a minor nuisance.
As you said you can still use the old ways of managing state (except mixins I think which were really removed for good), the thing is just that most of the ecosystem of third-party libraries (routing, state management etc.) quickly moves to the latest paradigm, so if you do not want to run outdated code with potential security vulnerabilities you will need to constantly refactor your code as well just to keep up with the ecosystem.
You're conflating several different things: patterns specifically recommended by the React team, patterns in vogue in the community, specific libraries from the community, and actual API changes in React itself.
The React team did definitely tell folks to stop using mixins and try using HOCs instead [0]. HOCs have some limitations as well, and hooks are designed to help address those [1], but it doesn't mean HOCs are suddenly broken and you can't use them.
React's actual APIs are quite stable. As the React team has pointed out, Facebook has something like 100K components in their codebase, and many of those are still using older APIs. For example, even `React.createClass` still works. Granted, it was moved to an external package `create-react-class` package a while back because it's discouraged, but the API still works (and that's what had mixin support).
The community jumped on render props, and the React team never specifically recommended them as a generally-encouraged pattern that I know of. The only example of render props in React's actual APIs is the `<Context.Consumer>` component.
The context API never "changed", per se. There's the original `this.context` API, which is now definitely considered legacy and deprecated, _but_ it still works fine as of React 16.x. The new `createContext()` API, added in React 16.3, is a new API that solves the same use case.
The deprecation of lifecycle methods is real, but the React team has been warning about that for a while. Note that even in future code, renaming them to `UNSAFE_componentWillReceiveProps` will still work, and the React team has provided codemods to make that fix if you want to keep using that code as-is.
The churn in the resulting ecosystem is a more valid point of concern. React-Router is a frequent target of complaints. That's _partially_ justified, as their API has changed a couple times.
As a Redux maintainer, I'm very happy that we've managed to keep the React-Redux API stable across multiple major versions and internal rewrites [2]. If you were using React-Redux v4.x, you _should_ be able to jump to the current v7.x just by bumping the package version.
Well, I'm glad you're happy with your work, just describing my epxerience working with React over the years and the frustration of having to keep up with an ever changing flow of changing paradigms and programming styles. People value different things in frameworks, for some frontend developers it's probably exciting that the community comes up with so many new things all the time and that they can learn a new state management paradigm every year and spend time refactoring their codebase, for me it's more a nuisance.
The problem of React is not that the core API is not stable, but that it's not a full framework for developing frontend apps as it misses e.g. routing and app-level state management, it only becomes useful in combination with libraries that provide this functionality (unless you want to write your own, which is also an option). It's the rapid pace of churn in the community eco-system that's a problem for me. Probably I'm just getting old.
I agree with you about the React team being very careful about maintaining backwards compatibility as much as possible. The API is however still a moving target, and some patterns or ways of doing things are actively pushed more than others. For example you can still use mixins and createReactClass now without any problems, but the docs and tooling all have one recommended way, which slowly shifts over time.
The problem just isn't with React though, I think the problem is with the culture that expects an opensource project to always be constantly evolving and putting out new things. I'm guilty of it myself... when checking out a library in github and I notice it hasn't been updated in awhile I get suspicious of it.
You're conflating several different things: patterns specifically recommended by the React team, patterns in vogue in the community, specific libraries from the community, and actual API changes in React itself.
This is fair, but I'm not sure how much it matters.
In reality, we build software as part of an ecosystem. Even if the foundation of an ecosystem remains stable, much of the value often derives from what is built on that foundation. It's the other tools. It's also the blog posts and forum comments and training courses and YouTube videos. It's also the collective experience of the community in using those tools, which is reflected in all of those sources of information, as well as simply passed on from one developer to another in person.
I'm not sure React can truly claim to be stable any more, though it's certainly done better at that than many projects in front-end web development. But even if that's true, the community has moved on from the older APIs to the newer ones. The new resources are built using the new APIs and written about the new APIs. If you're still using the older version of things, even things that React itself still intends to fully support, the reality is that you're going to be excluded from many opportunities elsewhere in the ecosystem.
Why would you want to use the old APIs for new code? Surely the benefit of API stability is that your old code that you don't want to change still works? It's not like they're introducing new things every week. It's more like once a year there are major new features, and the old ones still work.
Why would you want to use the old APIs for new code?
Consistency. A code base that has been maintained for several years but now does similar things in four different ways because of which APIs were fashionable at the time each of them was implemented isn't going to be great to work with.
Or maybe you just liked the old APIs better, perhaps because they were more helpful for your particular application than the new ones, or because some other tool or library you find useful works better with the old API.
Browser APIs have changed quite a bit in the last 10 years. Yes, the same approaches are still supported, but there have been many additions and modifications to core APIs. Ten years ago you would have never dreamed of trying to build complex front end behavior without something like JQuery, but now it’s totally unnecessary as all browsers mostly adhere to the standards. I guess my point is I don’t think React has changed any more or less than browser APIs - both have just steadily updated best practices just like any other piece of software since ever.
Just because the APIs remain largely backwards compatible does not mean that they didn't change. Just the fact that querySelector and querySelectorAll was introduced and started actually being usable across all the major browsers is a huge change IMHO.
This. Framework maintenance is something that takes a lot of time from our development team. Compared to other ecosystems (Python, Java), the frontend teams spend much more time dealing with updates to their stack (webpack, react).
Once a year I update my webpack, React, and TypeScript versions. And this is for a completely custom webpack toolchain. I don't think that's unusual compared to other technologies.
I think the main pain point is towards front end appearance/interactions. Js as a language has gotten more ergonomic, but it's been Turing complete forever. As a practical matter, the pain comes when you say "I want to align x" and come to learn that every browser has different flags to accomplish the task. I'm sure you've seen the fat stacks of moz/ie/opera checks and flags before. I know that example is bad, but I can't think of a good one at the moment, I rarely touch front end.
If you don't refactor and update your dependencies regularly you can easily end-up in a corner.
You can be hit by a bug in your dependencies, be it a functional one or a security one, but if your dependencies are completely out of date and there is tons of API incompatibilities between the version you are using, and the version implementing the bug fix, it will be really painful and take a long time to update, with stakeholders breathing down your neck expecting a fix asap.
Also, maintaining old tool chains can be a real drag (maintaining older building hosts, developer machines or VMs).
Updating frequently to be near enough the latest version is generally preferable.
In theory yes, but in practice even with frameworks codebases can turn into messes, and/or tends to become solid but completely frozen on a particular feature set. Small changes suddenly becomes daunting because the initial architecture needs to be changed to accommodate and surprise all is tightly coupled under the cover. With vanilla JS and spaghetti it's painful and boring but at least if I need to change a behavior on a page usually I'm done with a few lines of code. Edit: it's a tradeoff, but in early stages I found being able to make one the fly changes in a few minutes/hours to accommodate a customer instead of weeks (or never if it's too painful to evolve the perfect architecture) very valuable.
It really depends on the use case, and sure frameworks are awesome in the right context, but I think the current "best practice" of defaulting to one in any project no matter the business trajectory, product market fit maturity and team size is misguided.
At my position, there are at least 5 different interpretations of how to do React. Each project has an overseer who enforces a particular philosophy/design. JS frameworks are frameworks. They don't make the problem easier, they just change the terminology and add new abstractions which inevitably turn into angel hair pasta.
React is not a silver bullet. It solves one problem and it solves it very well: dealing with dynamical updating DOM views. There are still many different ways to architect your application but it stops the bikeshedding and reduces the opportunity for bugs at the view layer.
Agreed. This is my main issue with the "you don't need frameworks" rhetoric.
If you're a small team or a solo dev working on a simple app, and you know the source code very well, frameworks might not be the best choice.
However, if you've ever worked on a team of revolving contributors, constantly shifting requirements, or have any reason to reuse code across apps/repos, frameworks help immensely.
The biggest benefit to using something like React imo, is that when we hire somebody familiar with React, they can hit the ground running and start contributing immediately. Unless your app is dead simple, you won't be able to have the same velocity in a homespun framework (and given enough time, most "vanilla" apps turn into homespun frameworks).
> when we hire somebody familiar with React, they can hit the ground running and start contributing immediately
This is one of the selling points, but never really realizable in a large scale project. I've seen people become productive with an in-house template system, vanilla javascript + custom libraries even faster than on a "standard" React project.
As they emphasize in their own docs, React is not a framework. The amount of moving pieces you need around it for a working project ends up being more complex than your cut-to-size custom framework. There are many other positives to adopting standard tools, but this one is a red herring.
We've adopted a framework as a small team and it has nothing to do with onboarding new people. We adopted it became clear that if we stuck with vanilla JS, we'd end up re-building something like jQuery to keep our code and abstractions manageable. And then we'd build something like React, while doing a much poorer job of it. Once your app has some "click X and A, B and C should update" logic you quickly descend into a tangle of tracking dependencies by hand.
> Once your app has some "click X and A, B and C should update" logic you quickly descend into a tangle of tracking dependencies by hand.
I managed to deal with moderately difficult scenarios with about 7 files in typescript. I ended up using webpack but that is a dev-dependency which doesn't really count.
I built this for me, but if you employ some basic patterns and use something that is a little more powerful than JavaScript it isn't that hard. I also very rarely ever use a DOM selectors in my JavasScript.
I don't particularly like frameworks these days because you end up spending more time dealing with the framework than actually getting things done.
You could learn to pick better frameworks. I can’t remember the last time I dealt with a framework bug in react and I’m working on multiple teams on about two dozen web apps. And that’s without including other jobs.
It sounds like you’re not really working on apps frameworks like react are supposed to deal with, (7 files of typescript) so why do you care?
> You could learn to pick better frameworks. I can’t remember the last time I dealt with a framework bug in react and I’m working on multiple teams on about two dozen web apps. And that’s without including other jobs.
I have used quite a few frameworks over the years and there is always some PITA issue you have to deal with.
> It sounds like you’re not really working on apps frameworks like react are supposed to deal with, (7 files of typescript) so why do you care?
You don't need large frameworks to scale something. You can just do it with applying the right patterns (that these large frameworks use) and get 80% of the benefit. However that requires (shock and horror), thinking for yourself and learning how things work properly.
Could you share this? I'm a backend developer and I just want to make light frontends with flexbox, grid and javascript. But it'd be nice to scale to more complex UIs also with a few functions.
Just use vanilla JS to begin with. If your app has a lot of interaction, you can use React with create-react-app makes things easier.
You can still use vanilla JS, HTML and CSS. And it's not morally wrong.
Assess the requirements. Lots of moving parts and not a whole lot of time? React or Vue lets you draw the big lines quite simply. Need something simple or with fancy animations? Vanilla may be your best bet.
Personally I use vanilla for simpler stuff and React for more complex apps.
Don't worry, just make cool stuff. Nobody ever cares how you built it, just that it works.
Trello still uses CoffeeScript. It really does not matter as long as it works.
It's similar to how pub/sub works but it does the topological sort that prevents data with diamond shaped dependencies from being triggered twice, in less than 500bytes minified (before zipping).
"descend into a tangle of tracking dependencies by hand."
What is your definition of "by hand"? What constitutes by hand and what does not constitute by hand?
My definition is declaring each dependency explicity. "A, B and C depend on D or E." Add a watcher on D and E to go update A, B and C. Repeat for every combination of dependencies. When app is complex enough I threw that away for a framework that tracked dependencies for me.
Sorry, I don't understand. How would the framework know what the dependencies are if you don't declare them, even indirectly in some fashion? In what sense are they dependent?
Isn't this also simply true in the corporate world in general? Frameworks and best practices of doing something means that things are standardized. Standardization means that a vocabulary is shared and people understand each other.
You want to make people as swappable as possible. At least that's how I look at it from a management perspective (not a manager, but one can dream).
Not necessarily. Using popular frameworks will always widen the pool of contributors you have access to, no matter what "sector" your project falls under.
The problem is every dev thinking that every single project has to be resume buzzword compatible and super complex to hide the complexity they're sure is coming. But these requirements really only occur if you're forced into them by working on something in order to make money. The web is more than just the commercial web.
I'm using far more ridiculous, buzzwordy and complex tools in my non-commercial projects though. (In fact, that's usually the point of those projects.)
>In fact, that's usually the point of those projects.
And are you doing it because you truly enjoy the needless complexity or because the buzzwords would look good on your resume? If the later, again, that's profit motive and commercial web. Like how the only point of using kubernetes for personal stuff is to learn kubernetes for non-personal stuff.
> The problem with vanilla JS is not APIs, API is the easy thing.
Then the problem is really the API, if one needs to write tons of helpers just to make that thing bearable. Never had to write a framework on top of QT or WPF just to develop apps on these platforms. Web Components tries to make things a bit easier by allowing people to write their own widgets that know how to clean up themselves when removed, but it's not there yet apparently.
IMHO what the DOM needs is a good DOM diff API directly included in the browser. Right now it's either modifying DOM nodes themselves manually or just innerHTML string trickery, when wanting to update an entire tree of DOM nodes.
events are already a solved problem thanks to event delegation. It's DOM modification that is still painful.
This list of recipes doesn't solve the large front-end app at scale problem.
So personally right now, all I need IS a DOM-diff library. Using external widgets is a bit trickier, but with event handlers I can do required instantiation and clean-up provided the third party widget has the necessary event hooks.
> Web Components tries to make things a bit easier by allowing people to write their own widgets that know how to clean up themselves when removed, but it's not there yet apparently.
WCs aims to replace a lot of what is now React. As is "just the view and some encapsulation. With a the litElements lib (or some other) you also get some life cycle callbacks.
> This list of recipes doesn't solve the large front-end app at scale problem.
It did not claim to either.
My 2 cents: that problem is prolly going to be fixed by writing code that compiles to JS (or WASM). JS was the problem all along for big codebases; too quirky, too little safety, very easy to make mistakes.
> Diffing isn't really needed - usually you either replace a subtree completely or change a few attributes, which isn't hard to write code for.
Replacing the entire page on model change doesn't work for interactive forms and I don't want to micro-manage every attribute. My model drives the view automatically so diffing is necessary. The memory cost isn't that big if the diff algorithm is implemented efficiently.
The problem is that the Wild West and unnecessary complexity has just been shifted up a level or two as devs are now facing the Wild West of frameworks, de ops has turned into a monster with an unnecessary large toolbox.
It really depends how much complexity you shift to js - if most of the work is done on the server, you really don't need to lean on js very much and you can have relatively simple js which just annotates certain elements and updates content in response to user actions. You don't need a framework if you're not trying to shift the entire view layer to js.
>The problem is building proper architecture, so code won't quickly turn into spaghetti [...] With vanilla JS it's the wild west.
This is a "problem" that I solved for myself years ago. It's not even that hard. I've started by noting that most of the issues with JS come from a few sources.
- Managing code dependencies.
- Navigating DOM. (Manipulating DOM is trivial.)
- Managing events.
- Synchronizing JS state with DOM state consistently.
If you pause to think about those, each of them has a straightforward solution that does not require a framework.
- Do not make libraries that directly depend on external code. Use DOM and HTML events for configuration and communication.
- Use CSS queries.
- Use timers or document-level events. They will continue to operate regardless of how elements change.
- Use DOM as your state storage. (Custom attributes + occasionally symbols.) This way your code itself is completely stateless.
There is more to it, but this is the foundation.
One of my favorite libraries is one that checks for specific attribute that contains a CSS query, then runs it, then outputs the result as a parameter on the original element. Couple dozen lines of code, countless applications. Best of all, you don't have to write any page-specific glue code. You load the library and it just works.
I hope then someone in your team is responsible for continuously documenting these patterns, however trivial they may seem to the author. I use frameworks for their documentation more than anything else. Maybe it's the UK developer culture but I haven't come across any codebase that has even remotely useful documentation in the past five years in three jobs. These "intuitive patterns" only exist in the senior dev's head. New comers have to either constantly ask or figure it out slowly by going through source files. Homegrown "simple and intuitive" solutions only benefit the rockstar who wrote them, not the other members of the team who are there now and who will come after the rockstar is gone.
Please use well documented frameworks, otherwise we're trading away the entire teams productivity in favour of the rockstar to have his say.
This is a real problem, but I'm not sure the root cause is that senior developer.
We've been building software far more complex than any web front-end for many, many years. Much of it was built without the help of all-encompassing frameworks. Much of it has stood the test of time longer than any web app, too.
Doing this requires a basic understanding of general programming principles from all developers. It requires a solid understanding of software design and architectural concepts from at least the more senior developers.
These things aren't rocket science. Millions of developers around the world have these skills. Many books and conference talks and training courses have been created to pass on the knowledge and the important ideas behind it.
Unfortunately, lots of people get into web development without ever learning even the basic skills of their trade. They learn by copying and pasting snippets from Stack Overflow or some YouTube video they found, jumping from one trendy framework or tool stack to the next every five minutes, with no awareness that those snippets were often also written by people who never learned the basics. Rookie mistakes are everywhere, and the culture often favours shiny new things over solid, well built solutions to real problems.
You can't really fix this just by getting developers to use a well-documented framework. For one thing, a lot of those frameworks aren't great themselves, either in their design or (not coincidentally) in their longevity, because they too were written by people with limited experience and understanding. But even if you do find a good framework, if your developers don't understand how to use it and the trade-offs it makes, they will still make dumb mistakes. When you have requirements that can't be implemented by just joining one framework dot to another until you're done, you definitely want someone who knows what they're doing writing that code.
As is often the case, the key to improving this is probably better training, particularly in the early stages of a career. But that doesn't always work in business, where resume driven development means developers will stick around long enough to add a few buzzwords and then jump ship to a better paid job somewhere else, taking the value of any accumulated experience with them. Until businesses start looking for real skill instead of buzzwords when they're hiring and start rewarding real and growing skill with their compensation packages, unfortunately the cycle will continue.
I disagree with storing your state on the DOM. Querying the DOM can be pretty slow, but also now you're state is going to be stringy-typed which will involve parsers and a whole mess of reasons you don't want that. If you want to keep the logic simple, a view should be a function from a state/model to some 'visual' representation (be it DOM, canvas, Qt, ASCII, a quilt pattern, etc).
A DOM node's attributes are strongly typed, but it is an object and you can still set Node.foo = barObject if you're so inclined. Not saying it's not without it's tradeoffs, but if you want state housed in the DOM rather than another state manager it's not hard to conceptualize.
What is the library you use for running functions based on CSS query?
I am working on a project where I initialize some DOM elements with data- attributes and control their visibility in response to a form input change event. It would be nice to somehow run the visibility check in more of a declarative/reactive manner without having to commit to writing my templates with a front end framework and build tooling.
Are there any reactive JavaScript frameworks that treat DOM and data- attributes as first-class citizens?
>I am working on a project where I initialize some DOM elements with data- attributes and control their visibility in response to a form input change event. It would be nice to somehow run the visibility check in more of a declarative/reactive manner without having to commit to writing my templates with a front end framework and build tooling.
Here is an approach you can use:
const name = 'check-if';
const aState = name + '-state';
run();
function run() {
document.querySelectorAll('[' + name + ']')
.forEach(update);
setTimeout(run, 50);
}
function update(target) {
let selector = target.getAttribute(name);
let matchedSomething = document.querySelector(selector) !== null;
if (target.getAttribute(aState) !== matchedSomething.toString()) { //only update when change is necessary
target.setAttribute(aState, matchedSomething);
}
}
This exact code can be used for any styling based on any CSS query. It only allows one rule per tag, but in practice it's usually sufficient. In case you need multiple rules, you can wrap the original tag in another one. You can use data- attributes instead of customs, which will simplify the library somewhat at the expense of HTML readability.
You can use the same approach for enabling/disabling inputs.
If you need more fine-grained information to act upon, you simply write another library that adds it to DOM.
I'd say the bigger problem with vanilla JS or any other imperative UI framework is exactly that, the imperative nature of these tools. React introduced the frontend world to a declarative approach for keeping the DOM in sync with your state. Until we have something similar in the native API, React and co. will continue to exist.
Frontend development is a tricky beast because its hard to separate business logic from view logic. Since all your code relates to the view, its temping to just stick all your code into the view component or controller. This makes your components huge, untestable, and brittle. An great frontend developer will keep extracting models and business logic from view code until the view code is lean and really only renders. Some things are easy to extract like http calls or parsing logic. Other things are harder to see - like logic that might drive a step wizard. Even code like this can be expressed in plain models with plain functions, but its a lot harder to see and extract. Most people don't get there, or just don't care, so many frontend codebases end up with spaghetti view modules that you edit and pray things still work.
THIS a x1000 THIS !! There will never be a perfect framework, and jquery for a multi-person big project. It WILL be a mess in due time ! a Framework(even the most of the crappy ones) at least give you some opinionated standard ways of doing stuff. You can't pay me enough to work in jquery straight... Not saying it can't happen with frameworks. Just saying if you do a 100 projects with jquery or 100 projects with frameworks... There will be more chance the jquery ones will be a mess.
I learned jQuery on a project where everyone was expected to be full stack but only 2.5 of us could do any deep work on the front end.
I have done much, much harder things than convincing my coworkers to distinguish between 'important' nodes in a composition and incidental ones. Never put the incidental ones in your selectors.
If I'm a "Select All" checkbox, I need to find all of the checkboxes in "my" block of HTML that are not me, and select or unselect them. I don't give a shit if that's two divs up, one over and three down. Or if some IE bug means now it's three divs up and two over. I care about some top level element, and any of its children at any depth.
That's it. If I write my element selectors that way, I'm done and the layout people can put in a scrollbar later, or an expando. Also if I write my CSS the same way, it's easy to make these sorts of changes and it's easy to correlate the CSS with the Javascript that affects the same elements.
So much simpler than spending all day in a debugger when you're not in bug triage.
Most of those query selectors we relied on now have feature parity in the spec. I don't see why you couldn't use the same strategies in a vanilla situation today.
Could you expand upon what you mean when you say a checkbox has "my" block of html? That a given element should not make changes in elements that are at a higher level in the tree?
There are a bunch of elements we add to the page or remove to get certain visual effects to work well but they really have nothing to do with the logic of the page. Few if any interactive components ever care about them, or only for one specific interaction.
Classic example of the 'only one interaction' situation: the coworker who thinks he can use string concatenation for query parameters and you know that if you just wrap it in a form element, all of that is cheap or free and you just have to hook the form submit event to turn it into an AJAX request instead of a navigation. But that means that you've wrapped all of his DOM in a form element and now all of the CSS and half of the handlers stop working because they're looking for body>div>div>option and now it's body>div>div>form>option and now you wish you hadn't even touched this stinking pile but it's the principle and by god you're gonna finish this.
Or you had a block of elements on a page and now your boss wants it on the other side of the page, on another page, on every page, all over this page, or on a completely separate site.
What you want to solve these problems in a way that mostly stays solved is to try for a query selector with the lowest specificity (and no IDs) that still exactly identifies the DOM elements you are looking for. So there is some titular 'owner' element that all of these interactions are contained in, and they find each other by walking up until they find a particular shared parent and call parent.querySelectorAll() to find their peers, and only their peers. Not some other random element halfway down the page.
So for instance a click on .preferences .selectAll should find the first parent with class 'preferences', call querySelectorAll(".options"), and then invoke foo.selected = true on all of them. Not parent.parent.parent and then down through div>div>ul>li>input[type="checkbox"]
On the topics of speed and lightness: does Svelte really have a proven track-record in real-world usage at this point? I understand that it has a neat compiler and some clever ideas behind it (no virtual-DOM), but still.
It doesn't have to be wild west but I don't disagree it usually turns into that.
Before frameworks I spent a lot of cycles learning (usually the hard way) how to organize jQuery/JS code so it wasn't a total mess. I like to think I finally got it fairly maintainable for reasonable sized code bases. But by that time existing frameworks made a lot more sense so that's a bunch of thinking I'll never get back. I would guess I'm not the only one in this situation either.
Here's a really good book BTW if someone isn't aware of it.
That's true of every language. It's the software developers job to build the architecture.
I am an advocate for frameworks in commercial projects, for ease of knowledge sharing, speeding up onboarding and having a strong architectural philosophy built in. But we can't forget that we are the makers, we make the frameworks. React and friends are Javascript, anything they can do we can do too.
I am happy to use them for work. But I find all frontend frameworks too tooling heavy and full of arbitrary details you have to learn once and promptly forget. In my personal projects I have a simple architecture I use to organise my code in vanilla JS, no tooling and it's simplicity lends well to small projects sprinkled with only some dynamic UI.
The problem with frameworks is that they tend to drive the functionality of the site itself. It's easy for developers to start thinking in terms of what fun new things the framework allows rather than what the site actually needs.
I think frameworks are great, but you have to develop a self restraint from using every bell and whistle that's in it.
A trick I use to make the JS code more maintainable is to wrap code into pure functions that returns an element. For example if you need an input that only accept numbers: var input = makeInputThatOnlyAcceptNumbers() where the function returns the element, and all nitty gritty state handling is done inside the function.
Are transpilers included in Vanilla JS? If not, then IE 11 and Edge prior to 15 don't support async/await, which would mandate two codebases for lots of use-cases. Similarly, lots of other stuff has uneven support, hence polyfill, which also isn't "Vanilla JS" sensu stricto.
Well at least with vanilla JS you know your skills will be useful again in the future. With frameworks such as Angular or React, they can disappear and be replaced by the next flavor of the month pretty fast.
From what I have seen React is not better. It may not be spaghetti but then it is an exercise in architecture astronautics with way too many layers of indirection that is might as well be that spaghetti bowl.
I completely agree. What's everyone's favorite extremely lightweight view frameworks? And for those of us writing SPAs, favorite controller and routing frameworks?
The thing I really, really like about Vanilla JS is that it has 0 (zero) dependencies.
If something breaks in Vanilla JS, you know with 100% certainty that it's your code that's failing. With a framework, it's mostly the fault of your code - but there's always an outside chance that it's somebody else's fault, buried deep in some 3rd party dependency that may-or-may-not have been maintained.
I like React and Vue (I love Svelte!) - on a well-planned project they can perform miracles. But I see no reason to hate on Vanilla: it has its place too ... if you know what you're doing.
> If something breaks in Vanilla JS, you know with 100% certainty that it's your code that's failing.
If you're lucky enough to have the same developers for the duration of the project. Otherwise it'll be your predecessor who worked at the company 4 years ago's code. I've had to do far too much "reverse engineering" of "we don't touch that" code.
On the other hand, I've literally never encountered a bug in React. I guess it must have them. But I think not all that many.
I don't disagree. I still live in hope that one day I'll work on a project where all functions and variables have relevant and informative names and the Runbook is (accurately!) updated with latest changes on a weekly basis.
The point I was trying to make wasn't about previous developers on a project. Rather, it's the way frameworks ask me to trust them about the choices made by unknown developers to include NPM packages by other unknown developers in the framework's build. That, to me, is the definition of "wild west".
React is backed by Facebook. When it comes to frameworks I'm a lot happier to trust an open-sourced codebase backed by a company with a big vested interest in making sure that all the NPM modules they include (and all their dependencies, etc) are solid, safe and up-to-date. Even so, React's package.json file lists a devDependency for core-js - whose main developer is currently serving 18 months in a Russian jail[1].
How much trust we choose to put into other, unknown developers and their code is a risk to any project, is all I'm saying.
> If something breaks in Vanilla JS, you know with 100% certainty that it's your code that's failing.
Or the browsers' code which is a bigger problem.
I've been burned in the distant past by a blackbox framework that didn't work well with my use case (JSF) so I can sympathize with your position. These days I'd rather hit the occasional framework and polyfill bug than deal with a wide range of interopt issues.
Can confirm. Before I started using Preact, my client-side code was a large vanilla script. I would rather go work on a farm in Mongolia than go back to that.
Doing interviews I've heard a lot of this - react is more efficient than using the DOM directly, etc but no one can tell me why - they are just parroting what they hear or get taught at coding camps and make a fool of themselves.
I don’t think there is anything wrong with building your own ‘framework’. I feel like there is a lot of good experience gained, and learning to be had from taking this approach. Especially for less experienced devs.
It forces you to brush up on fundamentals, fill knowledge gaps, and practice/ learn design patterns. Also the end result is there is no ‘magic’, you know everything that is happening because you implemented it yourself.
Frameworks are great, but I don’t like reaching for them when I start new toy projects, I want to use it as an opportunity to improve my core JS skills.
I agree. I'm stubborn to take on frameworks as I have a vision and want to code it now; rather than learn and understand the framework to do what I want to create which by then my idea has deflated.
The company I am currently contracting for use Ansible. I've never used it prior and I get where the hype is but to me the whole system is just a mess. Asking the younger developers on "why isn't this working" feels quite embarrassing.
Five different folders, within more folders and then more folders on that; then you've got YAML which if you have one wrong space spews errors. I'm not dissing any of it as when it works when it works they do have their reasons for existence but it just feels so convoluted to do something you could write simply in bash.
Maybe I'm just a cynical SysAdmin throwing "get off my lawn" while wanting to see the world burn. But the era where I am from, where the internet was truly developmental; where if you wanted a CMS you built it from scratch. If you wanted a forum, you built it from scratch is kind of almost deleted from internet history.
Wordpress came a long and it ended all that, though I suppose it had to happen if you wanted more features from the users on the internet. It was a niche in the early 00's to have your own website but now my 70 year-old mother administrates her own website.
No disrespect, but I think you proved @vbezhenar's point. The right way to structure the code is with a framework of some kind, even if it's homegrown.
If there is anything I am trying to prove it is that you don't need complicated frameworks like Angular or React. Those frameworks have gotten too complex for what they do.
Switch statements indicate "it's one of these things", whereas in the series of ifs any of them could be true. Using a switch statement tells the reader that you expect one of these things to happen [0]. Using a series of ifs tells the reader that these things might or might not happen depending, and they're going to have to read each statement to work out which.
Your last version doesn't tell the reader what your intention is at all, and they need to work out what you're trying to do here. It's a lot less readable. Unless you're desperate for those bytes, it'd be better to use the switch statement for this case.
[0]: This gets a little weird in languages like JS where switch statements fall through to the next one if you don't break or return, but generally it still holds true.
That's not how switches work: a switch can (and will) trigger lots of cases if you don't either `break` (highly unintuitive to new programmers, who like you believe switch is "do one of these") or `return`, either of which cuts cuts the switch short.
I don't think this line of reasoning makes sense, since as you acknowledge, JS switch has fallthrough. I would not immediately assume that the coder's intent was for only one branch to execute if I came across a 'switch' in some JS code.
You should not use switch in JavaScript, because it is a language where switch requires break, which means it's 100% going to bite you in the ass unless you have a linter that checks for the break. It's not worth it for such a simple case.
i use that style too sometimes, depends on what's clearer. IME the former usually works better if you have a multiple tests, but the latter is the only readable option if you need to break a case across lines.
yeah, ternary-if is busted in php :/ (far from the only thing that's busted there though...) i'm actually doing some PHP work right now, and never chain ifs to avoid this exact thing.
It makes it clear that you're going to execute only one of the possibilities. Maybe that's clearer than a page full of ifs. But yeah, not particularly fond of the idea.
Except JavaScript switch has fallthrough, so it doesn’t make that clear at all. (Sure, no fallthrough happens with return in each case, but neither would a bunch of plain if ... return.)
How about we don't `break` like we should (!) and instead have fallthrough¹ cases that execute several cases— or more —on purpose²?
Oh, switches. Always the horror. In networking they somehow replaced bridges, but it's the same thing (that was never confusing to anyone, obviously). In (my) programming, a switch so often turns out to be a nice dressing hiding some horror pattern. And that Nintendo thing... nice games but 720p 30fps? Really??
When I re-read / refactor, I've got this nagging phrase in my mind, whenever I see one: “Kill the switch! Death to switches!”
To conclude this perfectly balanced and nuanced opinion (!): some switches find their place; but most don't, and never should.
____
1: SO: Should fallthrough be “allowed”? I move that whatever congress runs your country should outlaw it! But exceptions can be made... https://stackoverflow.com/a/188506/5376417
Is it not though? By exploiting the conditions to evaluate to true == $CaseValue you're subverting the expectation that the choices all rely on a single variable, all the while breaking fallthrough and default.
You're seeing it for the first time because it's a bad pattern. It's confusing to a reader who is expecting a typical switch use-case, and it has no performance benefit over a series of if statements.
I don't know about V8, but a lot of compilers would have a harder time optimizing this because of the strange structure. For mature compilers and naive (i.e. not-yet-profiled) projects, it's better to write what you mean and let the compiler optimize it.
This would be equally clear if the author had just used a sequence of if statements with a 'return' in each one. (Note that Javascript's case has fallthrough, so you can't immediately conclude that only one branch of a case will be executed.)
If using a framework, you would generally have typed JSON data, which is better. For example, makes number columns sort correctly (example code above sorts ‘10’ before ‘9’).
Dealing with cells of tables is one area where code optimisations are needed if you care about performance and have a large table. There are multiple obvious problems e.g. looping over calls to querySelectorAll.
That switch(true) statement is not what I would expect from a more experienced developer. It is show-off code that looks cute and works, but the compromises are not worth it (statement order is not obvious, if you make a mistake and two cases are true then do you know which wins, it could easily deoptimise the JIT compiler because it is doing something uncommon, I would worry how debuggers and code compressors would handle more complex cases, and understandability is poor for new devs IMHO).
Interesting at first glance, but what is the performance of this? It looks like all cases would have to be evaluated before picking one, so even slower than an if-else-if.
That entire example in general reads more like a cautionary tale about coding yourself into overly-specific clunk in the service of staying 'vanilla'. The 'type' of things being sorted is hardcoded into the html of the table and the actual js code. The comparator function has specific logic just to handle ascending and descending sorts of that that particular table. This one 'simple' example is already more convoluted and brittle than it would be even if you 'reinvented' your own framework-like thing.
Knowing that jQuery ends up calling those very same functions, only often after jumping through a bunch of hoops, doesnt make me consider it a shortcut. Between auto-complete and copy and paste, I prefer slightly more "work" up front, and then zero needless work at runtime, than a bit of "magic" that ends up doing needless work every single time it is run.
But I have to admit, I don't care about compatibility beyond Firefox on the desktop, if I wrote stuff for a company on a deadline, or if I worked with other people on something, I would mind jQuery very little or not at all. But for my own stuff I make to spark joy, where I get to decide all of it, I want it as vanilla as I can get it.
This line of reasoning only made sense in the old days.
For example, $.ajax() is strictly worse than the native window.fetch() -> Promise we have today.
I could see using jQuery in 2020 if your poor soul still has to support ancient browsers, but beyond that I suspect people only latch on to jQuery out of habit.
> I could see using jQuery in 2020 if your poor soul still has to support ancient browsers
IE 11 at work for some customer projects. It's dreadful. No support for anything decent, but at least the debugger is better than the "nothing" you had with IE6...
I'm not totally anti-jquery, but it helps to stay lightweight. If convenience is what you're after, you can always just bind querySelector and querySelectorAll to the document and assign each to a variable like this: https://dev.to/mrahmadawais/use-instead-of-document-querysel...
QuerySelectorAll is widely supported and you can make your own shorthand for it.
function $(query) {
const result = document.querySelectorAll(query)
if ( result ) {
if ( result.length > 1 ) {
return result
} else {
return result[0]
}
}
}
I hope you don't use that since it randomly returns either an element or a list of elements, so you'd have to also add an if/else every time you use it.
The main advantage of jQuery these days is all the plugins it provides, most (if not all) things you need on a website exist in jQuery. And I also found it really has messed up search results, search for anything javascript related, and almost all answers you find on StackOverflow are people suggesting to use jQuery. (Even when the author didn't ask for it)
The other day I was looking for a simple markdown editor, and it took me a while to find a decent vanilla one. (Ended up using https://simplemde.com)
Making decent UI's went from bicycle science to rocket science. VB-classic was easy to learn and easy to use, and you had coordinate control over where most things went on the screen. If your layout engine didn't put it where you had planned, you can just tell the widget to "go right here". You felt in charge of the screen, not some abstract layout layer with an attitude. A manager (person) could draw something on the back of a napkin and you could make it exactly match the napkin because you were in charge of exactly where things went. (Layout engines were optional then.)
The newer UI frameworks are round-about and confusing. They make it easy to get 80% of what you want, but that last 20% is bear, requiring long trial-and-error periods, unless you are heavily versed in them. Abstraction is only nice when it does what you want, not when it becomes "abstract art".
The price for "responsive" (client-side auto-placement) has been huge. In applications that are primarily for office desktops, their advantage is lost. Mouse and PC's is still where most real work is done. Instead we are using things like Bootstrap, designed for social networks, not real work. Glamour won over logic.
It's great job security for UI experts, but expensive for organizations because they need stack specialists whereby before a one-man-band (or 2) could make useful apps for less than half the cost and time without having to spend years with UI-Yoda to master some screwy layout engine.
I currently maintain nine web sites, internal and customer-facing. For the last two years I've been migrating them off of the framework-go-round into plain old PHP→HTML + CSS + minimal JS where there is no other option.
Because I'm in healthcare, the web sites have gone crazy in the last four months, and there are updates upon additions upon updates of the additional content over and over and over. Think 14-hour days.
The sites that have been migrated out of the framework jungle can be updated in minutes to hours. The sites that are still stuck in framework hell can take hours to days.
When things happen (for example, when another state locks down), the framework sites get slow. The non-framework sites keep zipping along, which was my main reason for moving them in the first place.
The next time you're looking at a government or healthcare web site that doesn't have the latest COVID-19 information on it, look at the source code and try to figure out what it's been generated with.
So you profiled the sites enough to understand that the actual bottleneck for these sites was the framework CPU/memory overhead?
I don't know what the requirements of these sites are, but throwing out all the things you get with a framework such as a battle-hardened authentication system for "plain old PHP" hardly seems like a pragmatic decision. Was a full rewrite in a base language only really an easier/superior decision then finding more simply caching solutions (which many frameworks support out of the box)?
So you profiled the sites enough to understand that the actual bottleneck for these sites was the framework CPU/memory overhead?
Yes. That's part of my job.
I don't know what the requirements of these sites are
Then anything else is just blather. I know more about my systems than you do.
Was a full rewrite in a base language only really an easier/superior decision then finding more simply caching solutions (which many frameworks support out of the box)?
Yes. For my purposes. Perhaps not for the sites you work with.
Sorry, but I'm extremely skeptical that rewriting a framework based codebase into plain old PHP is ever a good idea. I've maintained too many legacy (mostly PHP) codebases in my career where the creator thought he knew better than everyone else to think otherwise.
These are the kinds of what-if questions that scare people into using the most popular framework-- well, what if security isn't as good? What if it's not properly cached? What if the rewrite is hard? What a load of bologna.
Caching is a problem you need to solve regardless of whether you're using a framework or not.
These problems don't magically go away when you decide to rewrite these components yourself. You probably aren't going to write code as well as a community of coders that have contributed to a years-old codebase. Especially not on your first pass.
These are all pretty legitimate "what-if" questions to ask.
The original poster said "plain old PHP" so without making assumptions I am taking that statement at face value.
Still though, auth is just one arbitrary requirement I plucked from many that popular frameworks solve such as request handling, response rendering, database operations, routing, etc.
Yes, you can use a hodgepodge of libraries to solve these requirements but your argument that your codebase will be leaner than a "heavy framework" using codebase gets a bit flimsier in my experience.
You'll understand your code better and the limited scope of the libraries allows for less bugs in each component and easier migration later if needed. If I use the big framework, I'm stuck with it if I ever have to change my data storage method and it's outside of the frameworks normal scope. If I use a separate library, I can change over to whatever I need.
Look, I'm not saying you shouldn't use a framework, every project has different needs. I'm saying that frameworks have made people lazy and they try to fit their project into the framework they know when when it's wrong.
> You'll understand your code better and the limited scope of the libraries allows for less bugs in each component and easier migration later if needed.
What do you think the components in a framework are? They're just libraries, and often can be/are used standalone. I've seen no evidence that there are less bugs in a library not used for frameworks than one used for it.
> If I use the big framework, I'm stuck with it if I ever have to change my data storage method and it's outside of the frameworks normal scope.
There's no reason you can't use a different library within the framework. It's the exact same as writing from scratch, you're just doing it within the patterns of the framework instead of the patterns you've created on your own.
> Look, I'm not saying you shouldn't use a framework, every project has different needs. I'm saying that frameworks have made people lazy and they try to fit their project into the framework they know when when it's wrong.
I'm not advocating for blanket usage of frameworks either but I've yet to see a compelling reason to in this discussion thread not to.
Because each library does one thing only and it is easy to understand that particular abstraction.
With a framework you not only have to learn how build things in the framework (which takes a lot of time to become truly proficient) I also have to build what I am already supposed to be building.
I find personally that frameworks
* Simple things hard. Hard things simple.
* Anything outside of the happy flow they present to you in the docs is a major PITA.
* I frequently find myself scrabbling around for information when I need to override how the framework works in a particular scenario.
* They nullfy much of your pre-existing knowledge e.g. I am described at a lot of places as a JavaScript guy in the team, because I get JavaScript. When I use Angular or React, most that is irrelevant. It doesn't really help me.
If I am just using well established patterns + my existing knowledge of the programming language and environment. I can normally put something together myself that does just what I need it to do and I use a library for things like date time calculations or Ajax requests or something else that is mundane.
I think this is a pretty succinct counterpoint. I especially agree the sunk-cost of investing time learning a framework isn't something to take lightly.
The only thing I'd counter to this with is when I see this approach taken, an informal "framework" of sorts tends to evolve naturally. First you write something that handles the routing, then soon you want to organize the code the route endpoints call, then you layer on the authentication at the top level request handling area, so on and so forth. Over time, as new requirements come in and new people work on the project, more and more patterns, conventions, and library are added to the codebase - pretty soon all that "glue" code meant for interfacing with libraries is reaching or exceeding the complexity of a framework based codebase (except your codebase probably has less documentation for things like conventions and patterns than a framework would).
That said, I don't think it's the wrong approach especially when the scope of the project is limited and/or there are ways to manage feature creep (e.g., frontend only, limited lifespan, internal facing apps, etc)
I'm confused, are you saying using React/Vue is not practical for a small 1-2 person shop? As compared to what?
If frontend was bicycle science then I must have missed that in my 10+yrs writing frontends with JS+CSS...
> They make it easy to get 80% of what you want, but that last 20% is bear
JQuery was the standard before JS frameworks took off and it was a nightmare for anything besides smallish websites. It was good for 25-50% of what you wanted at most - everything else was completely different every project you looked at. Trying to manage a large application that any serious modern web-based SaaS company uses was incredibly difficult.
I started using Backbone.js before Ember/Angular was even a thing yet and it was the first serious attempt at building large JS-driven apps for browser and mobile. That was simpler because it mimicked Railsy REST/MVC set ups, plenty of analogies for backend people to learn from, but that turned out to be a poor way to create UIs and React/Vue/etc + Redux offered a thinner view layer with a very clean way to manage state and bind data to the UI.
JS frameworks stopped pretending they were traditional web server app/database in the browser. But rather one that reflected the reactive interactions which we are trying to model in real-life spread across various individual components... more like desktop interfaces, not recreating web apps backends in the frontend.
Vanilla javascript has improved quite a bit to lessen the need for JQuery, but even then managing state and mutations reliably, modelling data, coordinating async operations, only loading the JS you need on a particular page, code organization/modules, etc have all been made way easier with the new Webpack-driven frameworks.
But you can still use simple vanilla/JQuery if you only have a small project. There's still plenty of Jquery libraries being developed and simpler UI libraries like Bootstrap...
Unless you mean pure-HTML forms, which are extremely limited in terms of interactivity. But again they haven't gone away either if it fits your needs.
>If frontend was bicycle science then I must have missed that in my 10+yrs writing frontends with JS+CSS.
What you've said directly proves OPs point - you've missed the central message: UIs used to be bicycle science before everyone started using JS to make them.
They mentioned VB as in visual basic. GUIs with VB/Delphi are a case of dragging controls to where you want, pixel perfect every time on every desktop.
Web technologies are not designed for desktops but for building on top of HTML, so everything is an abstraction to get back to something that used to be possible with zero experience and sometimes even zero programming. For example, a simple notepad clone can be made in Delphi without a single line of code.
Now you need to 'full stack' to even know what's going on under all the layers just to place a control at an x,y and even then it can't be guaranteed because of all the different browsers, css edge cases, and other caveats.
> For example, a simple notepad clone can be made in Delphi without a single line of code.
Sure then I agree, making simple toy apps with VBasic and similar tools was easier. It was also easier to make websites in Dreamweaver back in the day than really learning HTML+CSS.
That doesn't really solve any serious problems, nor the reasons why we've adopted such extensive frameworks.
What I disagree with is that it's getting harder or messier or worse to build frontends. I've seen significant improvements in the last few years and I've told many people that I'm actually liking making JS-driven apps for the first time in my career (Typescript has played a big role in this as well, not just React/Vue). I'm no longer scared of deploying large-scale browser apps since it became clean component/redux driven stuff instead of a tangle of JQuery + other crap shoot combinations.
I'm sure the pace of change to outsiders can make it seem like a long series of failures and flailing about, but to those who have been following it there has been a relatively consistent evolution of ideas. One that more recently has gotten us the closest to desktop quality software than ever before - even though 'desktop widgets' was a dirty word in the frontend world for a long time - IMO largely because early attempts were too bold and complicated for the capability of the browsers at the time.
Yes it does. It meant that less-experienced developers could make nice programs that near-zero-experience users could immediately take advantage of, with the same look and feel as every other program they already used.
It went far past "simple toy apps"; maybe not suitable for making a distributed network app, but for making something useful for an accountant or an administrative professional, it was perfect.
> I'm sure the pace of change to outsiders can make it seem like a long series of failures and flailing about, but to those who have been following it there has been a relatively consistent evolution of ideas.
I've been following this since the 90s and it went from "a nice way to publish documents to everyone" to "a bastard environment with a shitty language that is inconsistently implemented" to "overburdened with frameworks to paper over the fact that this system was never designed for this at all".
Great, 20 years later we have some huge massive framework that takes ages to learn even for someone who used to know JS competently, just to draw some basic widgets and data tables that we used to be able to drag-and-drop into place in the 90s.
> What I disagree with is that it's getting harder or messier or worse to build frontends.
Maybe it's slowly improving in the browser now, but until we have things on the level of Flash as far as interactive design for non-developers goes, it's still massive steps backwards for no real gain besides the self-gratification of JS devs.
Re: [That doesn't really solve any serious problems]
"Yes it does. It meant that less-experienced developers could make nice programs that near-zero-experience users could immediately take advantage of, with the same look and feel as every other program they already used."
Let me clarify. I am or used to be what's now called a "full stack developer". I am not really an intense "coding wizard", but can do ALL parts of the development cycle reasonably well, including talking to the customer to understand what they need and why they need it. Those good with code details tend not to be so good at the analyst and communication side of things. There are exceptions, but I'd say this is about 85% true. These tools made full-stack-developers possible and relatively cheap.
This also means each department (group within an org) can have its own programmer/analyst who can focus on and learn the domain, now it has to be more centralized in order to have specialists.
Tools like VB-classic, Delphi, PowerBuilder etc. meant I didn't have to micromanage a lot of UI details that either take a lot of time or require hiring UI coding specialists now. I could do both the analyst/people side and the technical side at a good clip.
Current web stacks mostly killed all that, requiring either layer specialists or spending a lot of trial-and-error time fiddling with browser UI's trying to get the friggen UI to match the sketch. Before if the customer asked, "can you move that button to the right just half an inch", it was 5 minute job. Now such can take 2 days if it goes against the grain of the UI framework. It's ridiculous. Sure, an expert at the UI framework may instantly know the magic CSS trick, but it's only obvious to a UI framework expert, NOT to generalists like me.
It now often requires rocket science or a manual genetic algorithm (mass trial & error) to move that damned button half an inch on the customer's screen.
I used this tool at the State of [redacted] Dept of Taxation to develop the whole system. The database was Oracle (I think) and we would write the backend code as such:
1. Copy the 2019 code function "VERIFY_TAX_RULE_147B_2019()" to "VERIFY_TAX_RULE_147B_2020()"
2. Follow this list of rule changes for this rule to change the function
3. If there are any 2019 functions in this function, make a ticket to copy+paste those in a similar fashion for some other developer
4. Close ticket
5. Get another ticket
The front end for the forward-facing revenue agents would also get updated in a similar fashion, one Power Builder form for each year and window they needed, so if you opened 2020 taxes you would get "WIN_FORM_PAGE_A317_2020" and if you opened 2019 or 2018... you get the idea.
It was a horror from the usual "software engineering practices" standpoint on stuff like code re-use, but it was super easy to do and based on the risk analysis it was the best/easiest/cheapest solution to be able to test, review, and ensure the accuracy of EVERY tax rule we implemented with iron-clad certainty.
Someone in QA would just go to each function, make sure it calculated things correctly based on the requirements, and do a few other checks. We had a big QA department that would do test driven development on each pull request (if it failed, you went back to fix it again, so since we used Visual Source Safe we ENSURED it worked the first time; you know what I mean if you used VSS) and sit down with the developer for each function and go through it in a heavy review. I can't imagine trying something like that in React or whatever, you could never ensure the software would always behave the same way each time with the network latency and huge underlying security concerns for the framework and a bunch of other issues we would have had to overcome to prove it worked correctly every time. Backend frameworks would be even WORSE for our risk profile.
Most importantly: no one cared what the damn UI looked like as long as all the buttons and text boxes were there in the designated configuration. They were all Windows 95-style UI boxes and I doubt that the front desk agents would have been happier to use some Reactified "pretty" stuff.
The story is just to say that I agree with you wholeheartedly that the UI/UX space has exploded with useless garbage you don't need in a simple, boring business tool and 95% of software is just that, simple and boring.
Each such VB-influenced tool all had their weak points. But overall they seemed moving in the right direction as each vendor learned from each other's mistakes. Power-Builder's difficulty in code share-ability was a specific design flaw of the product, not of the general concept, and perhaps fixable on a later version.
As far as most business software being "simple and boring", I wouldn't necessarily call it "simple", for the domain rules can get intricate. But it doesn't need buzzwords like blockchain web-scale AI or what not.
Desktop GUI's reached a pinnical around the late 90's and web UI's still cannot compete on simplicity and functionality. DOM-based emulators tend to break on browser version updates. We need a dynamic GUI-over-HTTP standard to allow us real GUI's on a browser or browser-like interface. Something like YAML, but more interactive. #MakeGuisGreatAgain!
I agree with the central thrust of what you're saying here; its definitely easier now than it has ever been, and things are now moving towards the simplicity of how it used to be when creating desktop apps using web tech with the advantage that they're cross platform.
However this improvement is in spite of using a tool designed for a different medium, rather than because of it, and the years and abstractions its taken to get here express this.
Having said that, cross platform is better going from web to desktop than the other way round.
Re: and things are now moving towards the simplicity of how it used to be when creating desktop apps using web tech with the advantage that they're cross platform.
I suspect we'll need a new web standard that's GUI-friendly. For one, have the option of sending raw coordinates to the browser and have the (optional) layout/flow engine be on the server. That way you only have ONE layout engine instead of a different one for each browser version/brand, which is what we are really dealing with.
A. app -> server layout engine -> coordinates -> client -> screen
B. app -> markup/JS -> client -> DOM -> coordinates -> Screen
The problem with "B" is that each DOM is slightly different: different browser brands and versions. You have to test with about 50 variations to be sufficiently thorough. And as time goes on, they break more code. A more accurate diagram would fan out after "client" and have DOM1, DOM2, DOM3, DOM4, etc. Since the browser is dealing with raw coordinates in A, there fewer things to go wrong. Thin client = thin errors.
Another advantage of A is that you can choose different layout engines not bound to DOM standards and quirks. Or even have none and go WYSIWYG. (Web browsers don't really do WYSIWYG well in practice, partly because font-to-widget-size-ratios are not standardized.)
"A" is more stable. It's better factoring, period.
The GP was saying VB-classic, implying that he's talking about windows desktop apps. I think that's what he's saying about layout engine stuff; layout engine is only a thing on web apps. Everything you're talking about is re: web apps, just older style web apps with JS+CSS in the past 10 years. For old school windows desktop apps you don't have to worry about client rendering, client's browser size, responsive (mobile vs desktop), etc. I believe GP is making an argument that most of these business-use web apps could've been windows desktop apps where the frontend takes half the time and team to build.
As I mentioned in my comment, JS frameworks by adopting a reactive model are getting closer to how desktops apps function. That has always been the goal, making interactivity as capable and flexible as 'native' desktop software while still remaining consistent, accessible, and cross-platform in the browser.
One of the biggest motivations of these JS frameworks early on was due to the adoption of smartphones becoming the primary computer interactions. The other was the SaaS model, creating far greater demands on what needs to be done in a web form.
I've developed VB and cross-platform stuff like Qt and wxWidgets, and that stuff is no easier than the stuff I'm building with JS every day. HTML templates + automatic reactive bindings via Vue and a Redux/Vuex 'backend' are very simple.
What's more complicated and still shitty with JS frontends is the wider frameworks with Webpack, that come with a hundred packages that break often. That is the most painful thing I have to deal with day-to-day. The learning curve once you add in Babel, PostCSS, the various code optimizers and linters, TypeScript, etc can be quite intimidating.
But that has more to do with the tooling than the general approach being taken in modern frontend development.
Re: As I mentioned in my comment, JS frameworks by adopting a reactive model are getting closer to how desktops apps function. That has always been the goal
And they keep failing because they throw layers at the problem: chicken-wire is used to fix problems caused by the duct-tape on the prior layer, etc.
It's becoming pretty obvious that Yet-More-Layers only exacerbates the problem. It may get "solved" by having fewer browser choices, but then the evil of oligopolies will kick in and we'll be back to the IE-esque problems, one of the most hated browsers.
Re: I've developed VB and cross-platform stuff like Qt and wxWidgets, and that stuff is no easier than the stuff I'm building with JS every day. HTML templates + automatic reactive bindings via Vue and a Redux/Vuex 'backend' are very simple.
My experience is different, and I observe similar bottlenecks at various orgs. Those JS-centric frameworks are harder to trouble-shoot when things go wrong, and different browser brands/versions render them different and/or wrong. With the VB/Delphi-esque tools, things show up exactly on the screen where I tell them to go: there is no if, ands, and buts. They follow my exact commands like dutiful robots. The technology is MY slave instead of the other way around: Thou Shalt Go At X=37 and Y=200. My Will Be Done! (Cue thunder clap.) React/Vue et. al. often go, "Sorry Dave, I cannot do that, but I'll do it my way anyhow." (I recommend GUI's use vectors instead of pixels these days, by the way. They are potentially equivalent when needed.)
Further, the quirks in pre-web GUI tools were getting ironed out over time: they got better with age. The web seems to get messier with age because of the layer-to-fix-layer problem above.
> For old school windows desktop apps you don't have to worry about client rendering, client's browser size, responsive (mobile vs desktop), etc.
Is this just a matter of there being less ways to interact with the apps back then? Everyone had the same platform, same hardware, same screen resolution... etc. Plus, accessibility was an afterthought. Now, users have bigger and more varied expectations.
> JQuery was the standard before JS frameworks took off
jQuery was never a standard any more than it is now. It was popular even driving a bizarre fundamentalist cult of personality worship, but that by no means makes it a standard. In technology a standard requires wholesale adoption opposed to mere frequent consumption, even if not enshrined by a document (de jure). For example there was never a time that jQuery was required in any commercial capacity either to seek employment, perform work, or deliver a finished product. Claiming that I hated jQuery during its prime didn't stop me from closing a job interview, but it did turn a few heads.
You can't honestly compare VB UI's to modern day web UI with a straight face. Following your analogy, making decent UIs is closer to rocket science because web apps are closer to rockets than bicycles these days.
I would love to see a drag-n-drop approach to web UI building that is responsive and fast. But I highly suspect the reason this doesn't exist isn't "great job security".
There's really nothing complex or difficult enough in React, Vue, or any other UI framework that can't be picked up by a competent dev quickly.
>Something is wrong
Yeah, the hivemind that loves to hate anything JS/front-end related and things "purity" is the only bar by which to measure things.
> There's really nothing complex or difficult enough in React, Vue, or any other UI framework that can't be picked up by a competent dev quickly.
Honestly. Where I work we have a few undergrad co-op students who have just finished their first year of school. No previous React experience. They jumped right in and were useful on our React projects after about week. They just read some docs, asked a couple questions and played with our existing code. They're smart people but they're not x10 programmers.
We have other large projects that are a more "traditional" mix of DOM manipulation use jQuery, global CSS, etc. and introducing new hires to that is never as smooth. There are no docs as thorough as React's that explain the patterns established in those codebases (if there are any consistent patterns at all).
One thing to note, we make what I would consider to be web applications (for data management & analysis), not web pages.
I agree with a lot of your points here. For example, I’d love to have a nice constraint system like you can have making an iOS. or even windows app. The problem is we have to work with HTML and the DOM, which aren’t nearly as nice to use out of the box as OS APIs. HTML/CSS/JS wasn’t designed for applications, it was built for basic document manipulation. But the pure accessibility and compatibility of the web is a better trade off for most products because it’s easier for people to find and use something on the web than downloading an app. So we’re forced to use worse tools.
I also don’t get the JS hate here. :) you certainly should not use react for your static resume site or blog. But react is a brilliant and necessary tool for web applications. If you don’t use it, you’ll end up making your own, probably worse abstraction for managing state and reactive updates.
I started the "hating" when pc promised everything would work on every computer. this just seemed impossible bordering idiotic. before this every screen had the same resolution. UI was horrifically easy! The c64 had characters in the font set that allowed drawing boxes. You can imagine but it was 10 times easier.
The problem with many layers of abstraction is that it borders the imposible if the layer abstacted to poorly suports something.
Take physical screen size and simple scaling to fit? Is it a tiny 1024px laptop or a giant tv? there is no solution I can think of
VB classic didn't have a layout engine, so you had to do everything yourself. Making the window resizable required a huge amount of error-prone code that you had to change every time you updated the UI, and it often didn't work well. A classic VB6 bug was to resize the window larger, and then shrink it back down to the same size, and the layout would not be consistent despite the window returning back to the same size it once was.
The browser today lets you opt out automatic layout and instead specify fixed x/y/width/height coords with `position: fixed`.
It seems to me that your problem isn't the technology itself but perhaps the culture around it?
I never found it error-prone. Perhaps meticulous. You had one event where you simply go through all your "dynamic" controls and set their position and size. I did it for all my applications, both simple and sophisticated. Worked like a charm.
The built in tooling got more flexible in .Net (eg. You could effectively "bind edges"), but I actually found setting all that up more time consuming in practice that just arranging everything myself in straightforward code (which also gave me more control over exceptions and edge cases).
It became really error prone when elements had intrinsic size. A great example is when you have to lay out elements based on how text wraps. Designs back then didn't need this as often, but most designs today do need to take it into account (especially if internationalization is a requirement).
To do this correctly you need to do two passes for layout and at that point you've basically implemented a rudimentary layout engine.
I think we overestimate the complexity of apps we built back then and don't have an appreciation of how complex our apps are today.
If your layout depends on text wrapping, text length and i18n, then your design is wrong, your UX will be bad and your users will hate you for trying to be too clever.
Not to mention the amount of finicky bugs you will encounter.
That hasn't been true in my experience. For example, German has a lot of compound nouns that aren't breakable over multiple lines, so you often have to tweak your navigation layout to account for this vs languages that are more likely to be breakable over multiple lines, like English.
> It's great job security for UI experts, but expensive for organizations because they need stack specialists whereby before a one-man-band (or 2) could make useful apps for less than half the cost and time without having to spend years with UI-Yoda to master some screwy layout engine.
My company has a very, very small number of UI experts who are tasked with making sure non-UI folks can build front-ends. It's been a rousing success. We own some documentation and a few tools to make starting projects easy. We teach an hour long workshop that covers everything (React, the npm ecosystem, TypeScript, best practices, etc) and then we let them have at it. It's been a rousing success and nobody has seriously suggested moving back to jQuery or any of the WISYWIG tools.
Sure there is a cost -- you need to hire at least one person with enough knowledge to cut through the bullshit and build the right tech stack. But once you've paid that cost once the payoff is massive.
Sure, but that's a problem for everything. You'll struggle to build a modern cloud architecture without at least a few people with extensive experience with the cloud.
You can get pretty good mileage following industry best practice -- pick React, pick TypeScript, and pick the most popular tools for each.
Some but mostly we relied on my expertise and a few others who've been thinking hard about these problems for a long time. We've been thinking about sharing some of our insights but haven't yet.
There is nothing wrong. Before, you only had to care about your app running on a VGA monitor. Now, you have the possibility to make it run on devices of all sizes, resolutions and shapes.
Not really. Most productivity software still runs on desktops. We sacrifice too much to the Resize Gods without actually using them. It's like costly shrubbery insurance. (YAGNI.) Desktop GUI's were both easier to specify and were more productive to use. The "responsive" designs waste screen real-estate and require more steps to do the same thing, on average. The labor math usually says "no". There may be a subset of features that phone users need, but one can make a separate sub-app for those rather than poison the whole thing with mobile-oriented drawbacks.
I was reading through the code, and was astonished at how this doesn't look like code anymore but a mashup of different languages and patterns in one single block of code.
The only framework I'm willing to tolerate at this point is Vue.js, which, with the help of http-vue-loader, is capable of nicely using components in a compiler-free workflow.
React may be excellent for teams, where there's a clear distinction between font- and backend development, but sometimes you just need to hack together a server with a minimalistic frontend which should just be editable via sftp, when you're building tools for internal use only. Vue.js is great for that, but I'm worrying that it will turn into the same thing Angular has turned into.
These fixed-size GUIs have already been shit in the 90s (remember
the windows-dialog where you disable hiding of file-extensions? I
think it's still there as of today and still annoying as always).
Now I have a big high-res monitor but can't read bad written
applications like Steam because they don't honor my DPI settings.
Even worse. We're stuck with html/js also for "desktop" apps, via the electon and similar. Basically, UI development is dead (Windows WPF is in maintenance mode) and if you want, as example, build some graphs you need to manipulate js in a webpage. A
Users want to run your software on their system. You don't want to write software for their system, you want to write it for all systems. The output impedance of the developer and input impedance of the users is a function of how easy it is to write the app for all users and use it by any individual user. Optimal power delivery is achieved when I/O impedances are matches low. Efficiency is achieved at lower impedances.
JS/HTML/CSS is currently the optimal solution in that context.
UI isn't dead, it's more alive than ever. But since what works is what can get my product to the most people the fastest is on a web stack, that's the thing that's going to be used. And since the web stack is high impedance to begin with, anything I can do to lower that in terms of framework is going to be in demand, hence all the diversity we see.
HN likes to downplay frameworks like React, Vue, etc., but people who work on modern web apps everyday know how insanely difficult/unmaintainable it is to write the same thing in plain JavaScript. And before you start saying "but I can build a simple HTML site and sprinkle with some JavaScript", the market has spoken – general web users like high fidelity web apps.
Whether you like inaccessible websites when you disable JavaScript is one thing, but don't dismiss useful tools that don't suit to your tastes. If you don't need to build a web app nobody's forcing you to.
HN likes to downplay frameworks like React, Vue, etc., but people who work on modern web apps everyday
Whenever I read the word 'modern' in this context now, I know the writer means javascript, and in particular one of the 'modern' javascript frameworks. I'm not sure quite how or when it acquired that meaning, but it seems to be used that way on HN frequently. I wonder how this word came to mean built with Javascript to some people? Do you genuinely see modern as synonymous with built in React, Vue, etc. or would you allow other approaches into the modern canon?
The similarities with the burn the old world then rebuild it anew attitude of early 20c Modernism are striking, so I suppose it fits, but it should not be used in the place of built with javascript, as the implication is nothing else is truly Modern.
Also what does high fidelity mean in the context of websites? Is this like high fidelity vinyl records with a warm sound? Do your frameworks have gold cables?
I think you'll find people here casting doubt on the requirement for web frameworks because there are many other ways of building websites (server side for example, the way this website you're using right now is built), there is no one 'modern' way. People build contemporary websites with a variety of tools, Javascript is not objectively better than other solutions IMO (in many ways it is obviously worse), and client side is not obviously better than server side, it's a pattern which has seen its popularity wax and wane and will do so again.
GP is not talking about JS frameworks, though. They're talking about layout constraint systems (the argument goes that CSS is harder to reason about because "width" might not mean physical width, since it could affected by margin, etc). The counter-argument, of course, is that there are many more types of devices now (e.g. using "desktop" experiences in an ipad, multiple screen resolutions, etc just to give a few counter-arguments to the notion that desktop is "simple")
As for frameworks: the market has indeed spoken, but not in the way you think. Consumers of websites rarely pay for the majority of websites they use. Employers, however, pay developers and the buzzword-chasing in resume building/interviewing cycles is real.
Nothing is wrong. Things got more complex and segmented and specialized in. That's just how an industry grows. I mean look at how many jobs, companies, and careers were created just around the invention of the "smart phone". In 1999 none of those really existed. Sure you could play the snake game on your phone, but I think the app store is a little more complex. Anyway, software pushes hardware to its limits, and then hardware pushes software to its limits, and the cycle goes around and around. With the invention of the smart phone, you got to see hardware push software to its limits, creating all these extra layers of coding that most of us old schoolers arent fond of. And now (in my opinion), the AI and Cryptocurrency GPU/ASIC movements are pushing hardware limits. So I'd expect to see lots of innovation in that arena and also lots of greybeards claiming "We dont need all these fancy different processors, back in my day we used a CPU farm and it worked just fine and why do we need all this".
On the other hand I know what you mean because I cut my teeth on coding VB6 and Delphi (Borland anyone?) applications in middle school (where are my Yahoo!, ICQ, AIM app masters at?). It was fun, and easier than todays craziness. And people wrote more client software instead of making everything a web service. We also had zone alarm and people got hacked left and right and windows BSOD and all the fun of the 90's and repeated unknown socket errors on winsocks. I also felt like the programming world had more curiosity and self-sufficient people, as opposed to being so heavily money, convert, social, latest tech driven. It feels like everything now is a rinse, repeat, sell to FAANG cycle.
That. I remember Borland C++ Builder. It was a pleasure to build compelling user interfaces with it, but it's best value was simplicity, the meticulously crafted library and great help system. That's how I got into programming. The big difference today are devices, especially screen sizes. We want to make apps now. Small, focused tools. Sadly often we have simple apps bloated beyond recognition for profit. That's partly why every gizmo in an app is not only pixels, no sir, it has to jump and blink and shout for attention. More layout engines won't make your app better. Keeping it simple and focused will.
For CSS I have long suspected that this is intentional. The point was to let clients do what works best for them, and the page designers weren't supposed to be lining things up perfectly in nice squares.
Unfortunately the real world and the perfect world the CSS designers envisioned were two totally different things and as a result people have been fighting with CSS layout for years.
What's wrong is we are trying to fit a round peg(general desktop apps) into a square hole(flowable document delivery model as envisioned originally by Berners-Lee).
It is easier to make UIs with Winforms, Qt, WPF, heck even with Actionscript it was more managable than with DOM.
The problem is that there is no unifying standard, no single vision. There are competing frameworks but they leak abstractions all over.
For example I am making UIs with ipywidgets which is basically JS on the front end and it at least a couple of abstractions too deep to fully understand it.
To emphasize how stupid making UIs using web is, let's take something simple like dropdown.
There is no such thing in the web standards, we use ul, ol etc and then we fake it/add another abstraction with a library or framework
In an ideal world dropdown would be a web component that could be imported, then be styled and events would be bound.
> This approach isn't recommended because we can only attach one handler for each event.
Except when you do want that behavior. E.g., you only want to set one listener and have a stream of data coming in that can trigger various attachments/detachments to the same element(s) over and over.
With the ancient "on" methods you get a single method that you can replace at will. Unbinding happens automatically. For example, you can keep assigning to an anonymous function till your heart's content and there will only ever be one callback in that slot attached as the author states.
With the new, "recommended" methods you must manually track the state and unbind old callbacks. For example, you would have leaky behavior if you kept assigning anonymous functions with addEventListener. And you can't easily hack your way out of the state problem because the DOM doesn't give you a way to fetch the current number of listeners, reset them to default or really know anything about them.
So the recommended behavior does not include in its design the ability to achieve the useful old behavior.
But at least DOM does have a convenience method to toggle class that will save a good 10 seconds per year of dev time.
This could be done inline with
<input type="password" id="password" />
<button onclick="password.type = password.type
== 'text' ? 'password' : 'text'">Toggle</button>
...instead of 10 lines of code. Is it ever ok to use the fact that window.elementID works? even for exposition? (it works in all browsers, not sure if its standardized...) Why use setAttribute? Again, setting via element.type = ... works in all browsers.
The idea behind addEventListener is that multiple handlers can be attached to the same event of the same node, whereas before handlers were property assignments that would clobber each other.
The disadvantage of addEventListener is that event handlers are associated with event listeners instead of with DOM nodes, which makes them more challenging to garbage collect and thus increases the memory space of your application. The way to keep the code clean is to use removeEventListener when the handler is no longer needed. Event handlers are rarely removed from the code though, because of a lack of discipline and because many times its hard to tell when they are no longer needed.
The biggest advantage of assignment by property approach is that it imposes simplicity. Simplify means to make fewer and complicate means to make many. When there is only one handler it is inherently the most simple approach, which greatly increases code cleanliness and forces a greater concern of code organization.
Another possible advantage for onevent properties is they work as soon as the element is loaded. Attaching event listeners normally has to wait for the whole DOM to be loaded. The difference probably isn't noticeable over a good connection.
Coincidentally, I just commented yesterday about an interview experience I had about the DOM. I did not expect it to be so highly upvoted. https://news.ycombinator.com/item?id=22740897
I don’t know if I would pass your test, but the outcome is more or less exactly what I would have expected. The vast majority of employed web devs do not use pure JS to manipulate the DOM because it’s incredibly tedious. That was true 5-10 years ago when the most popular option was JQuery, and now we have massive swaths of React where people don’t manipulate the DOM directly at all. And they get by just fine. Major commercial sites are built with little to no direct DOM manipulation.
Saying that you’re going to let people have time, use the web to lookup the answer, that there’s no penalty, etc., that seems blind to the fact that you’re signaling what it takes to pass the test as well as what people will be doing once they start working for you. I’m certain you lost the opportunity to interview some good candidates simply because they are choosing to not work somewhere that thinks pure JS is the only performant solution, and might not know that there are both good and bad ways to use JQuery, and/or functional reactive solutions that avoid keeping messy/buggy state around when you could instead re-render. I’m sure you also lost interviews because some candidates were basically told by you that already knowing how to manipulate the DOM via pure JS was what was required to ace the interview. They assumed, and reasonably so, that spending the hour showing you they didn’t already know how would result in not getting a job, so why bother with the interview right now? You might have sent several smart people off to study and do homework about it, but you don’t know that because they walked out the door.
So, while I do think it’s very useful to know how to use pure JS on the DOM, and I think your interview experience is interesting, the incredulity about it makes it seem to me like you’re not entirely taking responsibility for the implicit message that you sent to your candidates for the interview, nor that the outcome is fairly predictable.
The job position was for people to write A/B tests. A/B tests are a form of white hat hacking where code is injected into a page to manipulate or deface the page to test a business idea as an experiment.
It would not make sense to inject something like Angular or React as part of test code and would be detrimentally regressive to inject Angular or React targeted logic over an existing framework application without a more thorough consideration for second and third order consequences. An experiment is meant to be something that is created with the least possible labor since its not production code and short lived.
That said the most desirable approach was to manipulate the DOM directly since this achieved the fastest execution, provided the smallest risk/footprint, and was fastest to QA for regression.
---
In hindsight we learned a couple of things from A/B testing.
* In a page with a lot of asynchronously loading content everything can be precisely altered before the user can notice it. The more precise form of delay were recursive setTimeouts where the interval delay could be manually adjusted to the millisecond and there was never interval overlap. This took practice to know when and where to increase the interval rate without impacting the performance of other logic already in the page.
* The tests did not often reflect the actual business results compared to the production code written later. We found the test logic, even though it was just hacky throwaway code, was generally less defective and faster executing than the more thoroughly tested production code and so performed better than the actual results from the formally released code.
> A/B tests are a form of white hat hacking where code is injected into a page
No. The idea of A/B testing does not require DOM manipulation or code "injection" after the fact on an already rendered page. I don't know about your A/B tests, but A/B tests in general are site experiments you run on your users/customers -- the idea does not in general involve code injection, or say anything about the implementation. I have built A/B tests in React myself, and there is simply zero technical or performance issues with doing so. You render one thing for some people, and a different thing for other people, and measure their reactions.
It might not make sense to use React or Angular for you, for your particular site design, but there is nothing wrong with implementing A/B testing using React in general.
There's nothing wrong with using JQuery either, if you want direct DOM manipulation. It would be worth studying why your previous A/B tests were slow, because it can uncover some knowledge about JQuery. There are bad practices in JQuery, there are ways to do things really slowly. There are also ways to fix it when it goes slow, and learning those things might be overall a lot more efficient than resorting to pure JS DOM manipulation.
Yeah, that makes sense. The specifics of what you're doing certainly will drive what the implementation looks like. It makes sense that using Omniture for tests means that pure JS DOM manipulation is the best way forward. This detail is actually incredibly important to your story, and so I think it's easier than not to draw the wrong conclusion from the story because that important detail was left out. Omniture testing might be something a lot of candidates aren't exactly clamboring to spend their time doing. Certainly, with an A/B testing job I would be hoping and aspiring to learn more about things like site UX, maybe some data science, do HTML & JS that is relevant to the business team, and be involved in the production site's implementation and design, etc. I would personally be less excited about using an older legacy testing framework that requires low level DOM hacking, especially if it seemed separated from the core dev team. How do you implement the design that wins? Does the A/B test writer's version get put into production, or does someone else take the code injection and translate it into HTML?
> Major commercial sites are built with little to no direct DOM manipulation.
Little implies some, and I think the average bundle is already large enough without saying, "Oh, just throw jQuery in there whenever you do need to do DOM manipulations.", which will happen. I built a React app a couple weeks ago where I had to use portals to integrate it with a legacy form solution because we didn't have time to rewrite the entire form backend to justify a custom frontend. It involved a fair amount of manual DOM manipulation, but it worked out fine. All said and done, it was probably ~75 lines in a file with a few more comments than usual. It doesn't make sense to add 30kb or even 10kb to the bundle for that, so yes, I would expect the average developer to know the base DOM api at least somewhat well.
edit: I completely forgot about TDD. Depending on your testing environment, you may need to understand the DOM api for mocking or base utilities built into the test suite.
I did not suggest using React and Jquery at the same time, and I don't really encourage that. I do not agree that it's a slippery slope and people will just start using JQuery with React. It's possible that something is already starting to go wrong if you're trying to manipulate the DOM using both React and DOM manipulation. The very point of React is to avoid direct DOM manipulation.
I've been in about half a dozen interviews in the last 6 months and I've never had to do this problem, but honestly my first reaction would be "this is a trick problem" out of paranoia that it's too easy. I wonder if more anxious people fall into that trap and overthink it to the point of overwhelming themselves; kind of like freezing up during an exam that you studied extensively for.
My biggest issue in interviews is remembering the recursion formula with some of the sorting algorithms. I eventually get it, but I end up burning a good chunk of time figuring it out, so it looks bad. In my entire career (almost 15 years now?), I've never had to use recursion or sorting algorithms believe it or not. That's what I get for working strictly on enterprise business applications.
I recently built a small side project in vanilla js for fun. I just didn't want to break out webpack and waste an hour getting it set up.
I got pretty far, did all the design. I wanted to run a client side simulation in javascript though, and found I needed to host a local server as chrome refused to read modules from a file due to CORS permissions (running chrome with the usual arguments didn't fix it).
At this point, since I needed an outside piece of software to run things anyway, I figured I might as well switch to webpack dev-server and get the whole modern frontend ecosystem. I then quickly started replacing my home grown dom syncing with vuejs, and snowballed from there.
I definitely learned a couple things, so time well spent, but I'm also going straight to webpack next time. I know it'll only take a few hours before I start hitting the limits of what vanilla js can do, and while reinventing the wheel was fun and educational, it didn't result in a better wheel.
Seriously, the poster is going to have to host their files somewhere eventually if they intend anyone else to ever see it. I can't believe they rewrote all their JS because they were forced to access over http:// instead of file://. This seems nonsensical.
A simple web-server only does that: serving a website.
With a proper webpack setup, you get imports/exports, (node) module bundling, live reloading which all massively improve your development speed.
However I wouldn't recommend anyone to build their own webpack config if you don't know exactly what you're doing. Just use parcel: https://parceljs.org/
It does many things an advanced Webpack project does, but without any config. I use Parcel as long as possible and then switch to lower-level Webpack when I need more control. Easier way to start a new project.
If you want to spin up a project without doing config first then https://parceljs.org/ is a really good place to start. It does 95% of what most people use Webpack for, but with no config.
It's also worth noting that if you just want a bundler (with no server or hot module reload stuff) then Webpack with no config usually works for most projects that aren't doing anything advanced.
I started trying to answer your first question, when I realized it’s a reasonably good question. Webpack doesn’t automatically change your JavaScript, so it is possible to use vanilla js and also Webpack. Colloquially though, “vanilla” is also referring to not using a pre-processing step of any kind, and not having project dependencies, basically directly writing the files that are loaded by browser.
Hey dammit, we’re autistic programmers, not pedantic dorks! ;) But seriously, I’m not sure that’s entirely fair. I do think Webpack feels not-vanilla, even if it doesn’t change how you manipulate the DOM.
... why would people wonder that? You expect a community of hackers to not nitpick? A group largely populated by programming people who are entirely accustomed to a single character changing the entire function of a statement and who frequently expect natural language to work the same way?
Because you end up with Webpack runtime code in your bundles. No different than if you included a library’s source code in your code— it would not be vanilla JS.
It is how Webpack works, actually. Webpack does not support bundling to native ES6 modules [0], it has to bundle into a format which requires runtime code being injected to execute properly, handling imports, and whatnot instead of relying purely on native ES6 modules.
Have you ever looked at the contents of a bundle? [1]
Long story short, Webpack circumvents native ES6 modules in favor of other module formats. It provides a great amount of utility, but it is not Vanilla JS.
I want to give you the benefit of the doubt that you're being sardonic but just in case I meant IE doesn't support ES6 modules so thereby following your narrowly pedantic definition it isn't very vanilla.js
My point was not that you must use ES6 modules— my point was that webpack does NOT use ES6 modules so it must include a framework for importing, exporting, and otherwise consuming the bundles.
Serious questions, please don’t dance around them:
How is what I described above still Vanilla JS?
Would you consider using TypeScript to be Vanilla JS? Why or why not?
Would you consider using lo dash to be Vanilla JS? Why or why not?
Also, Vanilla JS is pedantic. The point is that you don’t need any of these tools to make a website or web app.
I personally like the tools I use, I don’t care about vanilla js. But you can’t just try to argue it’s not obviously meant to not include a bundling or transpiration step.
Furthermore, making a site/app with everything being vanilla js EXCEPT for also using Webpack is certainly as admirable— but it makes it not vanilla js.
The programming environment usually is not deployed to the runtime environment, so it's not a part of the built program. Libraries are.
"Vanilla" language or tool has a precise meaning of using the official tool without external customizations. If you are importing a library that is not part of the language standard specification, that's by definition not vanilla.
Using a development environment is not a "customization" of the language, because javascript has no official development environment that you could customize by using a different one, so the environment is not a part of the language.
For languages like Smalltalk implementations that have an IDE+runtime that is THE official development environment and specification, switching the code to a different IDE+runtime would indeed be using a non-vanilla version.
index.js
var foo = document.body.getElementById("bar");
That is dom manipulation using vanilla javascript in all modern browsers. I can use webpack, rollup, parcel, or load it in a script tag, it doesn't matter it's still just plain old javascript.
true, it doesn't. but imo when people say "vanilla js" they mean both no framework to abstract DOM manipulation and no build steps, whether they be transpiling from ES7 or bundling stuff. perhaps webpack can be used to just minify+concatenate a few files together, but that's not how it's usually used, and i guess not what most people mean when they talk about webpack.
i am a bit biased, based on my recent experience of trying to load a webpacked library's `dist/foobar.js` into a WordPress thing via a normal <script src="..."> and having it barf all over the console, yelling about `window.module` missing and loaders and stuff. i never managed to get the bundled version to load, which reinforces my opinion - it's not "vanilla" if it needs some custom infrastructure and can't just be dropped into an existing plain js environment.
i did however manage to load the unbundled source with a native ES6 <script type="module">, and it worked great! vanilla js can be pretty pleasant these days :)
i'm sure it means many things to many people :) obv i only speak myself here
ignoring framework stuff (bc everyone seems to agree there) i'd say if your js qualifies as "vanilla" if it can run in a relatively recent browser without a build step or other transformations. you might further ES5-ify, uglify and minify it for practical reasons, but that must be an optional thing
---
since we're splitting hairs, we could also distinguish "theoretically vanilla js" - js that's standard ECMAScript so it'll run fine when browser catch up, but it's not supported just yet and thus needs transforming. this would exclude non-standard extensions like JSX
and note that i don't mean "vanilla" as any sort of value judgement! it's a practical description of how it works, not some kind of platonic ideal to aspire to – frameworks, webpack, Babel etc provide useful solutions for the shortcomings of the browser platform and ecosystem. the thing i was talking about is a single-file internal tool, and compat isn't a problem; if it was user-facing, i'd probably use some ES5-ifying tool myself. and i'd probably use JSX if i was doing a React thing, because it's great - inline HTML is an underappreciated convenience in PHP!
> I get "trying to stay vanilla", but any reasonably-common snippet should either be installed from npm or published there.
And that's how you end up with the joke that was left-pad and the broken internet that resulted when the author yanked it.
Dependencies represent a real risk to your product. If it is actually a simple snippet, you shouldn't take that as an NPM dependency - the risk/reward ratio is just way out of whack with that.
NPM disallowed un-publishing modules within a few days of that incident. It's not a thing that happens any more. Also, NPM for years has defaulted to creating lockfiles with all the specific versions of dependencies pinned, so even if a dependency gets updated to have a bug, you will stay on the currently-pinned version unless you specifically change that.
But anyway whether or not the module is un-published doesn't really matter. The module could also just become malicious. Ownership changes, quality of code changes, etc... If you're pinning with lockfiles you're basically back to copy/pasting or checking in a clone of an upstream repo - the maintenance burden shifts back to you at that point. You still then have to manually go update, and remember to do that, or you become just as easily obsolete as the copy/pasted snippet.
There are downsides to use package libraries as well. Like: 200mb hello world applications, or some companies restrict npm packages for security reasons.
Or, you just want to write code in notepad.exe. There is benefit to simplicity in many cases.
It's up to you to chose reasonable modules by reasonable developers. Notice I didn't call it a library, it's a 1kb module that has the code from the example + fixes you'd want anyway.
What overhead? You don’t run any optimization step on your code? I haven’t seen a single front end project without package.json in years in all the companies I consulted for, and I don’t even deal with fancy frameworks.
Nice collection of recipes! Just a few quibbles about the website design:
* The back and forward buttons lose scroll position.
* Visited links look the same as non-visited.
* In each recipe, top 70% of the screen is headers and whitespace, bottom 30% is content (on my laptop).
This is a really great set of demos! The resizable table columns really irks me because I spent so long trying to make something similar and it ended up being hundreds of lines longer.
Pretty good! My only wish is that the site would be like http://youmightnotneedjquery.com/, so that the content would be viewable just by clicking the heading and having new space for it, perhaps in a fixed window, instead of separate pages.
Are there any starter tutorials that would build from vanilla JaveScript, implementing solutions to developer problems, then demonstrating how one might use an existing, well-exercised framework to solve those problems? Every time I go try to learn about a framework from the project web site, they assume a tremendous amount of context.
Tangentially, my most recent frustration: I wanted to try a couple frameworks together (they had no overlap in functionality - not like trying to use React and Vue together), and they both came with CLI tools to initialize an empty project and complained when it wasn't empty. They both had different opinions about how to structure project directories, and neither explained in an obvious place how else one might get started.
It's a difficult place to start from, because a lot of react tutorials are out of date, misleading, shallow, or deep in useless ways.
I think most people learn these frameworks by being put to work on a mature code base with established patterns, that already uses a set of frameworks. At first, you kind of don't understand the control flow, but you get better week over week from there. Over time, you are bootstraping your own opinions by asking questions and learning hands-on.
Eventually, you can start a project from scratch including the minimal dependencies yourself, as you learn what's actually useful, vs what's "the same interface, but dressed for business".
That being said, I'd recommend getting started with `create-react-app`, and following some of the tutorials. I'd then recommend jumping into hooks (https://reactjs.org/docs/hooks-intro.html) as soon as possible, unless you have to maintain an older codebase that uses classes, because in "modern" react code, you're almost never using classes any more, and that reality bomb is not typically dropped on you in most react tutorials.
It's always worth learning a level lower from what you do, so if you write frontend UIs with React it's worth learning how DOM manipulation works with vanilla JS to understand the intricacies and appreciate what the library abstracts for you.
If you start writing a site in vanilla JS you'll eventually end up writing your own UI library basically reinventing the wheel which is fine as a learning experience and personal projects but maybe not the best choice if you're working on a large scale project with many developers since UI libraries and frameworks provide a common set of patterns as convention to follow that makes it easier for everybody to be on the same page.
Great resource. I'm wondering whether the examples are your own or copied from across the web?
I just wanted to point out that some of them are a bit outdated, and I belive it'd be nice to maintain this list as a reference with modern approaches.
For example, there's no need to use `appendChild`, because DOM today has a more versatile `append` method.
And `[].forEach.call(cols, function(col) {...}` would look much better and more declarative as `for (const col of cols) { ... }`.
You're correct, but let/const don't have full support in IE11 either.
I understand that people are still supporting IE, but still, this website could stay relevant longer if the examples were written in ESNext.
One of the issues here is that the examples don't add any accessibility hints at all. We really should be encouraging people to add as many as possible!
Slightly unrelated: I am a complete beginner in Javascript, and I was trying it out for a small web-based UI. I was surprised how importing one js into another was non-intuitive. One would need to import all the js's into the main HTML. Feel free to correct me if I am abusing it.
Meta-proposition: why can't I tell Google to weigh results from this (or some arbitrary site) higher after I have confirmed its usefulness? Searching through JS docs is a nightmare filled with outdated libraries and scummy SEO articles... so hard to filter through the noise.
Yes of course, but that would involve managing a list of resources and sites. I suppose one master list would be ok across a range of topics but still seems a little cumbersome. Maybe could be built as an extension.
> but a foundation, even a small one, is super valuable
Well, I mean, first example is "ele.classList.add('class-name');", beginner or not, you gotta understand where `el` is coming from. Seems like a big oversight to have incomplete samples, even from the first example.
The trick to manage the DOM with vanilla HTML is to not use HTML! Then abstract code into functions.
The advantage with modern JS frameworks is that they make it easier to handle state, and state handling is usually very hard. The trick to state handling in JavaScript is to make use of closures, to prevent the anti-pattern of global state where you don't know which functions change what state. The only function allowed to change the state should be function that created the element! This can be achieved with event listeners that listens for messages from the server.
This is such a wonderful resource, I wish we had it when first building our app, which uses no frameworks or libs. We do use TypeScript to generate it, hard to pass up the benefits and syntax it provides.
Js Frameworks are built on top of vanilla JS, so if you build an application of any complexity you will eventually start to abstract functionality until you have your own (probably bad) framework.
Ahh thanks. A lot of times you use these fancy frameworks and don't know what's going on at a lower level. Understanding this makes you understand the fancy frameworks faster.
I love this. It doesn't matter what framework you use, having to raw dom manipulation is eventually a task for any seasoned frontend engineer. Understanding the dom api is absolutely essential, when performance is paramount. Resizing tables, drag/drop, e.t.c any advanced interaction will need control of raw dom. Thanks for writing the little recipes.
I'm not dissing Frameworks. They are a tool that help you with certain kinds of problems. Any crafts(wo)man, should know their tools well.
DOM diffing is great for most stuff. When you need anything other than "Replace this with that and don't defocus my input fields", DOM manipulations are great. Drag'n'drop is a great example of this.
There is a lot of potential for the imperative APIs for this though. I even made a proposal:
I think everyone should know how the DOM works under the hood but the HN hate for frameworks and love for vanilla JavaScript is just unbelievable. As soon as you venture past small JavaScript sprinkle you will regret using vanilla. It feels like a made-up opinion by people who are actually not developing front-end JavaScript seriously. The DOM API is simply unfit for real web apps without a proper framework on top.
Agreed. The only way vanilla JS scales to a large codebase is through serious discipline and internal tools, essentially creating an ad hoc, poorly specified, home grown framework. Even the web components standard is insufficient without abstraction layers on top.
Not all codebases are large, and not every site is, or needs to be, enterprise scale. I think HN sometimes forgets that there's an entire web outside of FAANG+ and startup culture that doesn't care about any of that.
I don't think you need to be enterprise scale to justify using a front-end framework. Anything above trivial complexity is enough and it will give you headroom to scale as a bonus. I think a more common mistake is to use a framework when you could just as well render it on the server with the same result and being simpler at the same time.
But when you do need to create a dynamic web app, you should definitely use a framework. Using vanilla will just result in you creating your own half-baked framework anyway.
Its hard to see why the JS frameworks came to be, and easy to see the up front complexity of most of them. People who started before good frameworks were around take it for granted that people know what happens when you build complex sites with vanilla JS: You get a mess, or you get your own framework.
Not everybody wants to render everything on the client. JS frameworks (vue included, despite trying) do just not support rendering as a simple page.
Some people do have light needs that won't ever require a full framework.
Other people have very heavy needs that will require their own frameworks. The JS ones (react included) are not absolutely flexible.
And, if you fit none of those categories (honestly, most people are on the first), just replace the title with "how does a JS framework operate on the DOM", and take it as a learning resource.
> Not everybody wants to render everything on the client.
No, and then you should just render it on the server. Most "apps" should not be JavaScript apps at all. However, once you do need to enter that territory you should definitely use a front-end framework.
There's a large range of approaches between a heavy framework like React and vanilla DOM manipulations. jQuery is one such popular solution, and I don't see why such helpers should be completely avoided. Another (full disclosure: I'm the author) is: http://techlayer.com/espresso.js/
It still doesn't go POST in a nice way like the jQuery API does BUT it is not worth bringing jQuery to the page just for making requests with slightly nicer syntax.
One thing that would massively improve this is if they were written as singular standalone blocks instead of sparse collections of snippets; I'd like to be able to grab, say, "make an element draggable" and toss it on my codebase as an isolated behavior.
This kind of thing sounds great on personal projects, but doesn't scale. Like many abstractions, frameworks' biggest benefit is (arguably) making it easier for teams to work together.
Which is quite funny as it serves as very good demonstration why one should use jQuery: most of presented examples are 10 times more longer when it comes to code amount or alternatively there is some weird oneliner. All of that for saving 30KB of battle tested cross browser code.
This is a great resource. I've had to dig through a lot of StackOverflow threads to figure these out. Great to have lots of current answers in one place.
I feel like Safari should be included in there as well. Safari is the new IE, they're so slow in adopting new specs. With IE having moved to chromium and Firefox having solid contributions to the spec and always being on the bleeding edge, we were bound to see the it be the one fall behind given Apple's slower cadence, but I've been amazed at how much of a blocker it's been.
I have never used the dialog HTML element before, but I was playing around with adding an input type="password" this morning inside a HTML dialog and didn't see any problems.
> And is built in react. It's about choosing the right tool for the job.
React is useless here. Try browsing the website without JS and notice how litterally nothing changes.
The only things that need JS are the light filter at the top and the fast navigation using body/head swapping + pushState, none of which require React.
It really isn't. Teaching newbies to venerate JSX and React is far more harmful in my opinion: it does a really good job of hiding what's actually going on.
These days vanilla JS DOM APIs are pretty straightforward. It's well worth learning them and using them on small projects where a library like React is absurd overkill.
It’s not veneration it’s the idea that devs should understand the way things work underneath the over engineered abstractions FAANGs developed so they could onboard new grads to web development faster.
What is tantamount to educational malpractice is the pathological revulsion javascript developers have for their own language, such that merely teaching newbies how to actually write it without six proxies, three other languages and a framework to protected them is considered harmful.
Sure, either Javascript is an intrinsically good language, and you should therefore be able to use it as is, or it is not good, in which case the sane response would be to use it as little as possible. Every language has warts, but most can at least go out in public without layers of makeup.
>either Javascript is an intrinsically good language, and you should therefore be able to use it as is, or it is not good, in which case the sane response would be to use it as little as possible.
That's a false dichotomy. There is no such thing as an intrinsically good or bad language, and if the use of frameworks demonstrated the intrinsic flaws of a language, then all web-facing languages would be equally flawed, because no one avoids using frameworks in any of them.
Learning how to write "vanilla" JS (that term really bugs me) and how the DOM actually works is valuable regardless of whether the scale of most modern applications makes it efficient or cost effective to do so.
You know where vanilla JS still has a legitimate usecase in the era of SPAs? Landing pages.
- Mostly static HTML, time to first render is critical, all you want is a little bit of (progressively added) flair
- Can be inlined for instant loading/execution, no bundle download (or SSR) necessary
- Code has low volume and scope so structure / spaghetti isn't a concern
- You can separate it out from the rest of your SPA bundle(s), so shipping changes is completely decoupled from your SPA CI/CD process and can be done as frequently as you like and very quickly