Professionally, I do embedded and robotics, but once a year I find an excuse to create a simple web application (to stay updated). Every time, I get impressed by power and simplicity of the web technologies in general. In JavaScript those are things mentioned in the article + WebComponents. For CSS those are flexboxes, grids, and animations. In my opinion, React made a revolution with hooks and contexts. I love the direction in which the web world has been going!
Try writing a GUI with other toolkits. Hours of tweaking random XML to try and figure out why some constraint solving thing just isn't working...
Despite all the mess, I have an easier time getting buttons on a screen and doing things sanely (once all the fuss is set up) compared to trying to get the ball rolling in Qt/GTK/etc (especially if you're not using Java or C++)
Absolutely not true. Windows forms, WPF, JavaFX, Swing all are much more productive than the vanilla web. Like, how many lines of code does the most basic vbox/hbox thing requires in web technology? Many of them even have dragndrop ui creations, and this XML hatred is downright stupid at this point. How about criticizing the technology and not a random medium for that? Is writing something stupid in JSON inherently better?
HTML is simply a terrible GUI base, JS is quite great nowadays and CSS would be great, but has to provide way too much of what HTML should be doing. But the web ui frameworks are just barely getting at the level of where native frameworks have been in a decade.
That example you mentioned would be just a couple of lines of html with css (which you could inline if you wanted), and there are plenty of drag and drop tools for the web (WebFlow is a modern example, but they have been around for decades).
Why would it need any sort of CSS? Isn’t HTML supposed to be responsible for the structure of a webpage? And of course it can be done, but if we do something like hbox inside a vbox inside a vbox, the resulting code will be ugly as hell (perhaps Webcomponents will help a bit here?). Like, what is the point of HTML at that point? To spam divs (pun sort of intended)?
And there are plenty of other “layouting primitives”, all of which are quite cumbersome. And due to HTML encoding some form of semantic meaning only (though seldom used even for that), drag n drop tools can’t generate easy to read/modify output. Also, without js frameworks, you can’t really just embed another component into it trivially.
And I’m not trying to shit on web tech, JS has absolutely overcome its shitty past, and is quite a likable language nowadays, and CSS is an extremely powerful and expressive system (though this latter is due in part to how shitty html is). My only gripe is with HTML that is simply not fit for the task (as it was never meant for that).
There are a couple of exceptions for interfaces that are genuinely unconventional, or that deal with multiple spacial dimensions, or that are primarily representing graphs and visual/audio data. But most interfaces should be representable in pure text.
This argument that "the web is only for documents" is missing the point that most applications are just interactive documents when you really break down their UI. A labeled tree is a fine way to represent user-facing state for most apps, and most apps would benefit from exposing a more semantic interface to users that was easier for them to manipulate and read programmatically.
Nothing, because web applications are by definition html css js. Though canvas-based solutions can circumvent the layouting problem, but at the price of reinventing everything in a non-standard way.
Drag n drop UIs don't really help when you have too much dynamism (like "oh only have this button appear in these conditions", "do this here", etc). And I would say that box layout offered by CSS is much nicer than the constraint layout system _when you have a lot of dynamism_.
Like I wouldn't want to have to deal with an interfrace like facebook in native stuff. I don't think it's impossible, but I feel like it would require a lot more up-front design and correct engineering.
You're right about XML being a medium, just kinda my memories of working with this stuff.
Such a great point. HTML is a terrific way to write documents and TERRIBLE way to lay out applications - especially for lots of different screen sizes. It's not surprising at all to see Google embracing Canvas now to underpin Docs; basically they are admitting that it would have been better to write the whole program in a Java VM or in Flash than to rely on the browser for layout. This is patently obvious to anyone who builds large web applications. Ten years ago we had ASWing, JSwing and plenty of other actual frameworks where you didn't have to diddle around with tons of logic embedded in templates which were embedded in other logic; but thanks to Apple we're still saddled with this wretched Javascript/HTML paradigm that was never meant to do much more than inline some animated GIFs back in the 90s. Yes, it's gotten better (I've been doing this since the 90s, so I know). But it's so inelegant. To some degree this is just a problem with open web standards. It would be better if any one company actually had dominated to the point where they could write a closed standard, because at least it would be coherent and cross-platform. It was a lot easier to write a web app in 2010 than it is now, and it pains me to think how many hours I could have avoided reinventing the wheel if Flash had been allowed to stick around. Any app written entirely now on canvas is just replicating a VM that already existed a decade ago in what was by then a much more mature ecosystem - and was faster then than canvas or WebGL is now.
If I had to pick a stack to do a new web app entirely in canvas, I'd probably choose to port a ton of interface components from AS3 into PixiJS... but the point is, where have we gotten? Ten years from now we'll be writing apps the way they were written in 2010 -- inside a black box in a canvas or VM. The HTML5/JS revolution has been a sham from the start, just a way for one corporation to dismantle another with the side benefit of forcing all of us to rewrite our code from scratch in a crappier language.
I'm not sure I buy the idea that "efficient and easy tooling around a technology makes the technology". We all went through the same Dreamweaver pains.
How come the minuscule userbase of native frameworks have better tooling than the numero uno popular web? It may mean that there is a technical reason in the background.
They solve a simpler and more constrained problem which makes it easier to make tools. Something like Windows Forms are basically WYSIWYG - you drop some controls on a canvas and now you have a GUI. But the GUI will not gracefully adapt to different screen dimension from large monitors to mobile.
It's younger than the web but much older than the current bunch of frontend technologies. JavaFx is from 2008 [1]
Anyway, that's not very important.
What web apps never had is a visual app builder as popular as the first Visual Basic for Windows 3. We had some tools like that (example Jwt [2]) but none of them got a critical mass of users. Maybe it's difficult to match Visual Basic's success because Microsoft controlled the tool, the operating system and the language. If this is the case the only current candidate is Google, because of Chrome. They are investing on Flutter and Dart now but making them prosper on the web looks like a uphill battle. Much easier on Android.
> I have an easier time getting buttons on a screen and doing things sanely (once all the fuss is set up) compared to trying to get the ball rolling in Qt/GTK/etc (especially if you're not using Java or C++)
I agree that it's pretty simple to get a button on screen in Qt, but your linked video presents it as horribly complicated. And requiring an IDE to do it is pre-admitting it's complicated.
By the way - Qt and GTK are super-outdated ways to do GUI in C++. Popular, but outdated.
> but your linked video presents it as horribly complicated.
... could you precise that more ? I'm literally just making "new project" > design view > search for the button component > drag'n'drop it ? How can it get more simple ?
(opening a text file and writing "Button {}" is definitely more complicated if we're talking about teaching to beginners)
I mean the second case is generally discoverable for a programmer because there will documentation of a language or API. I believe people are generally aware of discoverability of documentation in 2021.
> I believe people are generally aware of discoverability of documentation in 2021.
as someone who teaches programming in university, that's definitely not true, less than 1 in 20 students has the reflex of looking for any kind of documentation (even after showing it to them)
well I'm discussing what is easiest for working programmers, although it's true I do hear about there being a bunch of really bad ones out there so maybe I am just assuming too much.
Just that starting modal with 6 steps to choose various configuration stuff would probably throw a beginner into a loop for a while, even if you could just skip it all. Maybe if this IDE wanted to be beginner friendly, they ought to consider just having reasonable defaults and letting power users change them later - like how web tools tend to be designed these days.
There are visual editors for React. Pretending QT is easier than web technologies because it's easier to drag a component in a visual editor than type text in a code editor is comparing editors, not UI technologies.
Well, the question of what's "modern" in C++ is both deep and contentions. But I won't shirk the question...
You want to be utilizing the features C++11, C++14 and maybe even newer versions of the standard allow you to use, to avoid unnecessary boilerplate, repetition, and arcane-ness of syntax and semantics.
Similarly, the GUI toolkit should not be based on C-like or C++98-like design patterns, when newer versions of the standard allow replacing them with more convenient patterns.
Here's one example, from the Nana C++ GUI toolkit:
#include <nana/gui.hpp>
#include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/button.hpp>
int main() {
nana::form form;
nana::label label{form, "Hello, <bold blue size=16>Nana C++ Library</>"};
label.format(true);
nana::button button{form, "Quit"};
button.events().click( [&form]{ form.close(); } );
form.div("vert <><<><weight=80% text><>><><weight=24<><button><>><>");
form["text"] << label;
form["button"] << button;
form.collocate();
form.show();
//Start to event loop process, it blocks until the form is closed.
nana::exec();
}
This is not perfect IMHO; for example, I don't really like the confusing div string with the many < and > signs. But you can put this in a text editor, build it with `g++ -I/path/to/nana/includes -L/path/to/nana/libs -lnana` - and it will just work, on various platforms. No secret sauce, no need for a bunch of IDE dialogs or any special configuration or action.
There is a wide world of applications and development that don't have anything to do with the web.
The films you watch on TV or at the cinema were not created (edited, VFX) using a web browser for a start, and the User Interfaces to those applications are pretty Graphical by anyone's definition...
As a counter point: plenty of desktop software embeds web technologies these days and even AAA games occasionally use them. I think Battlefield was a prominent example for React being used in AAA games for UIs. The Horizon TV streaming box also had a UI written in React (rendering to canvas for performance using their custom Chromium build I think, but they wrote it so the UI could also be rendered to the DOM so they could use it in their web version).
Not disagreeing with what you said, but "not having anything to do with the web" isn't as clear cut as it used to be and web technologies are increasingly showing up in unexpected places.
Having worked on both desktop and web UIs the problem you're describing occurs in both worlds. Usually with web you run into it when you're dealing with a more sizeable app, or fancier things you want to do with your framework.
Sounds like "developer productivity" could be increased by not having to create GUIs. As an end user, I will happpily accept and in fact prefer text-based, keyboard-driven interfaces.
There are different definitions of "simplicity". The entire stack top to bottom may not be simple, but if the developer experience is simple (which it can often be on the web- that's a major driver of the web's prevalence as a platform), that can be what matters.
I have a theory that the people who go on about how the web ecosystem is too complicated are either 1) web developers who are nostalgic for the jQuery days (and have selective memories about those days), or 2) non-GUI developers who enjoy the theoretical virtues of a QT or a GTK but have never actually had to work on a complex GUI, and so can't appreciate the incredible benefits the web has over those other platforms.
Maybe you are too young, but there was a time were we used RADs (Rapid Application Development) environments like Delphi, VisualBasic, Visual C++, etc. Those solutions which are from 1990s, are still years ahead in simplicity vs what you need to do to build a full web solution today (front-end and backend). Of course the web has many other benefits, like 0 install, runs everywhere, always updated, etc., but calling web development simple is just crazy in my humble opinion.
I have worked with both, including Widgets and Quick. I wonder why you think Qtcom is focusing development on Quick, which uses QML (JSON-like syntax) and JavaScript (ES6), while declaring Widgets "feature complete", mostly releasing minor fixes, in other words, keeping it stagnated. The obvious answer for me without getting into Mobile vs Desktop development is: it's easier to get new professionals to use technology as popular as JS (or any other web related stuff), and definitely cheaper for companies to hire said professionals, therefore making it a easier pick for new projects. To summarize the benefits: easier for junior devs to use and because of that overall cheaper/faster deliveries. Note that I'm not saying anything about quality.
Junior developer doesn't mean a developer who just knows JavaScript. Cheaper developers doesn't mean faster or cheaper delivery in the long run. And I don't think brundolf meant cheaper developers.
In my 20 years as a developer I’ve learned that the more polished something looks on the surface, the more complex the codebase under the hood becomes. Things are simple to the end user because of all that complexity.
That is my experience, too. I worked on a SPA with a more or less simple looking table that presented hierarchical data and made them editable with form elements. Under the hood there were hundred lines of very dense rxjs code and the whole thing was communicating with about 10 HTTP endpoints. But it looked simple.
There's preact/compat sub-module for the remaining react features, please inform yourself before inappropriately flaming someone. There some very slight differences https://preactjs.com/guide/v8/differences-to-react/#what-s-m... nothing blocking at all
Seriously. I’ve been doing web development professionally since 1998. I’d love to have OP write a blog post to teach the rest of us about this simplicity.
I've also been doing web development on essentially a daily basis since the 1990s.
I got pretty tired of chasing the fad explosion. Here's what I build everything with these days:
HTML, CSS, JavaScript, Go or PHP, Redis, MySQL or Postgres, Ubuntu & Nginx. Occasionally I'll make use of an ancient version of Sphinx for easy, fast search. I also sometimes mess with Vue for fun, as I happen to be fond of it, but I never find that I need it.
No frameworks. No containers. It's all mostly boring and ancient. I use DigitalOcean for about 95% of everything hosting wise (and rarely AWS). Works beautifully, everything is simple, blazing fast, light on bloat and rock solid.
The simplicity is still out there, if you don't have to care about what anybody else thinks, if you're not trying to earn a living doing web development (everything I work on is self-determined). That's a big if unfortunately. If you are trying to earn a living doing web development it's understood that chasing the latest thing isn't optional, as you can't afford to miss an inflection.
What sort of systems are you building ? I’m guessing some variation of CMS, shopping cart or simple crud backoffice reporting systems.
I’ve spent 14 years working for a small agency building these sorts of systems. I kept up with all the cool new stuff that’s come out and played with it but all we ever needed was 2 load balanced app servers with a single instance Postgres database and we ran some pretty chunky systems.
I’m now looking for a new position and this attitude has come up to bite me. I’ve always been dismissive of the new dangled complexity but turns out there are systems out there that churn through so much data that mongodb makes sense, and large teams of devs where splitting systems into separate services and writing reusable components is required which is where frameworks and inter process communication tools come in.
Most things exist because there is a need for them.
The last thing I built was a CMS structurally (a new non-commercial knowledge service), took about ~18 months to build. I plan to work on it for the rest of this decade approximately.
Currently working on a couple of trading systems (for physical objects, not financial). That's in the ecommerce sphere technically, although they're not monetary transaction based. The first one will hopefully launch in June. I might Show HN it.
Both work perfectly with the setup I described. I build in my wheelhouse though. I can build services like Stack Exchange, Quora, Wikipedia or Reddit (or most things in standard ecommerce, ecommerce platforms). I know what my stack is good at, and what it's not appropriate for. And at this point in my life I know well what I'm good at and what I enjoy, so I look for opportunities there.
MongoDB IMHO also has resource allocation issues, because for a simple two "node" distribution setup you have ~4 times the demand for resources than a "regular" clustered service like Postgre or Oracle. Added to that the actual promised efficiency relies heavy on the data model and has no real easy way to correct once deployed.
How do you get four times the demand for resources from two nodes?
The "promised efficiency" of any system is a complex question. The dynamic schema approach of MongoDB makes it trivial to update schema design on the fly so I am confused by "no real easy way to correct once deployed".
BTW : The recommended production setup is three nodes (one primary, two secondaries). This is what you get by default in MongoDB Atlas (you can't go smaller).
I was talking about a two "node" Mongo setup which would mirror the capabilities of a classic two node setup of Oracle RAC for example. Since in Mongo this is not a clear 1:1 match due to a different model of operation, in order to get the same performance/continuity as RAC here is what I mean.
If I want to gain a relative 100% increase in concurrent read/write access and transparent session failover to my application I have to procure two servers(with roughly the same performance lets put it at rawPerf=1.0 for simplicity) and a SAN/NAS with SCSI HBA and that would be it. All the necessary components will be running on those two servers and the application will have access to almost all capabilities of a single instance with a roughly twice the performance and fault tolerance. To do that in Mongo, I would have to procure 2 replica sets with 3 instances each(bare minimum to get the fault tolerance and not use arbiters which according to Mongo University is a bad idea) for the actual data and another RS for the configuration meta-data, which is another 3 instances. I will also need instances where I can run my "mongos" to route/consolidate my requests and to have fault tolerance I will need at least two of those. Now to do a break down of the different instances. From the two replica sets for data, I can use only 2 of the instances for writes and the remaining four only for consistent reads and that is only with the appropriate write concern. And while I have two instances for writes I am not guaranteed to get a consistent increase in write operations unless the data is at least somewhat evenly distributed. I will need six rawPerf 0.5 servers(assuming 0.5 rawPerf is capable to handle roughly half the data), that is a total of 3.0 so far. The configuration RS while not as demanding as the actual data RS will still require resources so I count it as roughly between 0.5-1.0 total for all three instances. And finally I have the "mongos" instances which although will not need disk space will need some CPU and the same amount of RAM as a regular instance in case the queries and not optimized, so I will have to give it 0.5 per instance. And the total amount of resources comes to 3.0+0.5+1.0=4.5. On the other hand with the Oracle RAC I would've needed 2.0.
As for the schema flexibility, from the Mongo documentation I take it that once the shard key is created it can't be changed arbitrarily. It can only be further fine-grained by adding more keys to it, however this is available from version 4.4. In order to change it cardinally, I would have to recreate the collection.
I'm sure you are well aware of all this, however I'm just stating my experience with MongoDB so far.
AH I see. When we talk about nodes in MongoDB they are the elements of a replica set. That is what confused me. Yes, you are right, to get the equivalent performance of a two node database server you would have to run a sharded cluster with two shards. That is definitely more nodes than the two node design you have outlined for the RAC like design.
I am not familiar with Oracle RAC architecture but casual mention of a SAN fails to recognise the cost and complexity of even the smallest SAN. On the other hand MongoDB can run on dumb disks without a SAN or RAID required (though RAID can help with performance).
With you two node system loss of a node results in a 50% loss in performance whereas with MongoDB loss of a node will result in a secondary taking over the primary role with no loss in performance. You get what you pay for.
Setting up such clusters used to be a PITA until the advent of MongoDB Atlas. Now you can set them up with a few mouse clicks.
As regards shard keys. Yes, they are immutable, but the documents they index are not. So dynamic schema properties are preserved in a sharded cluster.
While a SAN/NAS is overall an expensive hardware in both price and manageability, there are entry level devices. You can even get direct SCSI devices in some cloud services(Azure has "shared disks"). For Oracle RAC the data is accessed from same location, it's not distributed/replicated across nodes. It's literally the same disks attached to all nodes. Also ASM works with raw block devices which bypasses the need for file system abstraction and all the latency that comes with it. You could also deploy a cluster on a cluster/network file system, but this would generally not be a good idea since you get a lot of overhead.
Postgre clusters can be configured in similar fashion.
I'm not saying that Mongo doesn't have it's strengths. However using the full potential of your environment requires much more planing and has a lot more pitfalls.
I was particularly discussing the implications on what the relative immutability of the shard key has on the data distribution and that it is not that easy to change.
Taotau my aesthetic is similar to yours, but it's true that we are a minority. Devs are, as a group, perceived as technology maximalists that love new toys, and the truth of the perception is reflected in the software landscape. Libraries like Angular, RxJs, and Webpack are all packed to the gills with features! It's also reflected by all the "slightly better" options we get in our tooling (yarn v npm) and (scss v css) and (ts v js) and even (ts v es)lint. But without exception, all of those incremental improvements still require that you have total mastery of the browser's native runtime, html5 + css3 + ES6 + dom + async, and all the protocols it enables, HTTP, TCP/IP, DNS, and all the infrastructure that's grown around it all (CDNs and load balancers and hypervisors).
Devops is in a similar state! There is growing consensus that "Container orchestration" is something like the right problem to solve, and people seem to like Kubernetes, but tools like Puppet, Ansible, Salt are still in heavy usage, and are still very useful, but they solve a different problem. Even within k8s there is debate about the proper container runtime (Docker has fallen out of favor for containerd). But all of this assumes total mastery of linux, ssh, bash, systemd, vim, sudo, mount, ps, and all the distribution variations.
Java is in a similar state! Widely considered "boring technology", Java (lang) 8 introduced streams and lamdas, which is a very different way to code (and hence, to think), and emphasizes functional style over object-oriented programming. Then you get to pick which Java you want (Oracle, RedHat, ?), and how you want it installed (installer, brew, unzip, docker), and now your build tool (Maven, gradle, play, ?) Then if you're making a "typical" webapp you have to choose your VCS (git, mercurial, svn, cvs), code hosting provider (github, gitlab), your starting point - Spring, Spring Boot, Dropwizard - which assumes you want REST, when in fact you may want to try GraphQL, which may lead you to nodejs, and it's complexity.
Picking system dependencies is similarly complicated. Components we can choose from - message queues (rabbitmq, kafka, activemq, ?), caches, proxies (nginx, httpd), and here we have to balance many considerations, such as "is there a widely trusted image I can configure and use as is?", and your options, and the details used to deploy them, will depend on every other decision you've made. In fact, all of these choices are made in away that affects some or all of the others, in a way that is complex and difficult to articulate. This is certainly why certain combinations get acronyms (LAMP, Jamstack, etc[0]), and why its very hard to have an intuitive picture.
> Devs are, as a group, perceived as technology maximalists that love new toys,
Make that web devs, if at all. In many other places where software is written, it's closer to the opposite: Managers tend to be minimalists, and the more "adventurous" developers lobby for adopting newer libraries, or use a new language for some side-project.
The premise isn't that what I'm using will make it easy for somebody with zero knowledge to become good at web development in 24 hours or a week or a month, or any such pitch. It's certainly relative.
The relative simplicity is in that the stack is quite set and restricted, with no unnecessary pieces. I don't add to it just because the industry finds a new flavor of the week or something loses/gains popularity. Each part of the stack has a job to do and I don't add to it constantly or constantly turn over what's in it. That stack could remain entirely unchanged for five or more years easily. Where it can be avoided I don't use unnecessary incrementals that add dependencies or complexity (which will often resurface in the loss of reliability/predictability). I often don't use the latest versions of anything unless there's a very good reason to switch sooner than later. I might stick with Ubuntu 16.04 or 18.04 for the next decade if it were a safe thing to do from a security perspective. In that approach, I can place as much of my energy and focus on what I'm building as possible (since everything I build is mine, that's where my priority and interest is).
Web development was always a means to an end for me. It enables me to build things that I want to see exist. I don't love web development unto itself (I'm rather neutral on it), I love what it enables me to do. I grew up in the middle of nowhere Appalachia. An atheist, social liberal in a typical conservative region that was intellectually unfulfilling, uninspiring, non-ambitious, slow (it was also peaceful, green, and with very little crime). The Internet (and Web) showed up there around 1993-1994 and it was like something from another planet, my teenaged brain could see immediately what could be done with the open canvas and from then forward all I wanted to do was build on it. You're telling me there's this always expanding virtual space, seemingly infinite, and I can just build, and build, and build anything that I can think of? And it connects me up to millions (later billions) of other people? And it's not even very expensive to mess with? Holy shit, let's go.
So what I primarily care about is the thing being constructed, and I want my stack to be very reliable, fast and without many frills or unnecessary complexities. I don't want it to get in the way. I don't want to have to fight with it every time I begin a new project, I want to immediately get to building, with the stack being the 'ol reliable companion that just does its job.
If there's something far better nearby (that is reliable + low on complexity) with minimal learning curve, I'll consider it; I switched to PHP 7 very rapidly for example because the speed increase was such a considerable gain and it required very little time/effort to switch. I started utilizing Go because it was easy to learn, simple and fast (I worked with Java in the 1990s, and never wanted to go through that again); Redis is much the same story, I use it for all sorts of things (from caching to various throttling tasks) and it was pretty ridiculously easy to start using vs the enormous value I derive from it. I'd be happy to keep using my current version of Redis for the rest of this decade. I've been using Photoshop 7 since 2002 because it just works and handles ~95% of everything I need in that space (and they can't do anything to force me to upgrade).
It's also worth noting that I handle every aspect of building and operating a service in the beginning. So this adds emphasis on not shaking the stack unnecessarily, the time costs can become large fast.
I started building my own auth about 20 years ago and I've been learning and rolling (improving it) as I go. I've been using a structure that I've been iterating for about the past 6-8 years or so. Hardly a week has gone by that I haven't worked on something related to auth.
I've experimented with just about every approach. Lately I've dumped all forms of social auth (the past couple of years). I won't allow FB or Twitter login, none of them deserve to be trusted with that.
I'm a big fan of try (the service) before you have to sign up, but I always find that among the most challenging aspects to get right.
I know everyone has a different opinion on auth, but I find it routine to do after all this time. The part I find most annoying is probably throttling / controlling abuse attempts vs legitimate users (balancing it well), it's tedious.
I made a custom e-commerce from scratch with PHP and doing the auth system wasn’t hard at all and it is pretty secure. I feel people make auth seem scarier than it really is.
I seriously doubt you're going to do a better job at security than the AaaS systems out there. I couldn't, and no-one I know could. It's a ludicrously complex and subtle field.
How did you evaluate the auth implementations? In my experience it's about as hard to poke holes into something as it is to fix it. Besides, a custom auth implementation doesn't need to be best-in-class, it needs to just be good enough.
> the auth system wasn’t hard at all and it is pretty secure
If there ever was a red flag in what you're saying, this is it.
Auth isn't "scary". But it is hard. You need to know what you're doing in order to implement it from scratch. If you think it wasn't hard, odds are you did it wrong.
Definitely agree with this type of approach - and my experience as a freelancer (thankfully in charge of my tech stacks) is that clients are happy to pay for fast, reliable software built like this.
Web development, even single page apps, and progressive web apps, can be simple if you skip the web frameworks which solve non-problems and complicate things. The most difficult problem in web development is to make the user interface (UX) work on everything from smart-watches to 40 inch 4k monitors. CSS solves this problem, but it's not an easy problem by itself. The second most difficult thing in web development is automated testing across the stack, testing both back-end and front-end, with different user devices. It's complicated and time consuming to write the code that test every function automatically. Third most difficult thing in web development is optimizations, the browser dev tools doesn't say much about what is going on internally in the JavaScript engine.
I was able to create an original OS like GUI, including file system interaction, using vanilla JS (TypeScript) in about two weeks. I am still using it. The actual GUI is just a couple files each comprising about a dozen functions, nothing really complicated.
The nice part is that you can make web dev as simple or complex as you want. You can write your entire application in a single index.html file with no compilation or build step. You can also use various preprocessors, scaffolds, libraries and frameworks to achieve the same result. The choice is yours.
One thing I hate about the modern web is pages that load with lots of missing content / empty components and then download and render that content afterward.
Is this a React thing?
Waiting for the extra request(s) adds lag time, makes back/forward navigation clunky, interrupts what I was doing if I already began interacting with the page (eg. infamous relayout / unwanted scroll) and sometimes breaks snapshotting tools like archive.is.
I don't mind pages with javascripted controls, but their initial content should be included in the payload with the initial page load. Don't the frameworks have tools to help you do that?
It's not specifically a React thing, but JavaScript enables it. Lazy-loading content is a good idea if you're building dynamic web _applications_, as common components (buttons, modals, etc.) don't need to be reloaded over and over. However, with mostly static content like a blog, it's generally not a great idea.
You can probably thank Google for that as to get a higher page ranking, a site must do the initial load fast. And showing only empty placeholders is fast.
I absolutely agree with OP. I find it annoying that things load like that - even on a gigabit line with a beefy modern CPU. The solution is not to slow everything down to wait for the last thing to be loaded.
That UI/UX is getting slower as everything is getting faster is a sad reality of the times. But I guess that's the price of faster iterations, easier developer flows and a building on top of the lates greatest framework.
> their initial content should be included in the payload with the initial page load
The problem with that is that it pretty much requires you be running node on the back end too. If your back end is built with say PHP or Ruby, you’d need to call out to a node process, which is potentially a lot of additional complexity, time, and expertise.
Even if you are talking about SSR such as how Next.js does it, you wouldn't be spanning processes from your ruby/php application. You would deploy it as a separate application responsible of the frontend, using your ruby/php application as a backend service providing an API.
An alternative is to just serve the HTML from your ruby/php and then take over in the frontend, but this is more complex and not worth it in my opinion.
> An alternative is to just serve the HTML from your ruby/php and then take over in the frontend
This is still incredibly common for apps that are mostly server rendered but use React/Vue etc "sprinkled" through the codebase for more complex bits of UI.
If your component is generated by something like React you'd need to be running React on the back end to pre-render the component and have the front end re-hydrate it.
Otherwise you'd be trying to implement everything once in JS and once in PHP/Ruby
>In my opinion, React made a revolution with hooks and contexts
I agree with your overall point 100%, but to be honest nothing in React was / is innovative except for the virtual DOM diffing, but even that is becoming increasingly irrelevant as apps are moving towards more and more reactive architecture. React made a huge impact on web dev and deservingly so, but all of the other ideas have been implemented and used on the web before.
Of course it's great that React is bringing some of these good ideas to mainstream, but they've been there way before they have been distributed along with a VDOM algo.
> nothing in React was / is innovative except for the virtual DOM diffing
Maybe there wasn't much academically innovative in React, but it certainly brought declarative, functional UI programming to the masses. Its innovation was in making that as easy and accessible as possible with a tiny API.
I feel saying React wasn't innovative is so dismissive and ignores the massive paradigm shift that's happened in web development because of it.
But I'm not even talking about academic really. There were plenty of people who didn't buy into the "MVC/jQuery/templates" thing, and we were writing apps into production for actual customers. I've never been taught academically, but I realized that writing my DOM operations as declaratively as possible made my code much easier to maintain. So I started creating and updating my DOM in JS way before React, when it was considered "heresy" by people who didn't know better. And there were plenty of programmers like me, who never got academically trained or looking up category theory. They had just shot themselves in the foot with the silly MVC stuff too many times to care anymore about what other programmers think.
For me, and people like me React was a GODSEND. We started immediately hyping it, but there was huge resistance early on to adopt it. React was a great improvement from the status quo. But then later on we realized that people started using it as a framework just like they had with "templates+jquery+backbone+whatever" and although the DOM things are a bit easier now, many people don't understand any better why or how React is good and when it's bad to use...
On that point, I think the next innovation to come to front end development is to declaratively think about states using finite state machines & statecharts.
A concept that also has existed before, but with XState, I think a lot of developers will latch onto this paradigm.
The ability to think or plan a feature/apps states in the beginning rather than imperitavely or as an afterthought during development is really valuable. And perhaps if we're dealing with something more visual at the beginning, its easier to demonstrate what will happen if I click "X". and then it becomes easier to spec out & to involve PMs/designers and QA.
I suppose. It just feels weird that the post was highlighting hooks and context, while VDOM was omitted. VDOM was easily the biggest thing in my opinion. I had never seen anything like it and it worked wonderfully. It's not to say that everything else in React is bad, it's more like everything else pales in comparison to how huge VDOM was when it was introduced.
Kinda like hyping iPhones innovation without ever mentioning touch screens.
I read it more as talking about a revolution within React. Hooks and context are (relatively) new features that do "revolutionize" how you write components. That's not to say VDOM isn't important, it just isn't anything new, it's been a part of React since the beginning.
I'm so confused by what you're saying all over this thread, apart from "React is something that exists, and I modified the DOM before it existed". Okay?
> many people don't understand any better why or how React is good and when it's bad to use...
Your comment was very insightful, but I feel like you've left me on a cliffhanger. I'm someone who got into the industry right when React was reaching enterprise levels, so I missed out on what came before it. I got my job, was told to learn React, and have gone from there.
Is there any way you might be able to expand on the problems you were solving with your declarative approach, why it was useful, and how you think React should be used in modern day web development?
- application is in one state and the UI is in another state
- jQuery operations mutating the DOM causing weird edge cases after several user interactions
- the template language (handlebars, mustache etc.) was getting in the way because it lacked the expressivity of javascript
- application state was split all over the place between Models, Views and Controllers. instead, if you put as much state as possible in a single place in your application, it's much easier to just create declarative functions that take in an immutable state and output a DOM node object: `(state object) => DOMNode`
Right now I'd use React only for projects that require it as legacy or as a part of a framework. If you want to get things done quick, Next.js is pretty good framework for greenfield projects that uses React under the hood and I don't mind it being there too much. But similar things to React can be achieved with Svelte or Lit without having to ship and manage a VDOM implementation or JSX with its quirks (e.g. className).
So in summary, I'd stay away from all features of React other than VDOM, and even skip that if possible. And as a general rule, don't use any frameworks unless you can say why your project specifically really needs it. Surprisingly much can be done with basic HTML, JS and CSS. People who say "just use X" are trying to force simple answers to a field that is inherently complex and needs good judgment on which tools to use and when not to use them.
I have experienced working on a messy application codebase (jQuery + Knockout.js) which was 7-8 years old and seemingly was hastily made by on contract of another company. Had to refactor it to ES6 (dynamic imports) -needless to say it was a big pain with unpredictable barely any performance improvement as compared to refactoring on another codebase.
jQuery is a good tool for simple one page applications but not designed for complex web apps. It is harder to code cleanly in it as compared to React.
I'll bite. What part of React has really been innovative?
Because it seems to me that around the time React really gained popularity there were lots of options that did largely the same thing. Knockout, Ember etc.
Personally I only see it as the real proof that VDom could work for large applications.
Well, isn't there something a little "revolutionary" about mainstream adoption of cutting-edge techniques?
After all, like you suggest, things like functional programming and monads have existed for quite some time. The thing that makes React special is how rabidly people adopted it, and continue to adopt their major updates.
>Well, isn't there something a little "revolutionary" about mainstream adoption of cutting-edge techniques?
Taking the example of hooks, React has hooks because it was released with a bunch other stuff in addition to the VDOM, people started using those things as a (poor) framework, shot themselves in the foot repeatedly and finally hooks had to be introduced as a fix on top of that.
Calling that band-aid "revolutionary" or cutting edge technology, kind of sounds wrong. They never would have been there and wouldn't have been needed if it weren't for the bloated original release.
But of course, even if that band-aid makes people think differently about building apps, it's all good. That's why I mentioned in the post that it's a great thing. But calling it "revolutionary" when a large fraction of programmers have been doing it that way for ages is a bit of a stretch.
> but all of the other ideas have been implemented and used on the web before.
Is this true? I've worked in web dev for like 6 yrs now and React has provided a significant number of concepts and technologies I'd never seen before and still dont see elsewhere.
For example, JSX. Yes, it originated in php but React was its first time being implemented in the frontend.
Also the concept of hooks and functional components. The fact that you explicitly define side-effects in the render of a function, with memoization or execution dependent on arbitrary state, is a new invention as far as I'm concerned.
Honestly, the separation of concerns movement where content writers do HTML, designers do CSS and programmers do Javascript, all with with minimal overlap, set web development back a good 10 years. React was a wake up call that the three are intertwined so closely that you cannot think about them in isolation.
One of the early criticisms of React was: “You can’t do HTML in Javascript. You shouldn’t be styling in JS! That violates the separation of concerns.” React skyrocketed productivity and allowed scaling without spaghetti. That’s why it won.
CSSZenGarden was fun, but how many companies seriously did redesigns by just swapping a style sheet? Only repeat the dogma if it makes sense....
HTML in JavaScript still feels wrong to me and I still hate JSX. The Vue and Svelte approach to simply having the HTML in the same file was much more digestible.
I think React won because it had a more gradual learning curve than Angular and a didn’t drastically change between versions.
And the idea that HTML/CSS/JS are non-isolated is over-thinking it. It only applies to the world of Webapps. HTML can be published and served all day without CSS or JavaScript. And you can do a lot with HTML and CSS alone.
Why hate JSX? There are lots of benefits to it, like debuggability and variable scoping rules are exactly those of javascript. Templating languages, on the otherhand, are not debuggable and have awkward scoping rules. And, they always feel broken in one way or another.
JSX is not magical which is what I appreciate the most about it.
Don’t forget proper and full typescript support. Going back to vue (2) after doing tsx was like going back to jquery; loads more context switching and mistakes.
The ability to type `children` alone makes a world of difference.
Yes, yes and yes. All of these concepts are variations of what has been done before in a number of ways. Mostly by "FP academics" who "live in fantasy land", until everyone else starts using them too.
Transpiling, hooks and components have all been done (and done better) before React came along, but often they were laughed out as esoteric toys that have nothing to with "real programming". It's just hard to teach these concepts until you actually use them, and it's hard to get people to use these concepts unless they are included in something else that you need.
The same happened early with React, both JSX and VDOM were laughed at by many developers because "they looked stupid" to people who didn't understand them and were used to one way of doing things. MVC+jQuery+templates was the flavour of the day.
Same thing with TypeScript, FRP and so on.
Most likely, whatever concept is gaining momentum today, it's an exact or approximate copy, or in rare cases a novel remix of what has been researched 10-20 years ago, and used in production for 5 years before you heard about it on HN
These people who like to apply category theory etc. in programming have heard this mocking of their work as stupid esoteric fantasy (and then seeing them become mainstream later) so often that they literally called one of their specs "Fantasy Land" https://github.com/fantasyland/fantasy-land
There's still lot of work to be done. JavaScript doesn't even have proper immutable data structures natively, which would be a REAL low hanging fruit.
Svelte does reactive UI without a VDOM at all. Every DOM operation flows from declarative instructions based on the state of the application, without a need for VDOM or hooks.
The compiler is quite mature and used by countless apps in production right now.
I've been using it myself and it doesn't feel academic at all. The Svelte Kit toolkit, a successor to the Sapper frameworks is also ready to use but it's not 1.0 yet so might be a bit unstable. But if you're worried about having to figure things out then you can use Sapper+Svelte or just Svelte just fine, and they're very robust and well documented.
As I said, the VDOM was novel. However, unidirectional data flow, lenses and FRP with RxJs all predate React. There was also Elm which was a full framework that was based on these concepts, and ClojureScript with its whole ecosystem that did things a bit differently. Though most people who do utilise functional programming concepts prefer not to use a framework but pick-and-choose libraries that do the job for that specific project. That means that the field was (and is) very scattered, and there's no single "React but better and made earlier". Because React is a unique combination of tools. But each of those tools have been done in one form or another many times, except for the VDOM, which I believe was novel.
On another note, a React component in FP is just any regular old JS function with a signature: `(state) => HTML string`. React is such a simple concept that it wouldn't have needed any sort of library, if it weren't for the performance and DOM reset issues.
Your original comment was literally this, emphasis mine:
--- start quote ---
All of these concepts are variations of what has been done before in a number of ways. Mostly by "FP academics" who "live in fantasy land", until everyone else starts using them too.
Transpiling, hooks and components have all been done (and done better) before React came along
--- end quote ---
When asked about the emphasized part, you mentioned Svelte for some reason. When called out on that, you went and listed a bunch of things, ... none of which are really better, and are quite esoteric. To the point that it took the authors of some implementations months to understand the concepts.
React (pre-hooks) could be picked up in less than a day, and just worked. Re-creating React concepts from scratch was a three-page tutorial.
If you judge technologies based on a single anecdote you've heard on the internet then I don't think this conversation serves any purpose. I don't know what bone you have to pick with any technology other than React, but achieving declarative DOM manipulation pre-React was as simple as `(state) => $('<div>').innerText(state.message)` with the plain old jQuery. That was definitely easier than learning React, and by building a component structure with vanilla javascript functions, you could have all the functionality and expressiveness of JSX without a compile step or external libraries.
Of course this would cause problems that I've described in this thread before (scroll/form state resets, performance problems etc.), so the VDOM was the missing piece of the puzzle. Overall the concept of declarative UI was incredibly simple and predated React, but the VDOM was a great thing that solved the problems people were having with declarative DOM manipulation. If React had shipped just with the VDOM implementation, it wouldn't have needed to expand into a full-fledged framework and introduce a bunch of band-aids on top it. React deservedly skyrocketed, and the VDOM was an incredible thing to introduce at the time, but every part of React is quickly becoming outdated as more FP concepts from the past are introduced into the mainstream.
So all in all, React shaked things up in a good way, and finally people are ready to move on to make their apps actually reactive and taking a serious look on things that have been "academic" before.
> If you judge technologies based on a single anecdote you've heard on the internet
I don't
> I don't know what bone you have to pick with any technology other than React
I don't have a bone to pick.
> but achieving declarative DOM manipulation pre-React was as simple as
Yes, it was possibly achievable. Did anyone achieve it? You claimed that evertyhing React has was done better before React. When asked about examples, you answered first with Svelte (which appeared after React), and then with disparate technologies which are are at best esoteric and at worst extremely complex.
> That was definitely easier than learning React, and by building a component structure with vanilla javascript functions, you could have all the functionality and expressiveness of JSX without a compile step or external libraries.
You probably could, but did you? Oh, wait, you didn't. The hot tech du jour when React was released were knockout.js and backbone.js.
And, once again, the etirety of "learning React" took less than a day. And "building a component structure using vanilla javascript functions" was literally a three-page tutorial if you wanted it.
Compare this to Rx that you gave as an example of something "better than React". The author of the original Rx.Net sat by the author of RxJava, and it still took the author of RxJava several months to understand the concept. Lens, another of your examples, is esoteric even in Haskell.
But sure, "everything was done better before React came along" :-\
> React shaked things up in a good way
Indeed, it did.
Funnily enough, you start with "Transpiling, hooks and components have all been done (and done better) before React came along" and then continue with "there's no single 'React but better and made earlier'."
>You probably could, but did you? Oh, wait, you didn't. The hot tech du jour when React was released were knockout.js and backbone.js.
I did. It's kind of funny to hear that you cannot even entertain the idea that people actually did declarative UIs before React with plain old vanilla JS, because that was my bread and butter back in the day. That's precisely how I did frontend until React came along, and so did many others. We sometimes sprinkled in some CoffeeScript to get nicer function syntax, before () => {} and babel existed, but it wasn't necessary if we wanted to avoid a compile step.
Just because some frameworks were prevalent at the time didn't mean that everyone used them. Large portion of seasoned developers rejected all frameworks and still do today. They had shot themselves in the foot with MVC/"trying to do everything" -frameworks enough times to learn that not all answers come from a single framework that encompasses your whole application. This is nothing new or esoteric, and still today a good lesson to learn for new developers. Instead many people continue to use "the standard" framework, fighting against it when it fails to fit the domain logic of their app, and waiting for a new framework to arrive to save the day. Frameworks have gotten much more flexible about this today, but React wasn't anything revolutionary on the framework side of things.
It's not as simple as "React bad/React good". A framework/library can be good in certain aspects and bad in others. I loved React when it came out, because of the VDOM. Wasn't a fan of everything else though, and especially not a fan of how it was used as "the new standard framework to tightly couple your application into". This is not a contradiction, it's just non black-and-white thinking.
> I did. It's kind of funny to hear that you cannot even entertain the idea that people actually did declarative UIs before React with plain old vanilla JS
By you I meant "collective you". I don't care what individual developers did that no one knows about.
> Just because some frameworks were prevalent at the time didn't mean that everyone used them.
define: prevalent
1 : generally or widely accepted, practiced, or favored : widespread
2 : being in ascendancy : dominant
> Large portion .. upto ... flexible about this today
Bears little to no relevance on the discussion
> React wasn't anything revolutionary on the framework side of things.
Except, it was. It upended the prevalent way of doing things and ushered in a new prevalent way of doing things.
define: reovultionary
1 c : constituting or bringing about a major or fundamental change
I did bring about a fundamental change: the prevalent way of doing things on the web changed.
> It's not as simple as "React bad/React good".
Of course it's not. But we're not discussing whether it's bad or good.
> it's just non black-and-white thinking.
So far your "non black and white thinking" is "everything React has was done better befroe React, but I can't show anything to prove this except some disparate things that are both complex and esoteric, and I can also go on a prolonged discourse about how some developers don't use frameworks and may have done things a la React before React".
I already told you what I did and several developers did before React to combat the same problems the React addressed, but somehow you seem to dismiss all of it. If you don't want to believe it, that's fine. I know what kind of code I wrote before React, your ramblings won't change it. Have a good day.
for context, I wrote the first web frp+vdom and helped inspire the creation of rxLinq and related systems, and we even did a whacky thing back then that predicted Parse/Firebase/redux/graphql/falcor, including some basic features they still don't have (should have spun out a startup instead of getting a PhD!). our group even did the first lenses for the web, though that one ended up much less usable. I think we did all that around 2003, while the alternatives were PrototypeJS, jQuery, and a couple other more sugar-level things
however.... react with hooks, jsx, and the various css modes nowadays is pretty awesome, and eliminates most of the needs for streams. main lack there is more for rich animation, than web apps. graphql, redux, and friends are all still clearly clunky technologies with limited shelf lives, so I'd focus more there than react for basic abstractions
at the same time, nowadays I think more about synthesis, ml, end-to-end GPU computing (actually proposed that back then too!) and other more powerful ideas than revisiting frp/lenses/etc...
How is the vdom novel? Any retention mode GUI does that, hell the DOM itself does that. It’s only novel in that they reimplemented it in “user-land”, because of the performance shortcoming of the DOM.
It was novel because you couldn't refresh the whole DOM based on your application state without user experience suffering, before VDOM diffing came along.
And they still had to execute the DOM operations anyway so I feel scepticism of React was warranted.
When the complex reality of JS applications was reached in React, React shortcoming became more and more apparent.
There's no free lunch.
The easier to mentally digest appeal of 'redraw the whole thing every-time'* was fantastic but performance was always going to take a massive hit past an easily reached point.
* The difference this time was the diff engine was going to be smarter than before but it was not good enough.
I think the Opa language was doing JSX-like code in the frontend before JSX http://opalang.org/
Both Opa and JSX were created in 2011. Opa had other innovations as well, such having the same code base run on both client and server (like Next.js). Unfortunately it didn't get traction and was abandoned by the creators.
State and DOM being mutated all over the code base was the norm before React. In many apps, state was a thing that was spread out all over the code and could be mutated by any part of the code. And a DOM was another global state on top of that, that had to be kept in sync with the data of the application. Otherwise users would be shown a state that wasn't representative of the actual state of the application. People did this with careful DOM modification code, trying to always remember to set, reset add and delete DOM nodes correctly. Of course, this caused many bugs and sometimes huge performance issues.
If you tried to solve this problem by redrawing the DOM every time your app state changed somewhere in the code, the browser would freeze and all your form elements would be defocused on every update, scroll states would be reset etc. etc.
React solved this by the diff algorithm and doing surgical updates of the dom based on the components state. It does this by manually reading the state, keeping a virtual DOM in its memory and doing diff calculations.
But if your whole app is reactive by design, there's no need to read the app state, doing diffing or figuring out which DOM node to update which one not to update. The DOM update operations flow naturally by the declarations given by the programmer. Frameworks such as Svelte are moving into this direction and they're already seeing quite significant performance improvements compared to VDOM implementations.
The best part about React is declarative rendering, you tell React what the DOM should look like, it makes it so. React does this using a virtual representation of the DOM, but this is an implementation detail.
If you can do declarative rendering without keeping a virtual representation of the DOM and diffing it against the real DOM then "the virtual DOM is overhead" (https://svelte.dev/blog/virtual-dom-is-pure-overhead).
My only issue with CSS is the absence of container queries [1]. Now I need to rely on size listeners of the container element to make my components truly responsive. Media Queries do not work for components. CSS Grid & Flexbox are nice but not enough to achieve radical layout changes for certain breakpoints.
I do embedded also, and FPGAs. Do you have any suggestions for how to start learning web stuff? Every time I try, I get overwhelmed by all the frameworks, libraries, package managers, build pipelines, etc. There doesn't seem to be a set of best practices for what to do, or even what is needed and what isn't. What is the best way to get started?
This is a good resource that will walk you through the cutting edge web development technologies, starting from the very basics and progressing to the more complex matters in the end. Highly recommended.
Do you start learning FPGA programming by studying frameworks? I doubt. Like all other things you start learning the basics and then once you know them you can abstract complexities with frameworks. There is nothing overwhelming about web development. It is trivial.
Creating a CRUD website is supposed to be pretty fundamental, right? And how do I have individual user sessions with logins that show different content to different users? That seems, if not basic, fundamental to at least know how to do.
Should I hand-type static HTML to do this? Is that what modern web developers typically do? Will learning HTML, CSS, and JS teach me how to use a backend? Which backend language should I pick? Should I use a database? Which one? Or should I use AWS? Is all I need HTML, CSS, and JS?
PHP, is that a good backend starting point? That seems to be pretty fundamental, since over half of all websites use it. A LAMP stack, right? No? What about Python? Ruby? C? Rust? Arc? Elm?
Should I use Node? If so, what is the typical Node setup?
Should I use webassembly? That's a fundamental and new browser technology.
How do I compress and minify code and images to be served? A makefile, right? That's the typical way to build things in my software world.
If someone says they get overwhelmed by something, chances are decent there is something overwhelming about it.
Web is a large domain of knowledge. It isn't particularly hard in terms of math, algorithms or mysterious unknown proprietary APIs. But there is a lot to figure out. What parts are important, what parts can I skip.
If by basics you mean HTML, CSS and JS. Sure. Good start.
But you could also start with a framework and learn from the middle and out or the top down.
> If someone says they get overwhelmed by something, chances are decent there is something overwhelming about it.
The numbers speak for themselves. I don't need to convince you. There are more web developers than in any other programming field. So it must have some property that makes it easy to get started or at least some kind of incentive to make people go through the initial hurdle.
Anything worth studying is slightly overwhelming at first, but to say that everything continues to be overwhelming once you know the basics is wrong. Knowing a little bit of the grammar and some words will help you understand better Mandarine. Not knowing anything about the language will make it appear as some alien technology.
No skill starts growing at the middle. Nobody teaches mathematics by starting with abstract concepts. We don't learn new spoken languages by studying literature from the get-go. So getting the pedagogics right is part of the success.
HTML then CSS then JavaScript. I've taught all three and people struggle more in a different order. HTML is the skeletal architecture, CSS is just styling, then JavaScript is behavior. Those three things in that order are like orders of "need". You need HTML first to have a webpage structure, then styling to make it easy to understand its elements, then the behavior is more complex than both. I don't know why I see people put JS learning before CSS... JS is much more complex than CSS, and a much different change in paradigm from HTML than CSS is.
May you kindly point me where to start learning robotics, and recommendation for a starter robot arm? Maybe ~$300 if something worthwhile exists at that price range. Take care.
For $35 you get a little motor, a motor control board, and an ARM micro-controller board. ST includes some software for motor control. If you want to do precision motor control, out of the box it is missing an encoder (a device that tells you the position of the motor). The STM32 chips usually have some inputs you can use with a quadrature encoder, so you could add one if you needed to. It does include a current sensor and the software uses the for field-oriented control (FOC), so you can efficiently and smoothly control the speed of the motor. To learn more about motor commutation and FOC, check out this document:
Lego Mindstorms could be worth considering as a general-purpose hobby robotics platform: EV3 (the older version) can be flashed with a custom Linux distro, and Robot Inventor (the newer one) can run Python scripts. In either case all you need to add more structural parts is to pick up a bulk case of used Technic parts, so it's eminently reusable for multiple unrelated projects.
Oh jeeze, I feel old if the EV3 is being described as "the older one". I have horrible memories of writing some "Not Quite C" for RCX because the compiler didn't support modern amenities like stack frames.
Being able to just run Linux on the thing sounds like a god send.
A group I worked with in a high school lego robotics competition managed, if I recall correctly, to achieve 'recursion' by defining 2 very similar functions and having them just call each other. It was a frustrating device at times but also a really fun experience!
Cool! That makes sense -- it still felt incredibly clever and tricksy to us when we were about 16 and trying to map our 'beautiful algorithm' into NQC sometime past midnight, for a morning competition.
On React, people talk about it especially for it being a UI tool.
But the most significant feat React achieved IMO is how easy to write asynchronous hiearchical actors (from actor model) with it (kind of like erlang vm).
Context enables dependency injection and ownership management. Effect and state enables object ownership and lifetime management. Js timers, (i.e. setTimeout, setInterval, queueMicrotask, promise/async), help making an object living asynchronously as if it has its own private thread.
Yes, those are similar concept of lifetime and ownership Rust have, but instead of functions/blocks the object (value in memory) is owned by/shared with components. And of course these are not enforceable by compilers/transpilers/linters due to them not being a javascript-primitive, but at least React helps organizing those things in a lot more explicit and clear manner.
Web hooks are nothing new in other languages, they're just built-in functions that do things that were previously cumbersome to code yourself. That's only revolutionary to React. PHP is a great example of built-in functions, yet I've heard React fanboys complain that PHP has too many built-in functions (which is a really odd thing to complain about).
JavaScript is a great browser scripting language because it's the only browser scripting language. That's a whole realm of good times, and people can and should go nuts with it there.
The problem started a decade or so ago with Node. Too many people only learn JavaScript, become psychologically dependent on it, and they all collectively took it too far outside of a browser.
ECMAScript is a general purpose standard, but it was invented retroactively. Node is not ECMAScript in a server-side ECMAScript engine, it's JavaScript in a browser JavaScript engine. That's just too much of a force fit, and has wasted too much potential for me to say anything positive about it.
Couldn't disagree more. I was a Java programmer for my entire career until about 2015 or so when I switched to Node, and shortly thereafter to TypeScript.
I've commented this many times before, but having a system where everything is on the same tech stack (i.e. front end in TypeScript with React, back end with TypeScript on Node) has resulted in gargantuan productivity gains, especially for a small team where it's trivial for people to cross front end to back end seamlessly. For contrast, I know many teams with a backend in Python and a frontent in React/JS, and I've worked on some teams with that setup. In my opinion it's virtually all downside compared to a backend in TS, as Python and TS are quite similar from a web programming perspective (I'm not referring to Python's advantage in data science tooling), so all it basically is is a barrier to your front end folks being able to make small enhancements on the backend quickly.
Furthermore, TypeScript is a great language and I find myself being so much more productive in it than I was in Java, especially when it comes to refactoring.
JavaScript most definitely has its warts and head scratchers after being around for 25 years, but I feel like most of these oddities (truthy/falsey, typeof null === 'object', undefined vs. null, etc.) can be learned in an hour and written on a half page.
If you’ve mainly worked in TS then it explains the blind spot, because JavaScript is chock full of awful missteps built up over the years. There’s a reason my copy of “JavaScript: The Good Parts” is extremely slim next to its sibling, “JavaScript: The Definitive Guide”.
So you’ve come to it at a time when the syntax and capabilities have a popular subset that actually starts to fulfil the early promise. And yet, despite the article above, one may still be enormously critical of the anemic and inconsistent standard library, and don’t even get me started on the horrifying dependency shitshow of the node ecosystem that cripples maintainability of anything over 18 months old.
Just because we’re all holed up in the throne room, doesn’t mean there aren’t monsters still roaming the sewers, just a few levels down.
As for isomorphic code, I strongly encourage my competitors to write backend code in the same fashion and the same breath as the front-end, because the resulting tight coupling and special-case-driven technical debt makes them easy to outmanoeuvre when markets shift. And if they’re reading this then please also consider microservices, graphql,
and nosql data stores whilst you’re at it, for the same great reasons.
> There’s a reason my copy of “JavaScript: The Good Parts” is extremely slim next to its sibling, “JavaScript: The Definitive Guide”.
The reason is that these two books don't fulfill the same goal. The Good Parts is a rather short walk through the language and reads more like a "get started quickly" guide. The other goes into much more detail. That doesn't mean the latter's size os due to it covering all the bad stuff whereas the former doesn't. It's just a clever title but it's an apples and oranges comparison and I'd suggest not using it as some sort of supporting argument.
Whether JavaScript is good or bad as a whole is a different question (I think it is), I'm simply taking issue with that meme (that originally popped up in picture form, the two books side by side, rather than text).
I have also stopped trying to discourage people from cargo culting facebook’s stack for their 3-person teams or even solo. If someone insists on 10x the complexity and 100x the work, let them.
JavaScript is becoming bearable but still too painful for anyone who has touched ruby for example.
Meanwhile I’m learning closure and loving every second of it.
Haha ruby of all things. The language where they create aliases in standard library to make the code "read like natural language"... With a framework that promotes mixins as a service layer/code sharing abstraction and fat models/controllers.
I get not wanting to start with a super complex stack, but Ruby and Rails are the worst mainstream framework maintainability wise it's obvious why it fell out of favour.
I've heard someone describe Ruby On Rails as: "lots of great magical wands that make great palaces appear out of thin air but always ends up spawning dragons you have to fight"
I will pipe up for client-side TypeScript in conjunction with Ruby-based services. I’ve been contributing PRs for Hotwire and it is the first time in 25 years I didn’t actively resent working in JS of any dialect.
I find the Facebook stack to have a lot of boilerplate, but overall it's very simple rather than complex.
You always know exactly how to implement what you want, without having to think very hard.
You can do something small by yourself by writing less code, but using less code makes it more complex since you have to think a lot harder to understand the code when you come back to it in a few years
Even as a style guide, it's unnecessarily terse in some cases. IIRC, there's a line that says (paraphrasing):
> Don't use continue. I've never seen a loop with a continue that wouldn't be better without it.
And that's it. No examples, no objective criteria, we're just supposed to take the man at his word on this. Whether or not I agree with this particular case, I don't enjoy argument from authority in most forms, especially not in one where you are supposed to learn about a better style of programming.
I didn't do much web dev but is having the same language for the front and back end a real time saver? For a skilled programmer, switching language is not a big deal. I'd say that for a front end developer to touch the back end, learning the required bits of Python or whatever is used is not the biggest problem.
Front and back do different things, have different requirements. You control the architecture on the back end for instance, not on the front. The back end deals with data modeling and processing, the front with layout, very different task, very different skills, and the language is just a small part of it.
There is some overlap, for exemple I remember having to code a clock twice, once on the back end of to show it correctly the first time, and once on the front to have it refreshed in real time, the code could have been shared, but these occurrences where code can just be copy-pasted are not that common.
And BTW, most of my web dev was JS/PHP/SQL, and I actually liked all three languages for what they did. JS, I had no choice, but it did event handling well. PHP was good at generating HTML from a database and SQL, despite its age is still king for querying databases. I wouldn't want to use these languages for anything else.
> For a skilled programmer, switching language is not a big deal.
I disagree, but with nuance. I consider myself a skilled programmer, and I have switched languages many times throughout my career, and you are correct, it is not much of a big deal. There have also been times in my career where I've been responsible for whole swaths of an app from back to front end where the backend was in Java and the front was in HTML/CSS/"old school" JS (this was back in the JSP/server-side days). And yes, in that case it was not hard to switch back and forth.
The problem, though, is that, as you point out very well, the back and front ends have very different requirements, and so in most organizations you have separate teams focused on the front end and back end. If I'm a front end dev, I'm going to be spending day-in day-out working in Javascript and my JS ecosystem. It's not that it's hard for me to, for example, learn and use Python, the issue is that since I'm not "practicing" it every day it definitely gets rusty, and as time moves on the ecosystem moves on such that my environment likely needs some tweaking (venv vs. pipenv vs. virtualenv vs. conda - honestly it's been a while so I have no idea what is in widest use these days).
So if I'm on the front end, and I need say one extra piece of data that I know is stored in the DB exposed in some specific API call, for what is likely a trivial change for a backend dev, well now the time it takes for me to get my backend env in sync (again, which maybe I haven't bothered with in 3 months), refresh my knowledge of Python, work through any dependency update issues etc. I may have can often be longer than the time it takes to make the simple code change. So what usually happens is the front end dev just doesn't bother, they submit a ticket for the backend dev to do it and wait to sync until the next sprint.
Compare this with what happens when front and back end are both in TS - the front end dev usually has a short chat with the backend dev to make sure the changes will be OK, but since everything is immediately familiar can go and make the change just as quickly as the backend dev, without needing to wait for the backend dev to have time to do it.
I have seen this cultural change in depth over the past couple years, and it is just a pretty shocking change if you've ever experienced it if you've been used to teams that were more "siloed" between front and back ends.
Optimizing the common case is much more effective in my experience. Setting up an environment should be scripted anyway. And having to refresh your knowledge of Python implies a while since you needed it.
The piece that's really nice is being able to share your data model definitions. Not having to define your interface once in one language, the again in another language is very nice.
There's tools to make it easier, but using them still means you have to pull in another stack into your workings/you're stuck with whatever limitations the tool has
> For a skilled programmer, switching language is not a big deal.
Not exactly.
It is easy in web space, but switching language is a big deal if the previous and next language have huge differences in concepts and on which layer of the stack lives.
For example, switching from language that has a complete runtime and GC to a language that does not, is a bit hard. In JS we have things like Promise.all, and setTimeout, and such to control concurrent async operations. On language like c/c++/rust where you produce abstract machine, you have to choose how to operate and regulate those async operations.
The real advantages in my opinion will be found in deno where instead of managing separate node and web implementation of everything, you can use one implementation for both b
In a backend where you need a heavy-duty, multithreaded process to handle long-lived computations, node is probably not the way to go unless you want to pay for all the extra instances you'd need for the same amount of load. In my experience, for example, a java-based graphQL server (that spawned multiple connections to various services) needed much much less in the way of resources than the node equivalent serving the same amount of traffic - AND the latencies were generally much better with the java server, depending on the size of the JSON payloads that it was handling.
All that being said, you can certainly architect your way out of that problem and I imagine a relatively small percentages of web applications even HAVE that problem.
I agree with all of what you said. Note in terms of "architecture your way out of that problem", that's exactly what we did. We have an eventing architecture that uses PubSub to publish to serverless functions that can then do heavier processing asynchronously. And for us, this wasn't a compromise, this architecture has a number of other benefits.
But again, I definitely agree with what you've written, right tool for the job.
I would argue while it has other benefits it probably isn't as simple. Simplicity is usually the long term better choice. As the business scales since you've probably set a precedent this pattern will be copied all over the place. After enough times trying to understand who owns the data transformations, what lives where, how to support it when one part of the puzzle fails and trying to wire it all and how all these stacks couple together becomes a nightmare. Unfortunately I've experienced some of these issues coming into organizations after the original developers have left once it became too "big" of a place to work for - few people truly understand the architecture and even when they do its flaky and recovery is hard. YMMV depending on the complexity of your business and age. In the end IMO it just seems like a big workaround to keep using Node.
Not op but I assume they mean: a main web server is scheduling large jobs in the background by publishing an event to whatever pub/sub system you want to use (there are many!), lambdas can be subscribed to this system so they trigger off these events and publish a corresponding event back when they're done that the web app is subscribed to etc.
For an example, you can look at how node interacts with OpenCV.
The JS scripts together the compute heavy CV alogrithms, and you can do similar by hosting your computer heavy things behind a service call, while keeping the orchestration parts in node
The first post also misses something fundamental about modern software: servers programming is becoming more browser-like.
> Node is not ECMAScript in a server-side ECMAScript engine, it's JavaScript in a browser JavaScript engine. That's just too much of a force fit
And what makes V8 a "browser JS engine"? A focus on:
- rapid startup. Code starts running immediately, JITs quickly. The VM is designed for latency, not just for throughput.
- excellent sandboxing. The VM is designed to run untrusted code.
- no blocking code. Designed for callbacks and promises. No threading, no thread.sleep(), no mutex, etc. Makes is much easier for non-expert developers to write fast & reasonably correct code.
Now look at things like Cloudflare Edge workers, Lambda etc. Modern server environments share all of those same design goals.
Server-side JS/TS not only has the advantage of a single codebase. It also brings the design and engineering advantages of a browser VM to the server.
Your examples doesn’t really read as a prototypical server application.
Rapid startup: lambda is a tiny subset, and not really server application. A server app could take minutes and would still be okay, because they are designed to run for a long time. Even in case of scaling minutes are more than okay since deploying a new instance takes a similar amount of time.
excellent sandboxing: you usually only run your own code connected to db and other very privileged services. If there is a vulnerability it is a very big problem with or without sandbox
no blocking code: i’m not up to date, but node doesn’t have a strong parallelism story at all, compared to the JVM, Go, .NET
There's many reasons why you would want the server, and reasons why you may not want it. Data structures and algorithms that as you scale give you an edge in the specialized problem domain you are in is usually one that I've seen. How many services have I've seen deployed that scale the DB to many cores and CPU's just to avoid some startup time? This is a problem I sadly see in a lot of Node stacks, and its easy to look good when you write a simple component to replace all that complexity and costs decrease as a result.
Most of the "serverless" things delegate to a server in the end anyway - whether they be a database, a managed service, etc. Something has to stay alive, be a server and own the state after all - serverless doesn't make the problem go away just passes the buck. For run of the mill small scale websites or websites that fit a particular paradigm lambda works fine. But it doesn't suit all apps, and its hard to make all problems fit it currently. As businesses scale custom solutions can scale better.
A typical most basic website, awaiting requests and serving static/dynamic content is not a short-living process, I don’t see what is controversial about that.
So you think starting up a whole process, establishing connections to a db and serving the request would have any sort of acceptable latency and/or throughput? At that point, you could write your server in bash as well.. also, I think it would be ridiculously expensive.
Lambda is great for seldom run functions, like running some analysis/conversion on user uploaded profile pictures or the like.
Lambda containers serve multiple requests. You just write the code as if you were handling a single request. And on the contrary, Lambda latency is worst when you have spiky traffic patterns (such as for a seldom run function). Of course, if you can tolerate the cold start latency overhead, Lambda is also a cost effective solution for those seldom run functions.
Also, specifically for Aurora, Lambda supports transparent connection pooling. It is just no longer a concern of your application code.
Disclaimer: I work on serverless services at AWS. I’m definitely biased :)
Thanks for the correction! My point was not at all to “bash” Lambdas, just to point out the (in my opinion) incorrectness of grand(grand?)parent’s comment.
Though I suppose Lambdas don’t use separate traditional OS processes to serve requests, do they?
> Furthermore, TypeScript is a great language and I find myself being so much more productive in it than I was in Java, especially when it comes to refactoring.
I don't really see how. TS doesn't seem to solve any annoying problems I previously had in Java. As a concrete example, it would be nice to have the concept of a DTO as a first-class language feature, but alas, I find myself constantly casting and re-casting, plucking, or writing endless wrappers to make sure properties trickle down (or up). Hell, sometimes I just give up and use `any`. I mean, this is a web-first language that has no concept of sending objects over the wire.. okay then.
TypeScript's generics system is cute, but I think it's mostly academic. And did you look at the toolchain? To get TS working, you need babel or ts-node or webpack, and like 3 different .json config files. Importing a package without TS support? You need to write some stubs yourself in types.d.ts. In fact, the best parts of TypeScript are actually JS (await/async, arrow notation, spread operator, etc.).
This biggest "aha" benefit I get from TypeScript is that it is structurally typed, while Java is nominally typed. In my experience it has proven much easier to refactor in TS because I just need to ensure my objects have all the right properties. With Java if I have a Thing1, but a library is updated to add just a single new property so now there is a Thing2 type, well now then all the places I need a Thing2 I have to completely copy over from Thing1 - I can't just add the property and be on my merry way. This happened to me many times in my Java career - I still think I have PTSD having to do a Jersey 1.x upgrade to a Jersey 2.x version across a large codebase. It was a nightmare I've never had anything come close to with Typescript.
> I mean, this is a web-first language that has no concept of sending objects over the wire.. okay then.
I have no idea what you're talking about here. I use GraphQL with auto typegen of my TS types and I get typed data objects everywhere.
> TypeScript's generics system is cute, but I think it's mostly academic.
TBH this remark just makes me thing you really don't know much about TS. I use generics extensively, find them very helpful and are easy to use.
I'll give you the point on initial TS setup being non-trivial. Hopefully advances in tooling (things like Deno, which I'm not actually a huge fan of, or other projects like Rome) will make this easier, but even then I found this to be a "one and done" cost.
There is a reason for nominal typing though, because nominal types represent an interface contract that generally goes beyond just having the right type signature, but instead it is also about semantics. It's about the parts not covered by the type system, which the compiler therefore can't check. It depends on the kind of objects you are generally working with, but beyond pure data I find nominal typing preferable, because it makes it explicit that an implementation X conforming to interface contract Y is not just a matter of type signatures.
Note that the upgrade pain with Java was not due to typing; rather, it was due to using a library directly instead of creating a class to interface with it. In other words, inadequate abstraction.
> Note that the upgrade pain with Java was not due to typing; rather, it was due to using a library directly instead of creating a class to interface with it. In other words, inadequate abstraction.
I'd look into what Jersey actually is before you say something like this, because what you've said really doesn't make sense.
The shock wave that TS sends through a JS stack is hard to ignore. It's really annoying. Every tool added TS support in a slightly different way and you always have to keep it in mind no matter what you're doing. Sadly it's just the reality we gotta face. I'm hoping Rome can live up to the hype and be helpful here.
Oh man, so true, between TS mangling and whatever framework you're using (Vue/React/etc.), the stack trace ends up being literally worthless. It's kind of funny to think about: when something goes wrong, I don't even look at the trace (which is 100% what you'd do in any sane language), but rather I just go back and look at the "last thing I changed."
You aren't using source maps to transform your stack traces then? I've had very little issue in understanding stack traces in any of the major JS frameworks.
> Rome is designed to replace Babel, ESLint, webpack, Prettier, Jest, and others.
Afaik esbuild only intends to be a replacement for 2 out of 5 of those things. It does that well for sure, but if parent commenter's main issue is the amount of different tools, I don't think esbuild will help.
People are talking the other points to death but on the toolchain front, you might enjoy https://github.com/evanw/esbuild, which is rapidly gaining in popularity. Just 1 thing for bundling, transpilation etc. And its terrifically fast since its written in Go (ironic I know).
It would be amazing if there were other languages available for front-end development in the browser, no? Even if you think that JS is so wonderful, then having competition would still be good, or no? Currently JavaScript has a monopoly in the browser and monopolies are always bad. Bad for innovation and everything else.
It would be better if there were no oddities in a language. One of the reasons why everyone hates PHP is that it is full of inconsistencies, odd design choices, weird naming and unexpected behaviour. JS has at least some of these.
If there was a second of third language available in the browser, then that too could be used to develop back-end applications and would have the benefits you describe - that you can use the same language for both stacks etc. For example - if you could front-end stuff in Python, would it be amazing or bad? Or would the current JS devs just fear for their jobs because of it?
> For contrast, I know many teams with a backend in Python and a frontent in React/JS, and I've worked on some teams with that setup. In my opinion it's virtually all downside compared to a backend in TS
Is there any Typescript backend framework as mature as Django?
> Python and TS are quite similar from a web programming perspective (I'm not referring to Python's advantage in data science tooling), so all it basically is is a barrier to your front end folks being able to make small enhancements on the backend quickly.
So on the on hand, the languages are "quite similar", yet it cannot possibly be expected that frontend people learn more than a single language? Something doesn't add up here.
You are interpreting GP’s comment very uncharitably, to the point that it actually becomes a completely incorrect interpretation.
GP is pointing out that it is advantageous to have a single language on both front end and backend. And somehow you arrived at “developers cannot be expected to learn more than one language.”
There ARE big advantages to having the exact same language (as opposed to similar languages) on both client and server, especially in an SPA where you want to render something initially on the server, but then update it using the same logic later on the client.
> GP is pointing out that it is advantageous to have a single language on both front end and backend. And somehow you arrived at “developers cannot be expected to learn more than one language.”
Because he considers it a "barrier" to have to switch between languages to do backend-only changes. Which is a completely different use case than the one you're describing.
For an SPA where you're essentially doing frontend on both ends, yes, that's obviously easier when you're only doing it once.
But that's not the general case, and I'd argue that transitioning between different mental contexts for components you're not regularly touching is always going to be a hurdle to developers, regardless of the language used. Blaming it on the language is an useless red herring.
Having to write the same logic twice in two languages, and then making sure both implementations behave the same way. I don’t know if I’d use the word “barrier”, it’s certainly a significant pain in the ass.
The classic example is of course validation, but plenty of other places it can come up.
I feel like switching languages adds extra friction too. Switching contexts is still a hurdle, but using the same language can make the hurdle shorter.
Perhaps I'm overthinking things and HTML does this naturally, but is there something for rendering that is what Swagger/OpenAPI is to APIs? Some way of specifying HTML that can be both rendered (and read back for inputs) by multiple implementations.
In theory, that's what template languages like jinja, liquid and twig are for.
But as you can see, there's n+1 standards for it, and in practice none of them has a Javascript implementation good enough for productive use. So it's more a "what if?" scenario, had Angular/React/Vue not taken off.
It's definitely a barrier to have to switch languages. You might be super familiar with Chrome's debugger UI (which is excellent, btw), and feel lost when suddenly getting dropped into IntelliJ's.
Also, what if you just have frontend developers who straight up don't know Java or vice versa? I don't see how having a shared language could ever be a bad thing.
> Is there any Typescript backend framework as mature as Django?
No TS framework is as old as Django, and if you're looking for "Django for TS" you won't find exactly that, but Next.js is the current reigning champion for server-side frameworks right now, according to the popular "State of JavaScript" survey https://2020.stateofjs.com/en-US/technologies/back-end-frame... Next is a "both-side" framework, allowing it to do stuff you just can't do in Django.
If you want something much thinner than Next (and thus much thinner than Django), there's Express.
> yet it cannot possibly be expected that frontend people learn more than a single language?
The problem isn't learning two languages, it's interop between two languages.
Come on, as someone that has worked professionally with Django and Next.js, the only similarity they have is that they're both web frameworks. Django is light years ahead than Next.js is it's not even funny.
Yes, Next.js is one of the better Node/Javascript frameworks, but it's incredibly inferior to any other established framework in Python, Java, PHP, Elixir, etc. — unless you only need a static page with some dynamic React components. I am in the unfortunate position of maintaining a more complex Next.JS app, using most of its "advanced" features such as dynamic routing, SSR, GraphQL, API, and it's the most painful project I have ever had the misfortune to work on, because the upstream interface and API is so woefully under-documented, buggy, changes too quickly it's hard to stay up-to-date, etc. etc. I weep every time someone on this forum suggests to start a new project with Next.js.
In theory Javascript on the server and client is a productivity boost, in practice it is not by any measure.
I am in the unfortunate position of maintaining a more complex Next.JS app, using most of its "advanced" features such as dynamic routing, SSR, GraphQL, API, and it's the most painful project I have ever had the misfortune to work on, because the upstream interface and API is so woefully under-documented, buggy, changes too quickly it's hard to stay up-to-date, etc. etc.
Would you give some specific examples of where you've found Next to be buggy or where it's introduced breaking changes? We're evaluating a number of possible Node-related libraries for a new project right now, including Next, and there's no substitute for hearing from people with real experience of using them in production.
Not the parent commenter, but maybe my experience saves you some time.
Next js is awesome, and it is the best alternative in my opinion if you go the SPA route.
Now, things get really, really, really messy and complicated when you start to implement on top of it everything else a typical web application would need. Authentication, validation, i18n, acceptance testing, background tasks or queues, etc....
We started out with next and prisma 2 and wasted a lot of time, in the end we rewrote the whole thing before launch with ruby on rails and turbo, some minimal stimulus and it was awesome. So much easier and simpler, and the application felt a lot more solid and robust.
So, next is awesome if you're doing a landing or relying on an existing backend api, etc.
If you need a full CRUD app, don't waste your time with it.
Thanks for the information. Would you mind elaborating on what made things "really, really, really messy"?
Our use case is fairly typical, basically an SPA doing the heavy lifting, an API on the back end to support it, and then some largely static marketing pages. There is a potential fourth aspect if we want to customise any of those back end pages depending on who is logged in, for example to personalise help pages with the user's own details or to host some account management pages separate to the SPA.
Next is under consideration because our SPA will be React-based, so being able to share components and styles for the rest of the site could be quite a time saver. We're reasonably sure we want to use some Node-based back end for this project, because that would allow us to share substantial functionality between the SPA and API implementations, but this would still apply if we used Express or another alternative to Next.
It looks like the SPA and static pages wouldn't be a problem with Next in your experience, but maybe there could significant problems we haven't anticipated so far with using Next for the API and/or with using server-side rendered but not entirely static content?
Ok, so here are a few examples of the things we didn't like:
1. We were doing SSR, and given we needed authentication we used next-auth [1], which is a great library btw, but the problem is given the architecture you buy into when you do an SPA, we had to check for authentication in three places: 1) In the frontend you need to check if the user is logged in or not and show information accordingly. In getServerSideProps you also need to check for permissions, because otherwise you'd be leaking private information in the "initial data" that gets embedded in the first's request html as json. And then you also need to check for authentication in the API pages/endpoints... each one of these has their own ways to be done (well documented in next-auth's docs) but still, you need to be careful, and it was very, very easy to make a mistake, forget to check on some place, etc. Of course you have tests for preventing this, but still... a lot more fragile than just using devise, or a "middleware" in a traditional MVC application. This is one of the things I refer as being more "solid" or "robust".
2. Validation. Oh my!!!... Prisma, again, is an awesome library. The best I've seen and I've used many similar in the past (django's ORM, ActiveRecord, etc). Prisma is up to that level in my opinion... but it is just the data access layer, on top of that you need to implement your own validation rules. We used Yup [1] for this, which, once again, it's a great library. But then we realized we needed to validate things such as already taken emails... but of course, you would not check by issuing first a get() or select and if you didn't find it you'll create it, because that could lead to race conditions... so the "proper" way to do it is to attempt an insert, and if the insert fails because of an unique index then handle the exception, generate an error message, and make it back to the frontend. All doable, and not that difficult. But still a lot of work, and it is easy to forget about corner cases, etc: fragile.
3. Then we needed to add internationalization. So we mixed in next-i18next [3], which added another axis of complexity because translations need to be available both at SSR time plus at the client side. Plus we also need to translate the error messages from the handling of the unique index exceptions from above....
4. We needed to implement some CLI tasks, (think of equivalents to runing a worker or a sync process, etc) which needed to import some domain logic... but next has its own babel and webpack so you cannot write them with plain node, so we needed to do a lot of hacks with @babel/register so that we could import this code, and then we found problems with our code relying on things such as getConfig that next sets up on boot, but this was a CLI so we were not booting next... so we needed to init the config ourselves.
5. By this point our index page was about 250k of javascript + translations + css... and we were not done yet. And the feeling of the end result was not that great.
And we all had a feeling that any of these libraries might change at any point [4], or go unmaintained, or out of fashion and we were just a team of 3.
I insist, I don't think the problems are in any of these tools, nor in JavaScript itself, nor in the ecosystem. These libraries are great, we really liked them. You would have the exact same problems if you try to use Flask, or Sinatra, or any other "lightweight" solution.... it can be done, and it can work very well for you... but it is 1) much more work, 2) requires very experienced people that really know what they're doing and 3) you'll end up re-implementing django, rails, or similar... in your own way, with less documentation and less real-world battle tested. These problems are caused, in my opinion, by the "architecture" you get in (SPA + separate backend).
We rewrote the thing in 1/4 the time with Rails + sorcery + Tailwind + delayed_job + a few other smaller gems. Just a bunch of models and some "services" (plain ruby objects), hotwire for the "spa feel" and stimulus for things such as date pickers, modals, etc.
I think also something to consider is the team size and skills. If you have, let's say, 5 backend devs, and 5 frontend devs, then it might make sense to get into the SPA + separate backend... it is more work, but it is easier to split it... if you're a small team, and/or want to stay as a small team, then nothing beats Rails (or symfony, etc... never used those others) for this.
The similarly named (but completely different) Nest.js is much closer to Django than Next. Still a ways behind in terms of maturity, but it seems to be more or less on the right path.
> Yes, Next.js is one of the better Node/Javascript frameworks, but it's incredibly inferior to any other established framework in Python, Java, PHP, Elixir, et
This is like saying a screwdriver is incredibly inferior to a impact hammer.
> In theory Javascript on the server and client is a productivity boost, in practice it is not by any measure.
This is in direct contrast to my personal experience across multiple projects and teams. In practice it IS a productivity boost, because JS does 99% of what anybody needs a web server to do.
> This is like saying a screwdriver is incredibly inferior to a impact hammer.
I'm sorry, isn't the goal of web frameworks, including in this category Django, Next.js, Phoenix, Laravel, Nuxt.js to respond to HTTP requests and present users with an HTML page representing a document or a more complex web application?
> because JS does 99% of what anybody needs a web server to do
Brainfuck is Turing-complete and does 100% of what any other language can do as well. I stand by the fact that having to "know" only one language is great in theory, but in practice it's not. Node and client JS/Webpack are a leaky abstraction it's not very hard to get yourself cut with. In non trivial modules, you'll find it hard to be able to use the same code verbatim on the client and the server. Then add the complexity of server-side rendering, serialisation/hydration, React suspense, code that mysteriously works only when server-side rendered or viceversa, etc. and you'll ask yourself "is this really worth it?"
> code that mysteriously works only when server-side rendered or viceversa, etc.
It sounds like your opinion of server-side javascript comes from experience with badly written and poorly-understood server-side javascript, because none of that jives with my experience in writing node-based web applications.
I think we are into semantics here, but I would posit if your web server is talking directly to a db other than a key-value store for tokens or what have you, your system is architected poorly. Your web server should be talking to a service written in Java or C# or something that handles the db stuff.
edit: to address your point though, yeah, I think 99% of web sites don't need to be talking to a db.
That's different from web applications, of course, but most web sites aren't, and shouldn't be, web applications.
> No TS framework is as old as Django, and if you're looking for "Django for TS" you won't find exactly that, but Next.js is the current reigning champion for server-side frameworks right now, according to the popular "State of JavaScript" survey https://2020.stateofjs.com/en-US/technologies/back-end-frame...
So by that graph, it has a good chance of being entirely deprecated and/or abandoned in the next 3 years, what a wonderful foundation for a backend.
And it doesn't even have any support for an ORM? Neither does Express? Having to hand-write every single query and migration like it's 1999 again is hardly the cutting edge of IT stacks…
> The problem isn't learning two languages, it's interop between two languages.
Regarding ORM, it's typically paired with Sequelize or Prisma. (I'm personally using the latter.) I've built Django apps in the past (it's actually how I learned Python in the 2.5 days), but what's nice about Node/TS is that the frameworks are more loosely coupled so you can pick/choose your best components. For example, while I mentioned the ORMs above, you can even go one step further and use a backend headless CMS like Strapi, which will get you the ORM + admin interface that you'd get from Django models.
This isn't really true though. There are plenty of open-source modules in Node which were released more than 5 years ago and are still in use today. People only move to new ones, when they are clearly better. What exactly is wrong with that?
> There are plenty of open-source modules in Node which were released more than 5 years ago and are still in use today.
And how stable was their API over the last five years? It hardly counts if over 5 years the APIs change so much they're basically different libraries at the end.
Django's code churn for even complex projects is on the order of single digit hours per year at worst, the remaining 99.99% of time can go into delivering things customers care about.
I can't say I've seen that sort of stability in anything Javascript-related, apart from maybe jQuery projects. (Which of course have their own problems because jQuery is the wrong abstraction usually.)
On the backend, Express has had a very stable API for 5+ years. On the frontend, React has. However, stable or not there's nothing that competes with Django/Rails/Laravel in the Node ecosystem.
I'm not sure React is the best example. Although the library is backward compatible in theory, it doesn't much matter in practice because almost the entire ecosystem switched to a radically different core abstraction a couple of years ago.
There's nothing stopping you from using class component as opposed to the new functional component though. It works completely fine, as it ever was, and in fact, I know a lot of teams are still using it. The API on that front is indeed surprisingly stable. Furthermore, there haven't been any shiny new thing since hooks, and it starting to feel like boring old tech. It's not the cool kid on the block anymore.
There's nothing stopping you from doing it, but part of the reason a library like React achieves such widespread use is the ecosystem that builds up around it, and if everyone else is using hooks to expose whatever functionality they're building, you are now excluded from the benefits of all of that work.
Well sure, if you don't adopt the new technology then you don't get the benefits of the new technology. But that's true it literally every ecosystem. If you don't upgrade to a C11 compiler, then you can't use libraries using C11 features either.
But in both cases, there's little reason not to upgrade because your old code will still work fine on the new version. And indeed you're free to continue writing new code in the "old" style. Adding additional API surface after 3 years while continuing to maintain and support the old API is hardly unstable!
But that's true it literally every ecosystem. If you don't upgrade to a C11 compiler, then you can't use libraries using C11 features either.
I don't think the situations are equivalent, at least not to any meaningful degree.
With C11, your old code continued to work, your old libraries continued to work, your tools probably required at most minor configuration changes, your new code and libraries were still mostly the same style even if you also used some of the new features, and anyone you were working with who knew one version could very quickly and easily adapt to the other.
With React, you can stop after your old code and libraries continuing to work, except that you might not be able to use those old libraries from new code any more and they might no longer be getting much ongoing development. You still effectively have to learn a whole new version of React API, and find your way around a whole new ecosystem of libraries and tools that operate alongside that new API. So does everyone you're working with. You have the backward compatibility, but only by having two completely different coding styles in the same code base, and if you're hiring new people who only know the new API and ecosystem, they now have to learn the old one as well to work on your code.
If the original point was about whether tools are stable for a long time so you don't have to worry about making major changes or learning big new things, one of these situations is not like the other.
This is why features and deprecations are announced years in advance of the changes and that when code to support a feature is eventually removed they produce a compatability polyfill in order that teams do not need to do big-bang rewrites (e.g. https://github.com/reactjs/react-lifecycles-compat).
Maybe you disagree with what backwards compatability is? It doesn't mean that new features are backported to old verions of React or that the recommended syntax/API never changes. It does mean that you can rely on modern versions of React being able to run code you wrote 5+ years ago.
I find complaints about the stability of JavaScript kind of ridiculous. Everybody is literally still transpiling down into ES5 (2009) and most only dropped IE11 this year (2013), the main libraries/frameworks tend to make expert use of semver, polyfill old APIs and release codemods to automaticallly perform syntax upgrades. I'm interested whether there are any programming language ecosystems that have done this better? As far as I can see Python 2 to 3 caused hard rewrites, etc.
The fact that you can have different coding styles and APIs in your project and it will work is proof that it is backward compatible.
I don't think anyone is disputing that React is still backward compatible with the old API. The point is that there is a difference between having two APIs that both still work and having one stable API.
Backward compatibility is implied if your API is stable, but that's only one aspect of stability and there are many other practical questions. Will documentation and tutorials from a few years ago still be relevant? Will someone joining your team need to learn anything different before they can be productive? Will other libraries you have used previously that integrate with React still work with your new code? Will new libraries you might want to use today that integrate with React work with your existing code that uses the old React API?
Having multiple integrations with different APIs or different libraries to do the same job is a form of technical debt, and sometimes it can become quite expensive.
I find complaints about the stability of JavaScript kind of ridiculous. Everybody is literally still transpiling down into ES5 (2009) and most only dropped IE11 this year (2013), the main libraries/frameworks tend to make expert use of semver, polyfill old APIs and release codemods to automaticallly perform syntax upgrades.
Well, there are a lot of things you've said there that aren't quite the whole story.
A lot of modern build processes don't just target vanilla ES5 any more. They'll target something like the most recent two versions of the evergreen browsers and any specific minimum versions of other browsers they need for their particular market. This produces more efficient production code because all major browsers now support much more recent JS natively.
There are also some modern JS APIs that you can't completely polyfill. You have to target a runtime environment that provides real support for those.
Semver is great when it works, but when your culture is to have absurdly deep trees of nested dependencies with hundreds or even thousands of indirect packages involved, things still break often enough to notice.
Major libraries might provide automatic codemods for straightforward, unambiguous changes. However, sometimes you can't divine the original developer intent automatically. Then some manual intervention is required.
I'm interested whether there are any programming language ecosystems that have done this better? As far as I can see Python 2 to 3 caused hard rewrites, etc.
Almost all of them, in my experience. JS, including the ecosystem and culture around it, has by far the worst stability story of any major language I have used.
This is partly a cultural problem. Writing code to last simply isn't part of the mindset or skill set of many people working in web development.
Many tools and libraries we rely on for the most vital functionality are FOSS with at most a small team working on them or maybe just one single person. That means even really successful and widely used projects can easily fade away as those behind them lose interest.
Much of what is built on top is written by people being paid astronomical amounts of money who will job hop in less than two years for even greater astronomical amounts of money. They might make it to senior/staff levels a few years into their careers or maybe become the CTO at a startup, never having either built a new product from scratch or maintained one for 5+ years to see where those decisions they made earlier on come back to haunt them. Then those people are the ones leading and mentoring the next generation of newbies working in the JS community, and the cycle continues.
It's also partly a technical problem. The language doesn't provide much to help with building large-scale software and maintaining it over the long term. What it does provide is relatively recent. The tooling is relatively weak, well behind the state of the art for many other popular languages, which in turn lag the more research-focussed languages where radically different ideas get explored.
I believe a big factor in these cultural and technical problems is the way that you can just change your code and push out a new version any time you want since you have complete control over the servers hosting it. It has also become the norm to depend on online APIs provided by other parties who can do the same. This means concepts like managed releases and support lifetimes and stable interfaces are given less importance.
In striking contrast to all of that, there is code I worked on professionally a couple of decades ago that was written in C and would still compile and run on any modern platform with few or no changes. Likewise, there are professionally developed libraries in ecosystems like Java and .Net, which are platforms widely used for large-scale enterprise software development, that have been around for a decade or more and are still as active as ever. Even in Python, the 2-to-3 shift took place over about a decade, taking the community and the tools and libraries along with it. The language is still mostly compatible with Python 2 code, and there were tools to mechanically update code for most of the main breaking changes, so many of the popular libraries from the Python 2 era are still available and working fine with Python 3.
The only other language I've used where instability was as awful as JS world is Haskell, and that's obviously not a mainstream language in the same sense. It's mostly used by a community who are very open to trying big new ideas and changing how they work frequently, and that's part of its attraction to those people and also probably a reason that ideas from Haskell sometimes drift into more popular use over time but the language itself remains an eccentric choice for production use.
> The point is that there is a difference between having
> two APIs that both still work and having one stable API.
This is the direct effect of high levels of backwards compatability. You can't change APIs; you have to create new APIs and then deprecate previous APIs. That's the only way of avoiding a breaking change (other than never changing something and endlessly layering leaky abstractions on top of it).
> Having multiple integrations with different APIs or
> different libraries to do the same job is a form of
> technical debt, and sometimes it can become quite
> expensive.
I disagree. If you don't need to do any work to something it has zero cost. Write tests to its behavior and it can be a blackbox to your team until you truly need to deal with it.
> A lot of modern build processes don't just target
> vanilla ES5 any more. They'll target something like
> the most recent two versions of the evergreen browsers
> and any specific minimum versions of other browsers
> they need for their particular market.
This isn't mainstream yet. Until very recently the majority of companies were targetting IE 11. A lot of companies changed this in 2020 (Microsoft, Atlassian, etc), and additionally due to Node finally supporting ESM and the release of Snowpack and Vite, many open-source developers are finally targetting something greater than ES5. But you're wrong to imply that it's the norm.
> There are also some modern JS APIs that you can't completely polyfill.
People tended not to use these due to needing to support older browsers. But sometimes APIs could be partially polyfilled to an extent that was sufficient enough to use them (like `Proxy` with `proxy-polyfill`).
> Almost all of them, in my experience. JS, including the ecosystem and
> culture around it, has by far the worst stability story of any major language
> I have used.
OK, yeah, I'm not seeing this at all. For a start, TC39 has rules against breaking the web (see "One JavaScript", etc: https://tc39wiki.calculist.org/about/faq/). It's due to this choice that we still have mistakes like `typeof null === 'object'`...
Of course, TC39 is not perfect and there are very rare occasions that minor incompatabilities are introduced (https://tc39.es/ecma262/#sec-additions-and-changes-that-intr...) but "the worst stability story of any major language" is quite an absurd statement if you consider the minutae that has made that list.
> [...] Much of what is built on top is written by people being paid astronomical amounts
> of money who will job hop in less than two years for even greater astronomical amounts
> of money.
This is all true. But most of the products these people create are also being replaced every 2 years so it's not as big an issue as you think it is. We're able to go back to projects written in JavaScript 10+ years ago and they work in newer browsers, but the majority of projects are thrown away or rewritten for completely different reasons before this point (normally employee attrition on smaller projects is enough to lose the knowledge required to fix bugs or add features and so companies rewrite to get back that understanding).
I guess a form of backwards compatability we don't have is the ability to upgrade a tooling dependency through multiple breaking changes and not find out that the configuration system has been completely overhauled. That is unfortunate. But the code will build/run when you pull it down the first time from your repository. If you then decide to make upgrades to use new tooling you have to know what you're doing -- tooling upgrades are confusing.
> The language doesn't provide much to help with building large-scale software and
> maintaining it over the long term. What it does provide is relatively recent.
> The tooling is relatively weak, well behind the state of the art for many other
> popular languages, which in turn lag the more research-focussed languages where
> radically different ideas get explored.
I disagree. It has testing frameworks, it has automated code formatters, it has linters, it has type checkers, it has tools to automate rewriting 10,000s of lines of code via the AST, it has tools to automate producing changelogs, it has tools to visualise dependencies, it has tools to improve the performance of scaling a monorepo, etc. Some of these tools are significantly worse in other programming language ecosystems or do not even exist.
> Even in Python, the 2-to-3 shift took place over about a decade, taking the community
> and the tools and libraries along with it.
Are you trying to tell me that a breaking change that was so bad that it took almost a decade for the community to complete is something that we should aspire to?
I don't think that JavaScript has serious backwards compatability issues at all. Certainly not in the language. Generally not in the major libraries (React, etc). It perhaps has some issues in breaking changes to the tooling which could make upgrades very confusing (e.g. Babel changed how configuration worked a few times and this was painful due to obscure error messages).
On the other hand, I will say this: it is true that the open-source JavaScript community is high on modularisation, scrappy/innovative and prone to releasing something for fun and then ghosting their consumers. In situations where the quality of the package was high enough that you don't need to change anything this presents no issues, but sometimes when you've used a package with a broad vision that the creator has later on bowed out of fulfilling or which has later on produced lots of bugs, that then leads to engineers swapping it out for newer, shinier or better maintained (for now) things... That is the 'stability' issue that we tend to have issues with and it's the reason that I (and a small minority of other people) have started to 'vendor' or inline code into our projects. As Tom MacWright recently wrote "One of my golden rules is that you shouldn’t blackbox things you don’t need to. I like to “use dependencies for efficiency, not ignorance.”" (quality article by the way: https://macwright.com/2021/03/11/vendor-by-default.html).
This is the direct effect of high levels of backwards compatability. You can't change APIs; you have to create new APIs and then deprecate previous APIs.
I don't see how that follows at all. You can't make breaking changes to APIs, but it's fine to extend them or even expose different levels of abstraction as long as the underlying model you're using stays consistent and you provide suitable defaults where necessary.
If you don't need to do any work to something it has zero cost.
This is tautological, but if we're talking about a typical web application then you are working with that code, every time you make a new build. It might sit there as an untouched black box for a while, but if it has any kind of external dependencies or it relies on anything that could change about the language, platform or other parts of your own code, then there is always a risk that it will later break, and then you'd better hope you have someone around who still knows how to fix it.
This isn't mainstream yet. Until very recently the majority of companies were targetting IE 11.
You've made several claims like that, but in the absence of data there's no way to know whether you're correct. For example, preset-env has been in production for 3+ years now and had an extended beta/RC phase before that. It's true that it defaults to ES5 if you don't configure it, but the Babel docs explicitly recommend that you do, and it is literally a one-line change in your package.json to do something more modern and efficient based on Browserslist unless you genuinely need that degree of backward compatibility.
Of course, in some cases, even quite recently, you did need that. A relatively small proportion of business customers stuck in the IE11 era could still represent significant revenue at risk if you dropped support. But it will take more than an unsupported assertion to convince me that this has been the norm for most web development for quite some time. At one of my businesses, we've had literally no-one using IE11 visit a B2C web app for years. At another that mostly does outsourced development work, we've excluded IE support contractually for a long time and no client of any size has pushed back in years. There must be many thousands of other small businesses out there like mine, and I have to assume that they have senior devs who sometimes read the docs for the tools they use too.
OK, yeah, I'm not seeing this at all.
I think that's because you persist in interpreting my comments as being about JS itself, when I've tried repeatedly to emphasize that it is the culture and surrounding ecosystem that are the bigger problems. I'm not talking about the technical committees defining the language. I'm talking about the developer experience of using it in production.
On that score, I stand by my earlier comments. After many years of programming professionally, using many different languages, I have yet to find any more flaky ecosystem than JavaScript's other than the deliberately fast-paced world of Haskell. Nothing else even comes close for how much wasted effort I've seen over the years just keeping all the plates spinning so nothing falls off and breaks.
But most of the products these people create are also being replaced every 2 years so it's not as big an issue as you think it is.
Yes, I understand the commercial argument. The bizarre economics in the web dev industry sometimes make throwing entire projects out and rewriting every 2 years affordable. That doesn't mean it's not a horribly unstable environment, which was the original point of contention, nor that disregarding traditional wisdom about the dangers of big rewrites isn't a bad idea. It just means parts of the industry are so rich that they can afford to have a toxic culture where quality is a second-class citizen and the only answer to producing so much unmaintainable junk is exactly what you said. It's much nicer working in other parts of the software industry where what you're producing is expected to work and to last, but sadly it doesn't always pay as well.
It has testing frameworks, it has automated code formatters, it has linters...
And these kinds of things are advanced tooling, in your view? We had those in our IDEs for building desktop software back in the last century. Except they were automating rewriting millions of lines of code on 2000-era PCs, not 10,000 lines of code on 2020-era PCs.
I'm not sure what other popular programming language ecosystems you think don't have these kinds of tools today or have tools significantly worse. But in web development, TS is the current hotness because the developers finally realised that explicit typing is helpful for building and maintaining more than small systems, and not so long ago build tools adopting tree shaking was being heralded as a great advance for reducing the size of builds, and before that we got the radical new concept of a module import/export system so you could write code in more than one file without jumping through crazy hoops, and before that we discovered that immediate mode UIs and declarative specs are a thing. All of these ideas were well known and widely used elsewhere in the programming world much, much earlier.
Are you trying to tell me that a breaking change that was so bad that it took almost a decade for the community to complete is something that we should aspire to?
It took that long because that backward compatibility and stability we've been talking about meant a lot of older projects didn't need to move any sooner. And yes, having a platform where you can write code and it keeps working and the ecosystem still positively supports it for another decade is definitely something we should aspire to.
Generally not in the major libraries (React, etc).
Don't tell that to anyone who uses React Router. Or who builds their app with Webpack. Or Babel, as you mentioned. And again, it's important to note that you only said backward compatibility here. If we're talking about the broader concept of stability then you also have to include high profile libraries like Moment giving way to more modern alternatives because although they still work, they don't lend themselves to modern programming styles or play so nicely with other tools.
These comments are getting long and I suspect we may have to agree to disagree on some of this, but if you haven't worked much on software in other parts of the industry, I encourage you to look at what is considered the norm and acceptable practice in fields where better quality and greater longevity are more highly valued. If we built security libraries or the embedded software controlling industrial machinery the way a lot of online companies build their web apps, we'd be lucky to survive the night.
I'm trying to respond in good faith, even though I feel you unnecessarily resorted to trying to condescend me.
You wrote:
> there is a difference between two APIs
> that both still work and having one
> stable API.
As I explained, "this is the direct effect of high levels of backwards compatability. You can't change APIs; you have to create new APIs and then deprecate previous APIs."
I thought my point was obvious, but will explain it with more words:
If never making breaking changes to APIs is a strict requirement, all API changes must be additive. That means backwards compatibility entails the existence of more than one API to do the same thing. It seemed like you were insisting that there should be "one stable API" that never needs changes instead of "two APIs that both still work" and this is unrealistic for something that has existed and responded to changes in use for ~25 years.
> if it has any kind of external
> dependencies or it relies on anything
> that could change about the language,
> platform or other parts of your own
> code, then there is always a risk that
> it will later break
This is a useful point. For dependencies that never make breaking changes you will be OK. But if the dependencies you have are likely to change and likely to be upgraded elsewhere in the codebase and potentially might make breaking changes, we should consider them a risk to the project.
I agree that this should be highlighted -- but, in the context of what you were talking about, which was with regards to code that uses old features of React, you are incorrect. As I mentioned to you, compatibility packages exist for all old React lifecycle methods and deprecated patterns. Therefore, by design, you are not being forced to upgrade the patterns in old parts of your codebase.
I am trying to make specific claims about concrete things that I can evidence. The existence of compatability packages for features that have been deprecated for 5 years invalidates a specific argument about needing to upgrade old React code due to changes in the API.
> You've made several claims like that,
> but in the absence of data there's no
> way to know whether you're correct.
> For example, preset-env has been in
> production for 3+ years now and had
> an extended beta/RC phase before that.
> It's true that it defaults to ES5 if
> you don't configure it, but the Babel
> docs explicitly recommend that you do.
> [..]
> But it will take more than an unsupported
> assertion to convince me that this has
> been the norm for most web development
> for quite some time.
If it defaults to ES5 why are you asking for me to provide evidence as to whether companies have generally targetted IE11? It is the default; it is very unlikely that there is a majority of people that are configuring it...
> But it will take more than an unsupported
> assertion to convince me that this has
> been the norm for most web development
> for quite some time.
My claims are the following:
1. ES5 has been the default for front-end packages published to NPM since it was released (https://twitter.com/_developit/status/1289317757146693632). (I'm linking to Jason Miller's tweets since he has been the one most obssessively pushing for this to change. The problem we've all been having is that the `package.json` fields do not make it explicit what syntax a package is using.)
For context, this was to evidence my opinion that the JavaScript community has been very slow moving and careful to output code that is executable by old browsers to the extent that we've supported a browser released in 2013 and used a syntax released in 2009.
> And these kinds of things are advanced
> tooling, in your view?
Check back to my text and you will see that I made no such claim.
You claimed that "the language doesn't provide much to help with building large-scale software and maintaining it over the long term" so I demonstrated that we have all of the necessary tooling to do so and invalidated this.
> We had those in our IDEs for building
> desktop software back in the last
> century. Except they were automating
> rewriting millions of lines of code [...]
Can you point me towards examples of the usage of AST rewriting tools that are actively being used by open-source library maintainers in other ecosystems to help their consumers do upgrades in large code-bases (e.g. I can see that `clang` has AST tooling, but I don't see examples online of this being widely used: https://devblogs.microsoft.com/cppblog/exploring-clang-tooli...).
> Don't tell that to anyone who uses
> React Router. Or who builds their app
> with Webpack. Or Babel, as you mentioned.
I agree that those particular libraries haven't been maintained well (they make extraordinarily large changes in major versions to the extent that sometimes it might as well be a whole new library).
> I encourage you to look at what is considered the norm
> and acceptable practice in fields where better quality
> and greater longevity are more highly valued. If we
> built security libraries or the embedded software
> controlling industrial machinery the way a lot of
> online companies build their web apps, we'd be lucky
> to survive the night.
I think your argument has been a moving target. Originally, you pointed your finger at React saying it has a stability problem, so we showed you that they've been incredibly good at keeping backwards compatibility and that you could upgrade your version of React to regain access to the ecosystem's newest libraries built on top of new APIs without needing to rewrite your legacy code through the usage of compatability packages.
Then you implied that it was an overall JavaScript ecosystem stability problem, so I showed you the level of effort that TC39 and the brower maintainers go to keep backwards compatability. And I showed you that most in our ecosystem have been carefully supporting the lowest commmon demominator users for almost a decade by producing web apps that work in IE 11 and packages that first-class ES5 syntax, and gave you examples of big webapps that only recently broke from this tradition.
Now you are pointing at exceptional cases involving particular poorly maintained libraries and tools, and telling me that we lack tooling to deal with scale (which is a separate concern). If you don't think Webpack and React Router are good citizens with regard to their API stability and this annoys you because you like to be on the latest/greatest then don't use them. I and many others also specifically avoid these libraries/tools and yet don't paint the whole ecosystem with this one brush. (On the topic of tooling, it has only been very recently that we've been getting tooling that can deal with high-scale development, however it is happening now.)
* * *
I think that possibly what you're noticing is the second-order effect of more and more usages of JavaScript and web technologies causing new APIs to steadily be added to the web with the old APIs remaining forevermore. The original APIs were made to display and navigate documents. As the years have passed more and more APIs have been released to support more complex types of applications and this resulted in overall churn in user-space as library creators iterate to produce better domain-specific APIs. We provide a high-level of user-facing stability despite this.
I don't think it is fair to compare what we are trying to achieve to what is important when controlling industrial machinery. The use cases of that are much more static, while in 2021 people on the Web are creating tools like Figma (https://www.figma.com/), Office 365 (https://www.office.com/), Buerli (https://buerli.io/), and Spline (https://spline.design/). This is very far diverged from where we started and the fact it has been achieved without breaking the web is impressive. It's also quite clear to me that high-quality tools like these aren't achievable without the creation of impressive and scalable tooling (some of which has been released to the public).
I'm sorry if anything I wrote came across as condescending; that was not the intent. You seem reasonable enough, and objectively I agree with much of what you've said. However, I think we've been talking slightly at cross-purposes.
I won't try to go point by point now as these comments have become very long, but overall the difference between our positions (as I intend mine and as I currently understand yours) seems to be that you're focussing on specific technologies like JavaScript or React, while I'm talking more holistically about the entire ecosystem around them.
For example, you have talked about backward compatibility being excellent within JS-the-language, and about React continuing to support its class-based API alongside the functions-and-hooks alternative. That compatibility is not in dispute.
However, when I'm talking about stability, I'm also including everything that is built around JS or around React, the libraries and tools and documentation and people. And in these respects, the JS ecosystem is much faster moving and more fragile than almost any other language I have ever used.
The kind of bifurcation of APIs we've seen with React causes a lot of churn even if the library itself is still backward compatible. If you looked at blog posts or Stack Overflow answers or Reddit discussions about React from as little as three years ago, many of them would have little relevance to the newer API that has obviously become dominant within the community since then. On the other hand, if you hired someone with a couple of years of React experience today and asked them to maintain older code in your system that used the class-based API, they might have no idea what they were looking at. And if you found a useful library to work with React components but it only provides a hook-based API, again you can't use that functionality from your older class-based components. Your old code might still build, but it's essentially unmaintainable unless developers who have come to React more recently first learn what is effectively an entirely different library from their perspective, and even then you're limited in how much you can integrate that older code with more recent contributions to the ecosystem. (This paragraph is an elaboration on the point I was trying to make when I first joined this discussion.)
For the wider JS ecosystem, we've talked about the breaking changes in major tools like Babel and Webpack and in popular libraries like React Router. You suggest that these are "exceptional cases involving particularly poorly maintained libraries and tools". I suggest that there is, unfortunately, nothing exceptional about this sort of abandonment of earlier versions and interfaces within JS world. For one thing, Babel and Webpack aren't just any tools, they are arguably the two biggest names in the JS ecosystem, so when they break, the damage is widespread. For another, they are far from isolated cases. To give another example, Angular was React's big contemporary "competition" and it too essentially abandoned one API in favour of a radical rewrite for version 2, turning any project using the older framework into legacy code almost overnight.
Before React and Angular, we had a string of moderately popular UI libraries built around various levels of data binding. These were must-know technologies in their day for anyone who wanted to work on a project using them, but none remained popular for more than a few years, again leaving all of the individual knowledge and documentation and old code bases largely obsolete.
This pattern isn't unique to UI libraries, either. For example, as JS has evolved and added support for promises and then async/await, many older libraries whose interfaces weren't designed to support that programming style have been left behind, again including some that were very well-known and widely-used.
And with tools, it's a similar picture. Although Webpack is probably the most popular tool for building web app front ends today, over the years we've used shell scripts, self-contained tools like Browserify and Babel, task runners like Gulp and Grunt (with their own surrounding package ecosystems) to co-ordinate the ever-increasing number of tools used in build processes, more comprehensive tools like Webpack (again with a big surrounding package ecosystem) to try to unify everything in one place and bring some structure back, attempts to simplify the horrendous complexity that unification had introduced (the later versions of Webpack and the likes of Parcel), and now we're swinging back towards more specialised tools but in some cases with much better performance such as esbuild, but ironically these newer and better tools may be hard for a lot of projects to adopt because so many people are boxed in by their existing tools and have to wait for someone to provide some plug-in package for those existing tools in order to integrate the new ones. And again, breakage is not unique to Webpack. For example, not long ago, Parcel pushed out a breaking change, and because the effort from the Parcel devs is mostly focussed on the still-in-beta Parcel 2 that naturally has some major limitations of its own, this left teams using Parcel with broken builds either way until they figured out what the problem was and then probably rolled back to an earlier version of Parcel 1.
So I suppose my point is that all of that disruption can and does still happen frequently within the JS ecosystem, despite the backward compatibility of JS itself and the willingness of at least some of the big libraries to continue supporting old APIs after launching new ones. Stability, in the sense I'm using the term, implies a reasonable degree of backward and forward compatibility. The converse, unfortunately, does not hold. A good compatibility story is necessary but far from sufficient for a stable, productive ecosystem.
It's a general purpose web framework, that happens to have a tight frontend integration thanks to JS and React. It's still JS + Node, and everything that enables.
There are frameworks like blitz.js(https://blitzjs.com/) coming up which build on top of next.js and provide you a full-stack development environment with react in the frontend. Far superior than what django/rails/laravel can offer.
Learning is great. It expands horizons, potential, and current capabilities. Learning is not producing though. Learning is a cost center. If you want to increase productivity start by minimizing required learning. That exchange is called usability.
There are two fundamental practical problems with your thinking.
1. Employers don’t train on languages/frameworks. In most circumstances employees are expected to learn on their own or from a prior employer before applying for a job. Worse, the last place I interviewed only asked about learning from the current employer while never asking about self learning outside the office.
2. Employees, in many cases, believe they can cheat learning by using a tool or framework. That is largely due to a lack of boundaries and experience in a given environment or platform resulting in low trust of peers and the technology.
If you want to require learning then provide sufficient learning material expecting a predefined structured outcome.
We are training our employees. Learning the ropes of a new language/framework enough to make easy changes is trivial, so why wouldn't we? Much better than crippling our choices in software stacks we can use.
Deciding your tech stack solely on avoiding having to train people for a few days sounds like a terrible way to organise projects.
How often is it really only a few days, though? If you're talking about learning a different programming language, that's no small thing for a junior developer. For a senior who knows multiple languages already and has a few years of experience, learning the new language itself might only take a matter of days to be productive, as long as it's still a similar style of programming to something they've done before. But then you need to find your way around the ecosystem so you can make informed decisions, and that ecosystem might be huge and mostly low-quality, even if the good parts that you eventually want to use are not.
For similar reasons, in the case of web development specifically, I think people often have unreasonably high expectations from using JS/TS both front and back. Yes, it's the same language, more or less. Yes, sharing code can sometimes be useful. But the JS standard library is limited, and the ecosystem beyond that has almost nothing in common on the front and back ends. In practice, assuming you have some decent senior devs on your team, that ecosystem jump is still likely to be the biggest time sink even if you're running something in Node on the server.
So I kind of agree with both the parent and GP comments. It is beneficial to use familiar tools and reduce the need to learn new things before you can be productive, but you are going to have to learn new things sometimes anyway and that might require significant time no matter what you decide to do. When it comes to making fundamental architectural decisions for a new project, it's wise to keep the potential costs of using new things in mind, but it's foolish to disqualify choices that might be better in the long term because of small differences in up-front costs.
Depends entirely on what you expect the devs to do, naturally. Junior devs are IMO not supposed to make informed decisions of significance in any language, that's what you have senior devs for.
GP's use case of having frontend devs do small changes to backends and vice versa to avoid having to wait for The Other Team to have time, is very easily covered with really minimal training.
GP's use case of having frontend devs do small changes to backends and vice versa to avoid having to wait for The Other Team to have time, is very easily covered with really minimal training.
Sorry, but I can't really agree with that, certainly not for anyone below senior.
Asking juniors, who don't have much breadth of experience yet, to jump from front end to back end is a good way to end up with subtle SQL injection vulnerabilities, or passwords being hashed with non-cryptographic hashing algorithms, or secrets that should be handled at the environment level being hard-coded and committed.
Asking juniors to jump from back end to front end is a good way to end up with code that runs fine in Chrome but breaks in iOS Safari, or a subtle interaction between promises or awaits that deadlocks the whole UI if the server is unreachable, or styles that break when someone updates the theme six months later because two elements were the same blue at the time but the stand-in dev looked it up from the wrong place.
Either way, there's significantly more for them to learn if they need to know a whole new programming language as well as the specific libraries and the general principles about security and so on. And either way, The Other Team are probably going to be involved and therefore a potential bottleneck anyway, as surely at the very least someone senior from that team will be required to review code changes being requested by someone from outside the team who doesn't normally work in their part of the code.
It's never just adding a field to a structure. That data is going to be there for a reason, and someone is going to write the code to do whatever that is.
And to parse the data arriving in a request from the front end.
And to validate the parsed value.
And to perform the necessary security checks. Wait, shouldn't they have been done already?
Where do we keep the validation logic in this design, anyway?
Hang on, what type is this field? Is there a native way to represent that in this back-end language, or some convention we've adopted? Did the parser already handle that?
The scenario was a front end developer making a small back end change or vice versa. In such cases the rest of the code to be written will be in the part they're familiar with.
Sometimes the field isn't part of the request. Or maybe part of the minimal training was wrapping ValueError in BadRequest. Or maybe part of the minimal training was we have an exception handler do it automatically.
Often there aren't any new security checks.
Sometimes field types are documented. Sometimes you have an integer in the database and need the same value as an integer in the front end.
Most of the issues you brought up don't go away if you use JavaScript everywhere. Learning a little of another language is comparatively simple.
And yet – Apollo advertises its easy Python interoperatibility right on the front page, as one of the features that makes scaling easier.¹
GraphQL arguably makes decoupling frontend and backend languages even easier than classic REST APIs, since the GraphQL schema can serve as single source of truth across language barriers.
> And yet – Apollo advertises its easy Python interoperatibility right on the front page
Yes, absolutely, there is great support for GraphQL in many different languages.
> , as one of the features that makes scaling easier.¹
To be clear, that is your own commentary and I didn't see anything in the Apollo site that said implementing in Python makes scaling easier. I.e you seem to be implying that somehow implementing in Python is better for scaling, but there is no background to support that.
> GraphQL arguably makes decoupling frontend and backend languages even easier than classic REST APIs, since the GraphQL schema can serve as single source of truth across language barriers.
Yes, I totally agree with that. If you are, say, providing an API to other developers GraphQL is a great choice for a number of reasons, one of which is that there is great language support across pretty much all languages.
But if you are starting a project within a company, and have the luxury of choosing technologies, having the same ecosystem on the front and back ends makes it much easier for people on either team to go across that "boundary" if necessary. This is not just me hypothesizing. For the majority of career, which really started right when web apps started taking off, there was a separate language on the backend (Java for the majority of my career, but also sizable stints where Ruby and Python were the backend languages). Yes, most backend folks understood JS and CSS, and most frontend folks could understand the backend languages, but it was still a huge barrier to people being able to contribute across teams such that it rarely happened. It's only in the past couple of years where I've been in a "TypeScript everywhere" org where I've seen the gigantic change in the team dynamic that this allows.
On the other hand I've seen JavaScript everywhere slow down back end development and increase costs with not much increase in contributions across teams.
I've seen the same. It starts off faster and then as the business grows and features are added the problems scale up. Some symptoms I've seen on projects I've been asked to look over include but aren't limited to throwing Redis around when an in-memory structure would normally suffice because Node is too slow, scaling to 200 CPU's and using up at least 200GB gigs of RAM for a single servioce, when a 25 instances with 8 CPU's, 25GB of RAM could do the same job and cost a lot less, scared to write their own data structures/algo's that may be required as their business scales, etc.
I hear about this dreadful "scalability" problem with GraphQL and N+1 queries and all other sorts of geysers constantly, but I see a lot more success stories than failures.
idk why people mentioned Next.js which is more Front End framework than Back End, but no one mentioned Nest.js. It is not old as Django but I think Nest is nearest framework to RoR/Django in Node.js
Definitely. NextJS isn't a "backend framework", it's a server-side rendering framework that has some backend abilities to handle simple use-cases.
NestJS is the most full-featured Node framework, but it's lightyears behind Django. Yet I'd still use it given the choice between both, because I prefer Typescript so much better than Python and having a single language through the stack is a game changer, enough that I'm willing to compromise on the frameworak.
I have a lot of experience in both python, typescript and react. I would still opt for python on the backend, simply because it's a nicer language to work with. Debugging is a joy, and it feels like the library ecosystem is more comprehensive and stable.
This is of course subjective, and maybe I'm biased due to having a lot more experience with python than JavaScript.
> having a system where everything is on the same tech stack (i.e. front end in TypeScript with React, back end with TypeScript on Node) has resulted in gargantuan productivity gains
How so? Is it just about being able to use a single set of tools, libraries, habits, etc? Or are there particular things which are easier when the language is common? Are you sharing code between front-end and back-end.
I do very lightweight front-end coding these days. It's usually some variation on populating and updating a table from a websocket, maybe with some simple filtering and toggling in response to user interaction. There, i can't think of any particular advantage to having both ends in the same language, but then mine is quite an unusual use case.
There’s a lot of compelling reasons to share code particularly at network boundaries. Using something like io-ts/zod/etc gives you simple, declarative, type safe validation. Being able to share that behavior is an enormous productivity boost in and of itself.
Sharing validation for forms is definitely really nice.
It feels like it should be possible to do that cross-language, generating some JS validation rules from Java annotations, say, but i have never seen it done.
The way it’s usually done is with a generalized language-agnostic spec like OpenAPI/JSON Schema. Because the definitions are standardized, you can effectively build tools in any language that should provide the same validation, to the extent they’re compliant and the spec is unambiguous.
These approaches can of course be combined, where the sorts of validators I mentioned generate (or even build their primitives around) those more verbose standards.
Mainly it has to do with teams. In most orgs there is something analogous to "a backend team" and "a frontend team", because the concerns and expertise are quite different.
Oftentimes, however, a frontend dev may need some small extra bit of data or functionality from the backend, and vice versa. If the ecosystems are very different, then the amount of time it takes to set up that separate ecosystem, remind yourself of the relatively minor syntax difference e.g. between TS and Python, update your dependencies, etc. can be a big barrier, so often the answer is to just throw a ticket over to the team on the other side and wait.
If, on the other hand, you can just quickly get into the other codebase, make a small PR and get it reviewed quickly, it can drastically improve the team's overall productivity.
I've always had front-end and back-end owned by the same team, and in the same repo, despite being in separate languages. The repo has a single build script which builds all parts of the project, whatever language they are in. Implementing almost any feature involves touching both front-end and back-end code, so people stay fresh. All of this seems like table stakes to me.
Maybe some organisations have separate teams working on the two parts of an application, which honestly just seems stupid, but that's not a necessary consequence of using different languages.
> For contrast, I know many teams with a backend in Python and a frontent in React/JS, and I've worked on some teams with that setup. In my opinion it's virtually all downside compared to a backend in TS, as Python and TS are quite similar from a web programming perspective (I'm not referring to Python's advantage in data science tooling), so all it basically is is a barrier to your front end folks being able to make small enhancements on the backend quickly.
How big of a problem is this?
At the end of the day all that really matters is that the external representations that get handed off are the same and that everyone makes the same assumptions. Given the same set of fields manipulating a POJO with Java streams is not all that different from using modern Javascript on a blob.
If there are productivity gains to be had please share it with the hoards of nodeJS 'full stack' devs at my company who suck up all wages, dont produce anything, and make people hate digital
Typescript makes refactoring easier in what way? Can you do renames without error prone string search and replace? Can you get good autocompletions with ts? If so, that would be really nice
Yup! Especially using VsCode, which feels optimized for TS development. Click the var you want to rename, hit F2, rename it, and it renames all instances of the var. If you're renaming an import, it'll do it across all the files automagically. Moving a file? Imports get updated too!
Plus you've got MS's intellisense powering autocomplete. Unfortunately, I don't think it can recognize different foods, but as long as you've typed your variables the autocomplete is pretty good!
EDIT: the OP had a typo, saying food instead of good, for context as to why I made a food joke
> This biggest "aha" benefit I get from TypeScript is that it is structurally typed, while Java is nominally typed. In my experience it has proven much easier to refactor in TS because I just need to ensure my objects have all the right properties. With Java if I have a Thing1, but a library is updated to add just a single new property so now there is a Thing2 type, well now then all the places I need a Thing2 I have to completely copy over from Thing1 - I can't just add the property and be on my merry way. This happened to me many times in my Java career - I still think I have PTSD having to do a Jersey 1.x upgrade to a Jersey 2.x version across a large codebase. It was a nightmare I've never had anything come close to with Typescript.
Not so much refactoring as upgrading, but tis an example of why duck typing is kinda nice
But seriously... If you want to compare tooling, you shouldn't be comparing a scripting language vs a language like Java... compare Java vs C# and C#'s experience is better than Java's IMO (not REAL experienced with Java but I've done some basic stuff).
At my last company I created a few tools that became key to my org, which was front end/JS oriented. Being able to write them in JS meant anyone could contribute fixes and features trivially, with zero ramp up time. That is a really nice benefit of Node. Imagine if Rails developers couldn't use Ruby for their tooling. Node really filled a nice gap here.
> everything is on the same tech stack ... has resulted in gargantuan productivity gains
i highly doubt that - i don't disagree you got productivity gains, but it's not from being the same stack, but it's from experience gained doing it.
If what you say is true, why doesn't people use GWT (google web toolkit) and java on the backend to get this productivity gain? It has existed even earlier than typescript, and is compiled to be quite fast. It's even more integrated as a stack, and anyone knowing java is able to use it fairly easily.
no - react is a library, and in fact people do use react on the backend (for server side rendering).
we are talking about tech stack - most broadly the language (and compiler). GWT is a compiler from java to javascript. it cannot be compared to react (even tho GWT has a front-end UI component - but that's optional in GWT).
> switched to Node, and shortly thereafter to TypeScript
Undergoing a similar path. My problem is that the moment I switch to TypeScript and start writing my code becomes very similar to Spring. And at that point I have to ask a question of why would I not just write Java. Node on the other hand feels like node.
Either way you try to argue this, it's hard to make the case that Java/Javascript is better at any of those things than another language. Productivity be damned, your dinky jar file will get smoked on almost every quantifiable level if you pit it against against a C++ or Rust rewrite. What GP is saying is that the only reason people praise Javascript is because it's a unique language, and I think it's a fair appraisal. Javascript is in a class of it's own, for better or worse, and since it has no real competitors, it's easy to dismiss detractors.
Whenever I encounter Node, issues almost always follow. Whether it's NPM's delightfully useless error messages or a stream of neverending warnings filling up stdout, it quite literally never fails to cause a problem. Maybe Node should focus on saving it's reputation, because I for one run in the other direction of it. Hell, especially in the case of Node, I hope that Deno comes to replace most of it's core functionality. Putting up with half-assed software on a half-functional runtime only leaves me with a quarter of the patience I started with.
> * Lexical scope natively without syntax or conventions
I assume you mean over the alternative, dynamic scoping like in e-Lisp. But you realize that JavaScript's scoping rules are entirely wonky, e.g. that "var" declarations are lifted to the function level?
It's a dynamic error if you access a let-bound variable before it is actually initialized. In most other languages that have lexically-scoped declarations, it simply would not be visible. So I think JS's choice is actually a regression.
To be more specific the term is hoist which means the declarations are pushed to the top of the scope at run time for maximum availability, and var is function scoped instead of block scoped. Block scoping is often more specific because a function body is a block as well.
var is a terrible example of that. Just don't use it.
A good example would be the scoping in for loops and maybe arrow functions. For loops are goofy but virtually never an issue, and arrow functions are awesome.
JavaScript is different in that it use the function as the lexical scope rather then the angel brackets. This forces you to think about the code as functions, rather then blocks. And in turn helps you think of the code in three dimensions where time is one dimension, making it easier to understand code that runs asynchronously.
Because people coming from other languages find this confusing the let (and const) keyword was specified (ES6/2015) for block/angel-bracket lexical scope. Whereas var is function scoped.
There would be no point in having two ways to do the exact same thing if function-style declaration and arrow-style declaration implementations were identical. Why would they add a new feature to the language if it was purely syntactic sugar?
>> Node is not ECMAScript in a server-side ECMAScript engine, it's JavaScript in a browser JavaScript engine.
>What does that even mean? The APIs are completely unrelated and Node does different things that don’t make sense in the browser.
I have taken the privilege of rewriting the quoted part of the parent comment,
Node runs javascript on the server side in an engine built for the browser. It does not run ECMAScript with an engine specially made for server side apps.
This comment is so weird. JavaScript got scoping completely wrong, and none of those were particularly novel when it was designed and they are almost universal now so I don't know why they would keep you hooked on JavaScript!
And those things are outweighed by things JavaScript got so incredibly wrong... like === vs == and some of the weirdness when you GASP use == as any other language would do.
JS is like PHP... only a popular language because it's been around a long time and it's easy to get started. Otherwise, there are SOOO many better programming language out that the ONLY reason JS still has traction is it became the "default" web language.
10 years ago I would have agreed with you, but in recent years Javascript (and moreso Typescript) are just exceedingly pleasant to use. I'm using Typescript in backend services despite knowing Python and C# well just because I like it.
I can imagine that the original argument does not apply to the languages which compile to JS. But IMO the fact that there is so many derived languages covering the mess which JS is only supports the argument against it.
TypeScript is just JavaScript with type annotations. The runtime semantics are identical. JavaScript itself has improved to the point where it's great to work with, and arguably the nicest of the common dynamically types "scripting" langauges (python, ruby, PHP, perl).
Completely agree. I used to work mainly in Ruby, and I guess I miss its rich standard library, but overall TypeScript is such a joy to work with that now I use it for almost everything.
Couldn't agree more. I started in this field as a javascript programmer. I've since expanded my toolkit to include typescript, elixir, plpgsql and now gaining proficiency in rust.
I'm continually frustrated by my colleagues refusal to step outside the javascript ecosystem. Don't get me wrong, JS certainly has its place but its not ALWAYS the best tool for the job. I see a lot of people reach for node as their go to backend tech choice simply because its the ONLY tool in their toolbox.
Unless you're building a small focused microservice where the functionality involves calling out to a library with working tested code that does what you want, I think node is honestly a poor choice. To qualify my statement, I spent the first 7 years of my professional career building software with nodejs.
The sweet spot is much smaller than the scope of projects people throw at it.
* quick MVP? rails has more libraries that are drop in.
* Performance? go and elixir have node beat for multicore perf
* websockets? compared to phoenix channels, everything in node for serving websocket apis are a toy.
Lambda functions though? yea nodejs kicks but there!
TypeScript is a pretty good language for writing web servers, as long as you don’t need to do computationally heavy parallel computing. And you can still do that, but it’s very awkward.
I’ve done plenty of backend work in all of TS, Scala, Go, Python and PHP. Scala is my personal favourite, but it’s not as practical for teams as TS or Go, which are both very productive languages, with good enough type safety and performance, that new devs can learn quickly. And I’d easily choose TS over PHP or Python for a large system.
Plus, it IS pretty nice being able to use a single language everywhere. My current company is TS RESTful services with TS/React on the web, and TS/React Native on mobile, pretty hard to beat how easy it is to do full stack dev work for most ppl in this setup.
JS has no parallel computing support, so it is not an option. And when I say parallel computing, I don't mean distributed computing, I mean utilizing hundreds (thousands) of cores on a single die, like NVIDIA architectures. (It's a black art, even addition algorithms can confuse the newcomer.)
The best course is to do what every other language does when it comes to simple-parallel operations, like Gauss-Jordan elimination: use a dedicated, optimized library, like NumPY.
I really hope some day there will be a numpy for JS. NumJS is dead, and Google's TensorFlowJS is excellent for utilizing GPUs, but a dog when trying to do simple operations (the load/store async nature doesn't quite fit with most use cases.) I suspect WebAsm will facilitate the parallel nature of tensor operations without having to move
Node does have worker threads. They’re awkward because no shared memory, lots of serialization overhead and boiler plate, but if you’ve got heavy data processing to do on say a 4-8 CPU machine, you can certainly split it up between 4-8 CPU threads.
That's process parallelism, not compute parallelism. To radically different things.
I've avoided using node worker threads in favor child.fork, which then resolves to IPC through process.on and process.send, which is like any other process management.
True, but regardless, the kind of ergonomic, low overhead parallel computing available in Scala or Go just isn’t possible in Node. In Scala or Go, parallel computing is barely anymore difficult than synchronous computing, in Node it’s quite the pain in the ass once you want to start passing objects with methods and whatnot between threads.
Close, but I don't want to have to switch memory models, e.g. upload/download. What I want is the incredibly diverse numerical computing support and logical syntax of NumPY but in the same process & memory space. The W3C endeavor is something a little different. Thanks tho!!
I do think that this kind of thing will be able to be built on top of WebGPU (I saw this experimental POC that did so recently: https://github.com/milhidaka/webgpu-blas). The only issue is that since JavaScript doesn't support operator overloading even if a production-level library was created the code would be a little less readable.
This article nails it. While Python is such an elegant language for scientific research, it falls on its face when it comes to packaged applications (and as stated in my other posts, it's awkward async support compared to Node). I realllly hope scientific computing moves into NodeJS, or, Python gets better at asyncio and cross-platform packaging.
From my perspective (mostly a Python user), Javascript is a fine language for general-purpose scripting and server dev, and Node is more than fast enough to handle typical workflows.
Why do you think it's not a good language for this?
Also, I see a lot of value in using a one single language that can truly do everything: frontend, server, and scripting.
I guess you could use Python or Ruby like that with Wasm, but I haven't seen evidence of people doing that.
Like JavaScript, one can argue that the only thing wrong with node is the ecosystem/developer community. Things like npm as just not curated enough given the large number of JavaScript developers and the attendant variability in quality of output. Node itself is an almost perfect call-back driven even loop for Unix network io, which till go and go routines/channels was the conceptually simplest way to use the CPUs you are paying for, saturate the network, and have subtle threading issues. (Python gevent was also good at that, but had more implicit magic which is bad for reasoning about code).
But I am hopeful that when I finish reading the article I will not have to reuse my jquery / d3 based framework for doing quick data viz things (which I only started doing with great reluctance because people don’t go wow over tabular data even if the data is wow-ing. The first request to make it pretty, i switched to mono space fonts. But jquery is showing its age.
I don't know what's wrong with me. I hate JavaScript. I tried learning react and redux and just gave up. All this to put a button and a field on a page. React was basically invented by John carmack to do doom 3 and copied to render web pages. Is this really required!? It's not a 3d games engine. I've worked on web apps that require a lot of page updates per minute and I still hate react. I stay the hell away from front end web Dev as it just feels like hell. Sorry drunken rant.
Edit: I also worked on a node app that should have been written in a staticall typed language. Bugs that could have been caught at compile time literally caused me utter misery in on call overtime. All because some guy in our team demanded we wrote it in node. This was way before type script. I actually feel physical pain thinking about.
You should really try learning react first without redux. Redux is for managing global state. It's rarely needed but has become the defacto solution for react state for some reason.
React on its own is much simpler, once you grok the react compositional model. I don't know how you can do that while using redux too.
Yeah, unfortunately there's been lots of folks out there who have tried to insist that Redux should be used everywhere, all the time, and ignored the guidance we've offered over the years on when it _might_ make sense to use Redux.
Perhaps give it another try, but with TypeScript. Im a front end dev and yes, I feel the JS pain. I look back at how I used to do things and think "wtf". TS completely changed this and brought it back to sanity.
I’m pretty sure the real issue is backend vs UI rather than JS/HTML. If you’ve worked with a few alternatives, the web suddenly doesn’t look too bad. Sure, a couple solutions are probably nicer, but they are mostly platform locked and way slower to develop on.
UI programming is literally the fine art of handling what your most exasperating client is capable of inflicting on your UI.
at least part of the problem is that Javascript and webdev have really low barriers to entry, which is positive in the sense that anyone can do it, but the problem is that anyone can reach that unhappy valley of knowledgeable enough to do a lot of damage without realizing it.
If you put bad developers on other languages they usually end up running into some wall first but Javascript is pretty forgiving.
"React was basically invented by John carmack to do doom 3 and copied to render web pages. "
Does anyone have any reading material on this? I've never heard it and a quick Google turned up nothing, but I'd love to read about it. Unless it's a joke that went over my head...?
> Too many people only learn JavaScript, become psychologically dependent on it, and they all collectively took it too far outside of a browser.
Do you have any evidence for this? Because there's plenty of reasons why you'd share the same code in the browser and the server. Being able to do SSR and sharing validation logic are two huge and obvious reasons. Ever try to exactly duplicate validation rules between the browser and PHP? What about when they use weird regexp rules?
I have a site builder codebase that renders previews instantly as you make changes, then uses the same code on the server to render the HTML and CSS for visitors. That would be otherwise be outright impossible to do without writing the same code again in another language.
> Being able to do SSR and sharing validation logic are two huge and obvious reasons. Ever try to exactly duplicate validation rules between the browser and PHP? What about when they use weird regexp rules?
PHP is adding support for FFI to any C ABI-compatible language, and you can run the exact same code in the browser via emscripten or a WASM polyfill. As a bonus, emscripten/WASM compiled code will also be more efficient in the browser than plain JavaScript or Typescript.
NodeJS is important for more reasons than "it's just JavaScript". It is asynchronous from the bottom-up, and it is literally a challenge to force asynchronous patterns into a synchronous ones, which is almost always a hack because async requires a lot of thought. This is a boon to IIoT control, where the pejorative "web server" is literally the endpoint for 10's of thousands of IoT edge nodes. NodeJS fits in with this architecture perfectly compared to the shoehorning required to make it work with PHP, (C/C++), Python or Java. (N.B.: I am not a java programmer, but we did review using Java, too, but it was voted down for other reasons.)
If there is another asynchronous language that is as well defined as NodeJS and has as much library support, I would very much like to study it.
This. I grew up with Lisp and Smalltalk, yeah I am that old, but today I love Node to build web apps.
It’s a fantastic environment for asynchronous programming. It also has a built-in REPL for a management interface via TCP or Unix sockets. It doesn’t really need any additional packages (I hate the dependency hell that npm saddles you with, and people don’t seem to know that Node already has http, https, and websocket upgrades built in, so you often don’t need any “frameworks” or libraries).
Give me Node, and I can build an entire web app from scratch. Most of the time you don’t even need to use JS in the browser. Just html and CSS are enough. Web apps the way God intended.
I don’t use Typescript either. Its type checking isn’t worth the hassle of poor tooling and inscrutable stack traces.
IMHO, TypeScript is only useful if you are using a build tool because it requires so much configuration. I switched to WebPack for very large Electron projects and I'm hooked on it. The syntactic sugar protects me from myself, and the importing is cleaner. I also finally made the switch to VSCode, which while bloated and awkward to configure, is pretty dang amazing when working correctly w.r.t. linting and code inspection.
Lot's of projects are popping up using ElectronJS, which is Node+Chromium. I have written many, and they are literally write-once-run-everywhere. Node serialport and node libusb have some speed issues on macOS, but require literally no alteration, utterly seamless.
The idea as "Node is just web" is dead in the water. Hugely popular ElectronJS(Node) apps are:
[FYI: Python is far, far behind in packaging cross-platform apps and requires gigabytes of support libraries. People complain about Electron size, but they are only comparing it to native apps.]
> The problem started a decade or so ago with Node.
What problem, specifically? People enjoy writing Javascript. It has a ton of fantastic resources online, it is easy to debug and deploy, it's quick to pick up and forgiving of mistakes.
> Too many people only learn JavaScript, become psychologically dependent on it
You sound like Immortan Joe warning people not to become dependent on water in Mad Max. Let people enjoy the language they enjoy developing in.
> they all collectively took it too far outside of a browser.
What does this even mean? What's "too far" even mean? People want to write code, let them?
Unbelievable that this is voted to the top on Hacker News. The comment literally gives not one concrete example or reason by JavaScript is "bad". I'd expect more from you all here.
This happens every time a Javascript topic comes up - hundreds of comments just regurgitating the same "Javascript is bad" memes. It's bad enough that's there's no real point in reading the comments on JS submissions since there's rarely discussion about the article.
I am professional who used python, Java in my Career, and TypeScript is simply the best.
“Too many people only learn JavaScript, become psychological dependent o it “ is simply a false narrative from people who are stuck with obsolete web dev tech stack and refuse to learn better tools
What makes matters worse is that javascript is being pushed as the golden standard language and replacing pseudocode. In recent years I've stumbled across multiple articles on serious topics and concepts such as complex algorithms for compression or image processing and two scrolls down and I see an implementation in javascript.
The fact that you can put a 900 bhp engine in a 40 year old rusty Citroen, doesn't make it a good idea(JavaScript being the Citroen). There's a good reason why operating systems are written in low level languages and not toy languages that are meant to make sites jiggle. JavaScript is just a convenient excuse to write slow, horrible, unreadable and unmanageable code without having people pointing it out because no one expects JavaScript to be anything other than an endless mess of spaghetti. Even in the case of space x is just a tool for shiny buttons and that's it. That still doesn't make it a good idea. Some time ago I saw in a video that the Audi entertainment system is written in typescript and as much as Audis are great cars, the entertainment system feels painfully clunky compared to a cheap 120 euro Android phone. JavaScript and node are horrible technologies that should be abolished and replaced by something that doesn't require a 14-core Xeon and 32gb of RAM to run semi-decently.
So what, is that not everyone loves it. Devs shouldn’t be forced to use a language that they hate using.
Thankfully WASM is a remedy for this, and over the next decade devs will be able to build full stack across web and mobile in Swift or any other language they prefer.
ActionScript is also an ECMAScript language, and it's kinda ridiculous to see that JS still hasn't quite caught up. Out of things that modern JS lacks, AS had Java-like interfaces and you could specify types on variables.
As someone who first learned to code with AS2/3, I agree it was quite disorienting when I first tried to make a few games with HTML5/JS.
I do think you're not giving TypeScript enough credit -- I felt right at home the first time I used TS, and the type system is much more sophisticated than anything ActionScript ever had. As long as you're of the "favor composition over inheritance" mindset, which I'd argue is better, even for games, TypeScript is a fantastic spiritual successor to ActionScript!
Unfortunately there's no TypeScript-based game engine that makes it so easy to combine code with animations / sound. Nothing has really filled the void that Flash left behind.
JavaScript does not have a monopoly in web browsers. Microsoft supported vbScript and Google made a better and faster JavaScript (Dart) which also ran natively in the browser. But neither didn't take off. You can still "compile" for the browser though, the funny thing is that a lot if not most of the code running on the most popular web sites has gone through at least one compile step. So people don't actually program in JavaScript, it has become more of a compilation target.
TypeScript and JSX are the most popular languages that compile to JavaScript as far as I know. They're very close to JavaScript because people learned straying too far created problems.
Don't do much JS, but this is actually what makes me the most sad. My formative programming years were during an era where there were many competing technologies on most given platforms.
Now days, if I do mobile iOS, I have to do Swift, Kotlin for Android, and as you say JS for browsers. I wish we lived in a world where the platform didn't design the stack so much.
The only reason I'm using node.js is because I can do this:
let num = 0;
route('/url').post(data => num++);
What other languages can I do this in that are better? I simply want to have a variable I can access and mutate from inside closures and let it live in memory without the need for databases or file systems.
I want a language where it's as natural as my example above, and normally an object or array so the integer was just to simplify the example. Do you have any suggestions?
I want to declare a variable and then be able to access/modify the same variable through a closure in a callback for incoming requests, so I guess that requires it to be single-threaded.
(I'm using this for game state where it's very convenient to just declare a persistent data structure in code directly without without having to use any additional abstraction.)
well without atomic access your state would be wrong. there are languages that allow stuff like that, but if you do it you can still have the wrong number. i.e. in c# something like you wrote is possible but when getting multiple requests, the number might be wrong at the end.
you always have some tradeoffs because in your case when you would run it with a multi threaded js engine your variable would be as broken as the c# one.
that's why java does not allow it by default to modify a variable inside a thread that is declared outside.
> Node is not ECMAScript in a server-side ECMAScript engine, it's JavaScript in a browser JavaScript engine.
Why would your custom ECMAScript server be any faster or more stable than any of the existing browser engines? If you look at the resources behind those engines, I don't know who would match that effort doing the same on the server.
My guess is the browser JS engines are optimized for quick compilation and execution. While a backend engine could optimize for longer, persist runtime.
10 years ago JavaScript was an ugly language, with its clunky prototypal inheritance and so on. Modern JavaScript is a beautiful language, however, especially when enhanced with static typing as in TypeScript. So much so, that Stanford has replaced Java with JavaScript for its introductory programming course [1].
I think there were two main reasons: choosing a popular language (JS and python happen to be among the most popular, accessible languages) and pedagogical simplicity (it's nice to avoid burdening beginners with extra syntax when they're already struggling to learn other things). Some unscientific evaluation showed that students picked up static types just fine in our second programming class (which is in C++)
Personally, I think we should be teaching static types and I pushed for Typescript, but it didn't happen.
Is there something like DefinitelyTyped for Python? TypeScript only became useful once the ecosystem reached a critical mass of type definitions available for popular libraries.
At the moment the Python community seems pretty anti-static-types, and the core scientific libraries (numpy, matplotlib, pytorch) don't export type signatures. Language server / intellisense support for type inference also has a long way to go.
I started programming in Lua which is dynamically typed. It allowed me to experience why a type system would be nice. I'm sure if I had started with a typed language, I would have written it off as antiquated and unnecessary.
> it's nice to avoid burdening beginners with extra syntax when they're already struggling to learn other things
As someone that teaches college students to program (not in a CS department) that statement is correct but doesn't provide the full picture. It's good to get rid of the extra syntax if and only if you don't need it - and that means you're intentionally limiting what you're teaching them.
Well, of course, but the point is that avoiding syntax is not a great criterion for defining the fundamentals of programming. A couple orders of magnitude more important is to decide what concepts are useful for beginning programmers to know.
I am sure I’m absolutely nowhere near your knowledge and expertise, but please bear with me sharing my opinion :)
I think Java fits better as an introductory language — it is similarly popular as JS and python, and while I’m sure static typing can be picked up easily, I think fighting the compiler for a likely-correct program in the end is a better alternative than understanding why the program failed with this given input and not with another — so my not-backed-up-by-teaching opinion is that dynamic languages are not necessarily a great fit. It also features the basic OOP concepts, and modern java can showcase plenty of FP ones as well.
On the other hand, going lower level is similarly detrimental, I’ve taken a class where C was used, and that way you get cryptic runtime errors as well, while memory management is not that hard to pick up later on.
Intro classes don’t need to overburden the student. The biggest hurdle for students is thinking like a computer. You start introducing all these extra things to just get going and it becomes even more difficult.
Explaining to students what public static void main means is pretty annoying and seeing cryptic syntax littered everywhere does not help students when they’re first learning.
Dynamic languages make much more sense to beginners because the idea of what a variable represents is more abstract to them than tangible to you. To them, they don’t see the value of types because they’re not going to be building large programs where that is going to matter. They know what their functions return and take in, because they probably only have one or two. Performance and compiling is also not as much of a concern, etc...
> Explaining to students what public static void main means is pretty annoying and seeing cryptic syntax littered everywhere does not help students when they’re first learning.
C# has solved that with "top level statements" [1]. If Java added that then problem solved, right? It's a simple addition.
C# would be a better choice. In addition to top-level statements, the standard API seems much less "dogmatically" OOP. Reading a file is just one static method away. Unfortunately, it's still not possible to have top-level functions, right?
I agree with you on the overburden part, but not on the dynamic lang part. My very minimal experience is that the hardest thing to get right as a beginner (or even as an experienced developer) is to be able to follow the flow of your code (Maybe introductory courses should employ the debugger?), and the exact state it has at a given point, eg. at an exception. Restricting the valid states imo helps understanding. As well as not having to debug at all at first, but the compiler notifying what is wrong immediately.
I think that you're right in that it's hard to compose all those parts of your program together without accidentally mistaking a `Query` for a `string`, or god knows what. I'm helping a friend learn web development, and most of the issues they get stuck for long time at are solved by making sure that functions you are calling are returning what you think they are.
On the other hand, I feel that most of the lessons I've learnt that have really stuck are the ones where I first do a thing wrong, and then find how to do it right. In a similar fashion, letting the student create a steaming pile of ... and then giving them a solution to their troubles in a later course feels like a good idea.
I personally have come a full circle: starting with things like Pascal and C++, then going to C# and finding type inference interesting, then getting a HUGE boost to my knowledge and skills when I found Python and JS. A few years later, my personal preference is having static type checking, and Typescript does that pretty well, in my opinion. However, every time I remember how much I managed to learn and understand about programming when I switched to Python, I think that if I had to teach someone, I'd pick something expressive, intuitive and who cares about types when you really want to maximize exposure.
> I think fighting the compiler for a likely-correct program in the end is a better alternative than understanding why the program failed with this given input and not with another
In my experience (having TAed a CS1 course) I think it is better for introductory students to be able to figure out what they are doing wrong, rather than having a compiler point it out to them.
In the first class, we want to focus on computational thinking and being able to then express their ideas into programs. So we intentionally use very little of the language (JS in my case), because the language is not the point of the course.
OOP and all these models of abstraction and code organisation come later, once they have a good grasp of the fundamentals.
This particular course I taught is only taken by CS freshmen, so that other commenter's remark (that we should teach a popular language) doesn't apply here.
> I think it is better for introductory students to be able to figure out what they are doing wrong, rather than having a compiler point it out to them.
That’s implying they will find it out, instead of having a finished project that can randomly crash with a slightly different input.
Also, the compiler is basically just a shorter eval loop.
But I agree with you that OOP should only come later (though using objects is inevitable in most languages)
I think wrapping all your code in OOP boilerplate is probably too much for an intro course. One of the nice things about Python is that hello world is `print("Hello world")`. No `public static void main(String[] args)`, no nothing. And then on top of that, you can add your functions and classes and whatnot, but it's easier to wrap your head around a zero-fluff entry point.
> I think Java fits better as an introductory language
Oh no, for a beginner just setting up the environment is a huge hurdle. Sun's Java downloads page is utterly confusing, and the IDEs are monstrous and complex too. Past that, they have to learn about the JVM and compiling to JARs before they can even run their first program. Leave all that housekeeping to us seasoned, soul-crushed developers ;)
If we're starting to teach compiled, boilerplate-ridden laguages to beginners, why not jump straight to C++ or Rust?
Sun’s download page?? Also, vim is more than enough for beginners and there is hardly anything hard in javac Main.java && java Main. With a modern JDK java Main.java will compile and run it in one go even. Jars are absolutely not required.
Having gone the other way (starting with JS and moving into languages like Objective C), I actually disagree. Having a solid foundation in software writing helped me when I started to learn about the somewhat obtuse abstract concepts that tend to be coupled with learning strict typing.
Then, when learning Flow and Typescript, where I'm expected to have a meta understanding of typing itself, I was ready to go.
As someone who began learning with a statically typed language then moved to a dynamically typed language, I can say that I found learning a lot simpler with a dynamic language.
I see static typing as a nice tool to help stop you making errors; but when I was trying to wrap my head around how to program I found it easier to not have to fight a compiler and allow myself to make mistakes.
Python is much more limited as an introductory language than JavaScript. JavaScript is very versatile. Need to write server-side logic? Use JavaScript and Node. Need to write a native iOS app? Use JavaScript and React Native. Need to write a command-line utility? Use JavaScript and Node again. Need to make your web page interactive? Use JavaScript in the browser. Python is versatile as well, but not to the extent of JavaScript. JavaScript, when type-checked using TypeScript also scales better to larger projects and development teams. The one area where Python shines is in machine learning, where Python is a de-facto standard. But here too, Python is facing stiff competition from Julia.
It's an introductory course. The goal isn't to train students to be able to do all those things. I'd wager most professional programmers aren't able to do more than a couple of them well. There's more to front-end/back-end/CLI/mobile than just the language.
> But here too, Python is facing stiff competition from Julia
You severely overestimate the significance of Julia in this field. It's a great language, and I wish it were more popular, but Python still dwarfs it.
Out of the use cases you mention only server-side and browser are a good fit for JavaScript, and Python does quite well on the backend. Writing mobile apps with JS is a frustrating experience at best, and requiring Node for a CLI app is not great UX, unless you bundle Node in an executable.
Students should learn early to use the right tool for the job, not reuse the same one just because it's already familiar.
IMO Python is a better first language because it's more approachable, and doesn't have the prototypal inheritance and other quirks unique to JS (not that it doesn't have quirks of its own, but most aren't important early on).
You seem to have limited visibility into python’s versatility. It’s much much more than you describe, and I’m saying that as someone who hates python with a passion (and has been gainfully employed writing python for most of my career).
Can confirm. As someone who never formally learn programming, the moment I learned Python I never touched C# or Javascript again at will.
The syntax of Python is just way, way more straightforward. I do agree it may be a disadvantage for serious software engineering, but as a hobby? I will pick Python over others all day every day.
The introductory course is not taken by just CS students. In most colleges, introductory programming courses are open to all majors. For many students this will be the only programming course they will ever take. Why wouldn't you teach a language that is not only well designed, but also versatile, instead of just being a good "teaching language"?
I think that it was beautiful 10 years ago, too, if you mainly used a subset of it, relying heavily on closures and avoiding constructors and "this" as much as possible. I think that prototypal inheritance is elegant but in any case, there was never much reason to use any inheritance syntax to begin with other than perhaps in rare cases where one wanted to really maximize performance. As for static typing, while it has its uses, the idea that it makes things more beautiful is subjective.
Arrow functions really are a great bit of syntactic sugar. I know that they are more than that, but since I avoid "this" anyway, for me they may as well just be syntactic sugar. As for the "class" keyword, I find it to be utterly pointless but of course, tastes vary.
Picking a language to teach programming and concepts in computer science presents an interesting conundrum. Do you pick a commercially relevant language (which most students want) or go with one that might be better for academic purposes? I probably lean mostly towards the former because time spent learning something like Eiffel feels somewhat wasted.
No one should have a computer science degree and not know multiple languages and multiple programming paradigms. Prolog, lisp or scheme, C, JavaScript, Haskell. The long term task of the professional software developer is to learn new stuff. Helps if your awareness of the cool things you could learn is already broad. I cannot explain how wrong it is to graduate with Java only and think that is sufficient. To be honest, I would also want people to understand the halting problem and Godel’s incompleteness theorem’s proof, as understanding the equivalence of apparent different systems that can handle the integers is very fundamental. And these days some knowledge of distributed theory is also good, the Lamport time clocks paper and so on. Unless the student is ambitious and doesn’t really like programming and just wants to program for a few years and then get into management or something like that (product? bizdev? I’d that a thing?) they will go thru many iterations of interesting new technologies. The brain that enjoys learning mind-bending shit will have a broader conceptual base and a better chance to see how lisp macro type things can help with k8s configs.
Or while lazy argument evaluation might not be in your language, having it in your tool box for message processing design or you know evaluation of user preference rule sets against an event might be helpful.
No! Eiffel should be the default OOP language for any kind of course. Being forced to think about pre- and postcoditions and invariants by the language is a really good thing for beginner programmers. While the syntax is somewhat verbose (mainly because of using keywords instead of most punctuation) Not teaching about Design by Contract is yet another billion dollar mistake in computer science. There are DbC libraries or frameworks for just about any language, but only very few programmers know about its existence, which leads to criminal underutilisation of the technique in the industry.
I can't be sure, but I think there's a lot of thought, at least, behind selecting a particular language for an introductory course on programming. I don't know which language I would choose, but I'd like something that would broaden the horizons of student as much as possible. It could be Mozart/Oz or something similar.
I have no idea, unfortunately. On the other hand, the trademark doesn't seem to be a problem to guys behind Racket, which has the most advanced contracts system out there; the canonical book for programming classes in Racket, "How to Design Programs", teaches you everything you need to know about DbC without ever mentioning the term itself, IIRC. Even if you don't want to touch Eiffel due to it being proprietary, there are many languages which support DbC you can choose from: already mentioned Racket, Ada, Clojure, Scala, D, Nim, Haxe, Elixir, and many more.
Also, there's a difference between DbC and simply using contracts - it's similar to the difference between writing tests and doing TDD. Many people might not be convinced that the benefits of DbC are worth rethinking the development process, and so they dismiss all contracts as "too many asserts, don't need". But, like with tests, you can benefit from a solid test suite even if you don't do TDD; similarly, you can reap a lot of benefits from simply ensuring that precondition violations are caught at the boundary of a subroutine, because it makes it easier to find the reason beind the problem.
I'm convinced that in the next 10-15 years we will see gradual typing (with type inference) embracing contracts as a way to extend the guarantees from compile time to runtime. Maybe we will finally get the best of all worlds: rapid prototyping, great performance, and verifiable program correctness.
On the other hand, there are concepts (closures, objects, pointers) that come more naturally with some languages, and you absolutely need to learn the concepts even if you don't end up using the language.
To me, the dilemma is between a language that's easy to learn and one that is useful once you learn the language. Most languages have too many warts and footguns to be easy to learn, but learning a toy language isn't good, either, because it's not useful.
Programming languages are tools, what matters is if they do their job. And the current popularity of javascript means it works for most people.
But boy, how ugly and inconsistent it is. I wish I could like it.
I maintain systems written in Ruby, Elixir and PHP over the years. Every server side code written by me even as old as 5 years ago, works with very little modification required for today.
But the Javascript part is the one that always causes me hours-days worth of work into Rabbit holes. And by JS, I don't necessarily refer to the language alone. It's the entire ecosystem.
Oh, `npm install`? You just found out you got like 1000+ vulnerabilities. Alright, good thing it told me actually, let me update.
BOOM! Babel doesn't support this specification in this file anymore because it's nonsensical so you have to do something else now. Ok, BOOM! Babel deprecated that now, you have to try this workaround. Oh, wait. Actually, there is no workaround. You gotta downgrade your node version.
Ok, let me downgrade. Oops, that package isn't supported anymore on this node version. Oh, you need to replace this because it's no longer maintained.
I literally never had to go though this pain with any of my Elixir backend projects.
So npm gives you warnings about vulnerabilities and that's a bad thing?
You notice you have thousands of outdated dependencies and that's a bad thing?
I used to work a lot with python years ago, and the only reasons we didn't have this problems was because the packages management was so terrible that you didn't even notice you had to update dependencies or that they had vulnerabilities.
Diff being you usually have like five python deeps for every hundred npm deps a d you can do the old school thing and subscribe to the security alerts for those deps. The difference in number of deps means you have the cognitive
space to understand them. Npm needed to automate because the numbers are too high. One of
python’s old selling points was “Batteries included”. And the idea is fewer large library rather than a bunch of tiny libraries.
With a small number of deps where you skim the development DL, you know if there is a security issue or a cool new feature you want. Also it has more of the Unix C philosophy of don’t break stable APIs in new releases. So upgrading mostly just worked. (Stuff like deliberately breaking old SSL protocols aside). (Until python 3 of course.)
Not OP but what I think they struggled with is fixing warnings.
JS projects are like a poorly built house, things are constantly deteriorating and need constant maintenance.
I've got a new nodejs project that a colleague wrote about 6 months ago. It's already completely broken and needed a lot of effort to get working again.
On the other hand his php project from 2011 still works, just as my perl stuff from 2006 still just works.
This doesn't sound foreign to me.
Node projects rely on a lot of dependencies (and so does their dependencies) so there is a lot of moving parts and it's prone to break.
I completely disagree. The TypeScript compiler allows you to specify a compile target against a version of JavaScript. That means you can write modern TypeScript and have it compile to ES3.
JavaScript is backwards compatible. What you wrote in JavaScript 10 years ago will still work today in all JavaScript engines.
Because you mentioned Babel I suspect you actually didn't use JavaScript - but a language that compiled to JavaScript. And this complicate things a lot and is probably the root cause of your wasted hours. The time you save upfront by using some framework you pay back later in maintenance once new versions are released and things get deprecated. In JavaScript itself nothing will ever get deprecated.
1: Trying to fix every vulnerability in any nested dependency is probably not what you want to do. In my experience only a tiny fraction has an attack surface and most are duplicates.
2: Webpack is a monster and updating webpack will always result in a lot of work. If possible use a well supported framework that incorporates Webpack, like Next.js or Nuxt.js. Updating will be a breeze.
3: Don't wait years before scanning for issues, update on a set schedule so it won't become a huge task once a critical issue is found.
Do elixir libraries just never deprecate stuff? Or just that their package managers never alert you about vulnerabilities so you can pretend like they don't exist and so never upgrade?
I write PHP for a living and every time I look at the JS world, I feel like they're exactly where PHP was 15 years ago, except with 20 times the amount of incomprehensible tooling.
I’ve worked with PHP and JS extensively and while I could almost agree from some narrow perspectives, I think JS is nowhere near where PHP was 15 years ago in any sense.
I was writing PHP 15 years ago. It wasn’t a great dev experience and the tooling was awful. JavaScript today has stellar tooling in comparison, and arguably less warts in its standard library than PHP still has today.
I really disliked JavaScript until I read some books that helped me understand what it’s doing under the hood. These days I just don’t have issues with it. Yeah, the ecosystem thrashes a lot and the tooling experience can be bad in regards to that, but otherwise it’s impressive lately. Even without TypeScript, intellisense on regular JS enables extremely streamlined navigation of references and implementations, refactoring, project navigation, tooling integration, etc. Not to mention modern profiling and debugging tools for JS are incredibly easy to use and benefit from.
PHP wasn’t at this stage even 10 years ago. The debugging story was still xdebug and tooling was improving but not great. Composer was painfully slow and buggy - nowhere near as nice as yarn and npm are now.
Yeah JS has problems, but I don’t believe it’s nearly as bad as old PHP.
> JavaScript today has stellar tooling in comparison, and arguably less warts in its standard library than PHP still has today.
There are a lot of reasons to like JavaScript as a language and NodeJS as a particular implementation. The standard library (or lack thereof) is absolutely not one of them as things stand today. I'm not even sure what you'd compare between them.
If you meant to say "package available at the other end of npm install" instead of "standard library" I could see that being a different story.
This may be a little off topic but your comment piqued my interest: I am currently learning JavaScript and I was wondering if you would like to recommend any of the books you read.
It’s been a while, but I really enjoyed the “You don’t know JS” series by Kyle Simpson. It explained a lot of the details I needed to understand in order to be proficient more consistently. Whether I was working on client or server side code, I felt like I understood my tools well enough to feel a lot more confident than I did before.
15 years ago, PHP didn't really support any programming paradigm very well, it was a huge untyped mess, the standard library was missing a lot of stuff, reusing code meant including individual files based on filesystem paths.
Today, PHP offers a solid OOP experience, good gradual typing, a larger and saner standard library and code loading based on namespaced components.
Now compare today's JS to PHP back in the day. It has the exact same kinds of problems. Except with modern JS, you'll end up adding TypeScript, webpack, Babel and a dozen other tools as well as several hundred megabytes of libraries to paper over all of those problems. But by doing that, you make the build process and the code that ultimately runs in a browser completely incomprehensible and undebuggable for the average developer. And then you start adding even more tooling (source maps that barely work) to try and solve that problem...
I had the impression that beside gradual typing, ES6 solved most of the mess (cleaner apis, modules) which was happening at the same time PHP (and python) accelerated their growth.
I find it really unfair to compare es6 to php 15 years ago, es6 is really cute (the babel/transpiling part is peculiar, I admit it)
I started just despising JS. But with discipline and a well-configured linter, formatter, and ideally using Typescript, I've found it to become my favourite language.
Doesn't mean I'm saying JS is inherently beautiful. But if you ignore the bad features and do a little setup, it has the potential to be wonderful.
So many people are bringing up TypeScript here as an example of how JavaScript isn't so bad. I kinda feel like that's cheating. Like saying eggs are absolutely delicious when baked into a cake - you're praising something after it has been turned into an entirely different product.
Maybe TypeScript is great, but I just don't like the idea of depending on transpilers to not suck when creating the final code, and also having to debug that transpiled code, and then the whole transpilation step in between the standard command-S-command-tab-command-R workflow (this is also why I never use SASS/LESS if I don't have to).
Once JS itself has strict typing and real classes, and enough time has passed that I can be assured 95% of people using five-year-old browsers will be able to use it, then we can talk about the wonders of JavaScript. Until then I don't get why anyone would use it (or anything that transpiles to it) when there are so many better alternatives for server-side development.
People occasionally rely on compilers. I don't really see this as much different.
At the end of the day all I care about is if I build the products and solve the problems I'm hired to do. Beyond maintainability, the "engineering" stuff is a distraction we need to be careful not to obsess over.
Well yes. But as the problem solver, there is nothing better than when someone has a problem, and you have a solution ready at hand which came from lambda calculus or distributed systems tricks or some crazy shit from On Lisp. That is why they are paying you, not to cranks out good dutiful straightforward solutions but for clever ideas that are simple to implement and operate. The engineering is both awareness and skill in following processes to get great cheap and effective solutions. Otherwise you end up with 20 million lines of
code and all the aesthetically sensitive people have have to leave the company.
Given that people are usually already using Babel, TypeScript isn't really any different than running a linter is. There's no additional transpilation step if you write your code in TS, but you can also run TypeScript to have it warn you of potential errors.
Because it's no longer the same language. You're not programming in JavaScript, you're programming in TypeScript, which happens to be compiled to something JavaScript engines accept. All the praise towards TypeScript does not necessarily apply to JavaScript. It would be like praising Assembly while you're actually programming in C.
AFAIK, the only difference between TS and JS is types. TS doesn't give you anything that's functionally different than JS -- only types that are stripped during compilation. You can't perform any logic on types at all (e.g. you can't have conditional logic based on interfaces).
With most things, yes, if the implementation for that feature supports your operating system, and it doesn't take long enough to be noticeable, and there's no weird caching issues at any given level, then yes, it's transparent in that case.
Or you could just write the JS directly and be done with it.
The code output by typescript is generally pretty readable depending on the target, and the source mapping works very well regardless. The debuggers in all major browsers and ides handle it fine.
I've not come across any bugs caused by typescript itself in the time I've been using it since 2014, and my point was that this is the same for c or any other language - how fun is it to debug assembly you only kind of wrote
This brand-new book on using Python (via Transcrypt) in the browser to build a React app may be helpful in that regard: https://pyreact.com. Just started reading it. Seems very good so far.
You can write Rust for the frontend right now. It's pretty neat.
Yew [1] is one of the early Rust frameworks for client side work. It allows for multi-threaded (!) execution and javascript interop.
Not many other languages make sense as you have to pack in the whole runtime, GC, etc. Rust is pretty well positioned for WASM, and it's going to take off soon.
I use both JS and Python for work and not a day goes by where I don't wish history had taken a different course and Python had ended up embedded in web browsers.
There was a strange time in the dark days of IE6 dominance 20 years ago that you actually could write page scripts in non-javascript languages. VBScript was a big option that some people used, and IIRC there was a way to get python support in IE (and Windows) script host too. When I was first learning Javascript in ~1998 I remember all the docs showed how to do stuff in both JS and VB script tags: https://stackoverflow.com/questions/17483782/vbscript-suppor...
> If people didn’t like JavaScript for front end work, it’s not like they could just switch to python
Sure, they can, both via compile-to-JS solutions like Transcrypt [0], and via generate-the-frontend-with-backend-Python solutions like idom [1], Plotly Dash [2], and others.
> It turns out that even if you accept "Python is great and JavaScript sucks" that "Python compiled to JavaScript" ends up even worse than JavaScript.
Clearly, there are people that disagree with this value judgement, and the existence of that disagreement is an existence proof that Python for frontend is, in fact, a choice people can make, even if it is one you find unattractive.
I also have gotten DMs on Reddit from companies looking for devs since I commented on a thread 10 years ago about an obscure toy language: it doesn't mean thats a reasonable choice for technology.
I think theres legitimate reasons to compile Python to JS, but "JS is bad" can't be one of them, since you still have JS that you have to worry about. It makes sense for codesharing with server code or preexisting business logic.
Over the years I've debugged js compiled from various languages, and it's seriously a terrible experience: however bad you think debugging handwritten js is, reading and debugging generated js is strictly worse (and you will have to)
> however crazy you think handwritten js is, generated js is just obviously worse to try to read (and you will have to)
Or...maybe I won’t; I’ve used plenty of compile-to-JS languages (including what starts as “js” with JSX and modern features but gets compiled to plain, and more widely supported, JS), and I spend as much time reading and debugging JS in its compiled form as I do reading and and debugging .NET or Python bytecode instead of source, which is none.
> That's not a solution if you end up with Javascript in the end. (
It is, just as using compile-to-(or interpreted-by-a-runtime-in-)-native-code languages is a solution to “I don’t like raw x86_64 machine code for desktop applications”, even if you end up running machine code in the end.
> Also Dash is absolutely terrible, horrible documentation, horrible code.
“X is not a choice people can make” is a different claim than “One example of X is not something I personally would recommend”.
The issue is that writing code that goes through a JS-transpiler is more complicated than just writing Javascript, unless the language you choose is Javascript-adjacent, whereas writing code that compiles to machine code is infinitely less complicated than just writing machine code.
As to your second point, that's why I put it in parentheses, of course it doesn't refute your claim but if you use as example a technology that has awful documentation because of this two-language paradigm, and leads to garbage code both at the Python stage and the Javascript stage, to me it doesn't paint a good picture of the whole concept.
Why is that not a solution? The concept of compiling/transpiling a language into the target language for the runtime is everywhere.
Even native languages like C/C++/Rust compile their language into binary format that the platform can run. It just so happens that the web runtime format is JS instead of binary machine instructions.
Can’t easily write Django code in JavaScript either. In general it’s not like working programmers get to choose any programming language whatsoever for the hardware and platform they’re writing software for.
You don't have to use Django (you can choose one of the billion alternative CMSes), but everyone has to use a browser. Hell, Django itself has to write javascript.
>If people didn’t like JavaScript for front end work, it’s not like they could just switch to python
Sure you could. You can develop for the web in practically any language you like these days. People use JavaScript because it has native support for the DOM that nothing else can match. Until we get away from the DOM for application development, it will always be king.
>That has nothing to do with Javascript's merits as a language though.
Sure it does. DOM support is built into the very core of JS as a language, and that has shaped the entire history of its' development and subsequent API choices. It's not just a library that it happens to support, the way it would be with any other language.
Yes, the language is sloppy. Like all things sloppy it’s more about knowing what not to do only after which the elegance is exposed.
That said, unfortunately, the language is much better expressing personal projects than picking up the trash in an untrained corporate environment like an over paid janitor.
let obj = {a:1},
arr = [1],
map = new Map().set("a",1);
// Iterating over an object keys
for (let x of Object.keys(obj)) {...}
// an array
for (let x of arr) {...}
// or a map?
for (let x of map) {...}
I would expect, given you have described an operation on 3 different data structures using different words, that it would also demand 3 different kinds of syntax/denotation no? Your own language requires as much. Why not JS?
Well in python by example you use for x in myobject to iterate and that's it, no Object.entries(myobj) vs. mymap.entries , lua is even more consistent, ..
Yes, indeed. It is really pleasant compared to how it was 10 years ago, and still -- code written 10 years ago, even code written 25 years ago still runs in modern browsers. It's amazing and wonderful.
JavaScript has quite effectively managed to avoid anything the Perl 6 fiasco which greatly contributed to Perl's demise, or the Python 2 => 3 timult, which turns out will not be a kiss of death, but made for some rough years. JavaScript did almost have its own trouble of the same sort with ES4, but it was very wisely abandoned when it turned out to be too ambitious/contentious...
> Yes, indeed. It is really pleasant compared to how it was 10 years ago, and still -- code written 10 years ago, even code written 25 years ago still runs in modern browsers. It's amazing and wonderful.
sadly that is not true. some stuff broke over the years. most often it was not javascript itself but changes in the dom api.
I don't actively use it but I followed it. It is actually a more modern language than pretty much anything else and it seems to have great community that is not a bunch of zealots. Also, it is far from dead.
At the same time Perl5 is also still alive and from the start, it was clear that the two will be maintained in parallel. Perl6 was not intended to replace it, they changed the name to Raku to clarify the situation.
So while it may be a fiasco if you consider the market share, it clearly isn't for the language. Perl5 doesn't really need change, and if you want to change it anyways, it would be for a whole new language, and that's exactly what happened.
I dunno. If you walked into a sophomore-level computer science lecture 15 years ago, most of the people there would either have heard of Perl or be proficient in it themselves.
Now? I'd be amazed if a single student had written a line of Perl, or ever heard of Raku.
That simply doesn't compare to where Python, Java, or even PHP are in the popular mind, IMO.
I would call that something of a fiasco, frankly. Market share is everything for a programming language. The game isn't zero-sum, but it's close; there's only so many developers with so many hours to create libraries, guides, new software.
Speaking as a long-time Perl monger (Perl5 has been 80%+ of my day job for most of the last 25 years):
Perl6 was definitely a fiasco that contributed to Perl5's demise. The active support in the ecosystem was divided between the "two Perls" and sapped the driving forces in the community.
Perl5, like any other language, needs constant maintenance and growth in order to interact with modern tools and frameworks. For example, Protobuf and gRPC only work with a particular module (Google::ProtocolBuffers::Dynamic) which requires an arcane series of dependencies.
Remember that a language is much more than just the semantics and the batteries-included libraries with the core. On the module and community side, Perl has been in free fall for the last decade.
I'd like to say it's a testament to the original design; but I can't overlook the hundreds of millions of dollars, perhaps more, that has been spent to improve the language.
It's nothing short of incredible that it is as fast as it is and as useful as it is. It shows that many hands do make light work; and money can buy that effort.
I don't have any numbers to back this up, but I'm pretty sure that between Google, Mozilla, MicroSoft, etc. more resources (both people and money) have been put towards improving JavaScript (language and performance) than any other language in the history of programming. Now I hope someone will provide numbers to show why I'm wrong.
Huge amounts of inspiration came from coffeescript. The biggest advantage of JS has often been going last and executing what is already proven to be a great idea.
I don't know if this is part of the standards but there was a backwards incompatible change in the way regex worked around firefox 73 and a bunch of sites crash in older firefox now.
Backwards compatibility is one thing. But forwards compatibility is something javascript devs have a terrible time with. The standards change fast and new features are added constantly. And unlike, say, Bash devs, javascript devs want the latest and greatest and don't care if it doesn't run on $software from 2 years ago.
Yes they do, that's the entire reason to use Babel. If there's any part of the stack where you have to go to great pains to be compatible with a wide range of completely different environments, it's the frontend. It's the dev environment that churns a lot, partly for that reason.
Bash runs on an vastly larger number of different environments yet Bash devs still manage to write forwards compatible code. It's the culture, not the language.
The Winchester House was continuously added onto by a huge construction crew for many years after the death of Mrs. Winchester’s husband. She believed her psychic who told her she had to continuously add onto the house to repent for the people killed by her family’s rifles during the civil war.
The result is a sprawling, very crazy looking house that no one would have sat down and designed upfront. I think of JavaScript as the programming language equivalent of this house.
Most programing languages old enough have that problem: C#, php, C++.
And modern js does not look crazy, it's the es5 and bellow that was a bit wacky. Typescript is much cleaner than the 3 languages I mentioned, my opinion.
I haven't done much at the level of optimization I think is going on there, and this is Evan's third iteration so I'm guessing there is a lot of insights baked into it, but dang if it's not hard to wrap your head around. Even if you check it out and use VSCode to try to figure it out.
Individual sections of code make sense. But it's like a deconstructed hamburger and you've never seen a hamburger in your life.
this is my opinion but you pick a library that clings onto an outdated programming model (markup-centric, or string-based programming as I'd like to call it), to judge modern javascript.
ES5 syntax itself has nothing particularly strange. It’s bog standard C/Java syntax. If there’s any complaints to be had, they would be the semantics of using the syntax (though maybe that’s actually what you mean). The worst feature (type coercion) was an intentional addition because many developers asked for it and Eich (to his later regret) went along.
The only other truly weird features came from twisting prototypal inheritance into something vaguely Java-ish. These actually became more convoluted with a whole extra layer of weirdness while once again trying to force traditional classes on top. Unfortunately, devs from other languages think they’re the same and they mostly work as expected right up into things fall apart (usually when the hole they’ve dug is massive).
In truth, the biggest mistake was not going with scheme. If they had, the rest would be easy from language extension to adding lower level abstractions to compiling various languages to it would all be easier.
Built-in method and class naming is wildly inconsistent. OO is bolted on, typing is bolted on. While not "the language," the GIL and what it means for parallelism (multiprocessing is a shit show) was a mistake.
To pick up on your tangent with a tangent, I think Tim Powers's take of the Winchester House mythology, in his book Earthquake Weather, is my favourite re-interpretation of the story.
As to Javascript - I like the language because it a language that fits best with my way of thinking about code. I'm not sure if that's a good thing to admit.
The very fact that your example uses a house shows this is not limited to JavaScript, or even software for that matter. A relatively famous paper "Big Ball of Mud" by Brian Foote and Joseph Yoder discusses the effect.
Seeing a lot of distain for JavaScript in here, but not enough examples of what's actually wrong with it. It's fine to criticize the language, there certainly are issues with it, but I'd like to see some actual constructive comments and examples from other languages where it's done better.
besides being really insane typing wise, javascript also both really lenient and unpredictable in what it accepts as expressions. Try to guess the result of the following expressions:
> [] + []
>
> {} + []
>
> [] + {}
>
> {} + {}
It means that if you feed it nonsense it does not stop you but happily carries on and explodes a few milliseconds later somewhere else. Another can of worms is the difference between null, 0,undefined, '', ....
Ok, you got me worked up. I need to go for a run to blow off steam.
If your statement begins with a curly brace, that brace is a code block, NOT an object literal.
Coercion rules are terrible, but they were only added to the language due to developer demands.
If you worry about zero or empty string, you’ll have problems in tons of other languages. Null vs undefined is less understandable along with the old ability to redefine undefined as it was a variable . In any case, I agree that one of the two shouldn’t exist.
Most of the complaints aren't really about the language syntax or capabilities. Aside missing proper support for integers, modern Javascript is pretty nice. The complaints mostly come from developers being forced to use either Javascript (only way in the browser), or being forced to change code because of breaking changes in libraries.
Library changes aren’t what they used to be. It was once frameworks of the month. At this point, React has been undisputed king for over half a decade. Major libraries like react, moment, lodash, express, etc all have had stable APIs for years now and aren’t any worse that any other language I’ve used.
Complaints like integers come from not studying the language and not keeping up to date.
Asm.js type directives have offered 31-bit integers for years now on all major JITs. That is slowly not working again as wasm takes over, but BigInt has been included for quite a few browser versions now.
> Complaints like integers come from not studying the language and not keeping up to date.
Perhaps, or perhaps fixing one too many bugs where someone thought floats were appropriate for all the things. Regardless, forced change, even if it is a good change, is still forced.
Comparing Javascript to other dynamic languages its comparable and indeed has some nice features - e.g. self style prototypes. If you compare it to more type safe languages like Java, C, Swift, Kotlin etc then it has major flaws. The dynamic languages are great for making little scripts or small-medium size one man projects, they fall down when you need to build something larger with lots of people and lots of code. If you include the problems of javascript with running it into the limited environment of the browser then there is much room for complaint.
I think a lot of the arguments are due to the clash of these two opposing mindsets, people who start in javascript and build things in a browser think it's great, people who build enterprise applications with typed languages disagree, often strongly.
The tooling and ecosystem are the main problems from my perspective. If you set yourself up with Kotlin + Gradle + IntelliJ you now already have all the tools you need.
Want to create/maintain a modern JS/TS stack? Well, you are going to need npm, webpack, probably babel, linters, need to understand how to setup source maps and get those working for debugging server side. etc.
It's a nightmare and it's all very fragile and that isn't even touching on the poor quality of the libraries outside of React/big ones.
Deno is definitely trying to fix that. Single executable, no node_modules, no package.json no Webpack no Babel, built in linter, formatter, bundler, Typescript compiler...
It's definitely not there yet but they have the right idea.
Yeah but I still don't see what I get from it for server side development that isn't better on the JVM...
Better JIT, real threads (also Loom coming which is better than async/await or Promises), better standard library, better library ecosystem, better profilers, better debuggers, better metrics/monitoring for the VM, better portability.
It seems to me that the core server-side JS benefit is isomorphic code on browser and server which is probably useful if your team is small enough to have the same people working on both but for companies of the size I generally work for this is rarely the case beyond maybe small fixes I might do in JS/TS.
For me personally this can't offset the absolutely gigantic difference in quality between say JS/TS and Kotlin/Java.
JavaScript is such a polarising topic and I wonder why. Browsers are not dropping support anytime soon and the ecosystem is healthier than ever. Just use it for what it is good at. And if you are wondering what that is, it is a great high level programming language that is good at glueing things together. It is obviously not universal. You won’t write operating systems with JavaScript as much as you won’t write web applications with assembler. In both cases you can try if you are mad enough.
Great programmers and hackers don’t complain about the language as it is irrelevant. They just use whatever is available to get the job done and get it done well. The more programming languages you know well the more you understand that each has advantages and disadvantages. Part of being a pro is to know what to use under what circumstances. What’s the point of comparing apples to oranges?
Finally, you will always need a scripting language with a loose type system even when you start at the low levels. Don’t be so obsessed about type safety, etc. It only shows lack of skills to keep the program model in your head. Gaming engines are scriptable for a reason. It provides different ergonomics that are useful. There are plenty of Rust, Go and Java applications that that replace scripting with ill-conceived configuration templates that resemble scripts except that they are inferior. If you are writing a complex system in Rust, v8 is a modern, expressive scripting runtime that will help you rapidly prototype. That is not say it is better than Lua or Python. It really depends what you want to achieve. But choosing the right scripting language can also drive adoption. So choose wisely!
> JavaScript is such a polarising topic and I wonder why.
If you ask me, the reasons are quite uncomfortable; and has parallels to how a lot of prejudice is seen in society when upward mobility happens. JS now encroaches server-side jobs, while earlier it was relegated to the browser. JS can do scripting. JS can now do native phone apps quite well. It can be used in desktop apps. It also pays well.
> JavaScript is such a polarising topic and I wonder why
Probably because it's a gatekeeper language - in order to run code in a browser, you have to use this language[1]. That means a lot of developers that dislike it enough that they would switch to another language if they could, are stuck with it because they need to target the browser. This "captive audience" is effectively forced to engage with the things they dislike on a daily basis - at that point you either develop Stockholm syndrome, or the resentment grows into hatred. Thus the "warts" that JavaScript has (by nature of having been thrown together in a couple weeks originally, and being iteratively turned into a "real" language over the following decades) have a chance to cause much stronger negative feelings than they would if people could just switch to something they liked more.
[1] I know, I know, WebAssembly may change this, and there are already niche alternatives like Scala.js, ClojureScript, Blazor and Reason - but for the most part, you still can't effectively run things in a browser without knowing JavaScript, even if just for debugging
All good things start small and evolve. The C programming language was created over the weekend if I am not mistaken and look how much it stuck for better or worse. JavaScript was also accidental. There was a time you could program web sites in VisualBasic, ActiveX, Java, Silverlight and Flash. They are now all gone. There is no denying that the JavaScript language is resilient. It stuck for better or worse.
Developers can choose to program in whichever language they want but only JavaScript is officially supported on the browser. Any other language will require a transpiler or compiler (when it comes to WASM). Similarly you can program iOS and Android apps in whichever language you like but only Objective-C/Swift and Java are officially supported. All other languages you need to support yourself. The official spoken language in UK is English whether you like it or not. You are free to speak any other language you want but social frameworks and civil services evolve around a single language.
If developers are so smart how come we cannot understand these basic principles?
My argument on why it's polarizing is largely historical. Javascript was a hot mess for decades. I stepped away from web design for a while simply because accomplishing anything meaningful in js always felt like a hacky mess to me. At some point, getting anything done required learning new frameworks getting obsoleted within a year or so (jquery?).
It's a reputation that's hard to shed.
Last year I finally started to dabble in Node. Though I fully understand the criticisms of Node, learning it really did open my eyes on just how far js has advanced. I'm really loving the present state of js callbacks/anonymous functions, leading to elegant solutions that I now miss when going back to Python.
I'm sure there are many other factors that play into this (just look at Gary Bernhardt's "WAT" talk), but essentially, I agree that this has to be a big part of the problem. If you've been developing backend systems and asked to hold up robustness and stability guarantees for multiple years and then run into Javascript, you will likely run into situations where you have to make up for its deficiencies in that regard.
That doesn't make it a bad language per se -- that's the case with any language in some aspects -- but since JS will be a new language to you, you're much less likely to accept that situation as a given.
"Gaming engines are scriptable for a reason" - I'm sure I've heard the opposite opinion from respectable sources at least 2 times. Here's Jonathan Blow
https://www.youtube.com/watch?v=y2Wmz15aXk0
I agree with the rest wholeheartedly.
I've been dabbling in javascript the past couple of days and since I already know how to program it is has been sooo easy and quick to get up and running. The tooling for web dev also feels better than what I personally have experienced doing things natively. Are there things that I don't like about JavaScript? Sure. For example. The behavior of the "==" operator freaks me out and I would always use "===" instead. But my programming experience helps me evaluate the subset of JavaScript that I need and that won't cause me too much grief in the long run. And while this is changing, there is something really nice about being able to get by in just HTML/CSS and JavaScript. Sure there are different frameworks you have to learn and they change a lot, but I'd take that over having to learn an entirely new programming language just to work on a specific domain any day (I say as I learn an entirely new programming language to work in the web).
I am naive to doing any professional web development, but from what I have seen, it seems like having to handle the idiosyncrasies of the four major browsers is a lot less effort than having to handle the 4 major operating systems though I could be wrong.
It's building on top of something that developers should be using anyway; or at least have familiarity with. I'm quite glad they ended up going this route for that reason.
Confirmed. Every time I convert an old Node project to promises I constantly find bugs and situation that were just lost in the hell. The result is also so much cleaner that sometimes you realize you were doing something wrong entirely and you scrap the whole thing. No other JavaScript improvement comes close. Everything else is nice but only saves a few chars at most.
And they announced promises like a big improvement over callbacks :D Now that was hell! Fortunately, when I started doing serious Node.js development, callbacks were already on the way out.
For me too. Only thing I sometimes struggle with, is figuring out how to place error catches.
Wrap each async functions body in a try catch? Or always attach a catch handler to the calling function? But what if I forget to do that?
Should the caller or the callee handle the errors or can both?
I'm years behind on Javascript (I'm circa 'AJAX is new' in my knowledge) but I've been having good luck catching up using the Babel REPL with small snippets to just see how the new features get translated into the Javascript I know. Seeing what the compiler renames is a good way to understand the new scoping rules, etc.
It's been especially helpful for yield and async/await, but I wonder if there's a bug in Babel with async/await. Just using the code sample from the article:
function fetchUserName() {
return new Promise(resolve => setTimeout(resolve, 500))
}
async function withAsync() {
print("withAsync: fetching...")
await fetchUserName()
print("withAsync: done")
}
await withAsync()
when I set the target to be 'ie 6', so hopefully I get output that's only the Javascript that I know, most of this gets translated to (a lot of) Javascript that looks normal for 2005 Javascript - except the last 'await' line is still there. Is that a bug/limitation in Babel or was 'await' present in Javascript from years ago?
I don't know what the REPL you're running does with top level functions, but my guess is that an `await` needs to run within a function that is declared `async`. The reason (if so) would be that then babel could then transpile the function appropriately into a Promisory function. At the top level, what function would be translated?
Top-level await is very, very new and requires ES modules -- you can only use this feature without warnings recently in Node 15. For the foreseeable future, the final line should be replaced with:
You're right, thank you for the explanation.
My REPL runs the code in the textarea in an anonymous Async function, which is why top level async works in my examples.
Some other important features and browser APIs released in the last ~10 years: Web Workers, WebGL, OffscreenCanvas, Typed Arrays, Web Audio, Web Notifications, WebRTC, Websockets.
There's a lot to like in modern Javascript, pretty much everything in the list I appreciate.
The only thing I wish was never added is the new Array Functions, I mean, ok they are "handy" sometimes, but they seem to get abused heavily. Newbies like stringing them together and even nesting them, when they could have achieved the same with a single for loop and the same number of lines. In other words they seem to encourage people to artificially increase the complexity of a problem without any objective improvement in legibility, not to mention lots of GC work with throw away arrays... many people don't seem to even be conscious that under the hood of most of the array functions is just another iterator of some kind.
Newbies aren't the only ones stringing them together and nesting them, even seniors like me are...to great effect, increased readability and are safer than potentially dangerous mutations.
I teach all my reports to lean heavily into the new array functions because, if wielded correctly, are much more powerful than using for loops while using less code.
The big problem with them is that they are naive. If you string 10 of them together, you will iterate the array 10 times and generate 10 garbage arrays.
Lodash and similar libraries are much better in this regard as they tend to use iterators internally which don't generate all the extra garbage and don't iterate multiple times. Because they don't have to handle all the weird edge cases, they tend to also execute faster too.
This is the most missused phrase of all. We are not talking about optimisation here, we are talking about _not_ writing slow code, there is a huge difference. Optimisation tends to add complexity with a trade off.
I’ve always heard premature optimization used to refer to convoluted, harder to use and understand techniques that trade lots of developer time for extra performance.
In this case, we’re talking about a single import and almost identical API while also gaining access to tons of additional and more advanced functions that save time too. It hardly seems comparable.
That is a valid opinion, I agree there are advantages to plain for loops. However, it is not a universal opinion and I would argue against the for-loop, sometimes. Some languages people love do not even have loops.
You never know what structure a for-loop will take, it could break early, skip items, build a new data structure, mutate a data structure, or all the above. If I see a map and a filter, I know exactly what each does.
I don't want to argue over which is better. Pros and cons. I just wanted to say that chaining and nesting array functions is not a reliable sign that someone is a "newbie", maybe they're just someone with different preferences.
A for loop is an imperative construct and can be used to do literally anything. One has to read on into the body of the loop to understand what's going on. Worse, there could be a bug and now you have no idea what the programmer intended. Array.map, on the other hand, only does one thing: turns an array into another array. The intention is clear. It makes a program much easier to understand.
In javascript, what prevents the body of the map function from doing arbitrary stuff? Don't you have to read that to know for sure, just like a for loop?
In some languages the map function may be restricted to not have side effects, in which case I'd agree, but not javascript, correct?
This is correct, but there are some guarantees such as the result will be an array of the same length, mapping function will be called for each element, function itself can be more easily tested in isolation and there are no imperative constructs (creating accumulator array outside of the scope, tracking the index, pushing to the accumulator array)
This lends itself very nicely to functional programming (especially with typescript IMHO)
There is nothing more clear than code as a way to communicate, at least for me. My writing in English obviously could be better but easier just to show what I mean.
Many array looping functions have been around since ES5 and I've been personally replacing them to for-of loops with very few exceptions (.map() and .filter() remain handy)
Useful fresh additions are .find() and .includes()
As a standalone idea yes, however in practice this is not actually the case [0], mostly due to those methods having a number of extra checks, more functionality built into them etc.
Fair point, although as the answer states, it depends on use cases. Working with small datasets the performance difference is negligible, but with decently large datasets (~1-100mb) and nested loops the delta is night and day.
I just wish those methods were available on iterators (and return iterators when called on arrays) and a collect method that creates a new array (a bit like Java). That would reduce the overhead and keep the advantages of this functional style.
As someone who works in a few languages I find the array methods really handy as they work similarly. It's usually a bit clearer to me what the programmer's intention was with them rather than a straight for loop.
Sure if your entire program is only one loop that iterates over 100 things that fit in an L1 cache.
If you write an entire program with this thinking, a significant program, each of those "negligible performance hits" will usually add up to a poorly performing program. Back in the day people called "optimising" the application of clever algorithms and tricks to squeeze more out of a computer, today we call it ripping all the shitty slow code out of programs because devs couldn't be arsed to write things properly because "computers are fast". </ yes it's a rant, it's why lots of stuff sucks, make nice things pleeease
It's nice to see JS improving, honestly all this improvement primarily makes searching for how to do something a lot easier. Now instead of copying and pasting 15 lines to, for example, handle async calls from Stackoverflow you copy three lines. I think learning new methods to do stuff in languages isn't relevant anymore when most web programming involves googling anyway. The only problem is sometimes answers on SO are outdated and even the most voted answer may be giving a suboptimal solution. This is something both Google and SO should have a huge incentive to fix.
I'm saddened JavaScript adopted "classes" rather than improving support for prototypical inheritance. For a dynamic language, prototypical inheritance exemplifies beauty and simplicity. Unfortunately, JavaScript's execution of prototypes was poor and, given the languages popularity and that it is/was most developers first and only exposure to prototypes, it has left the engineering world with a bad impression.
I didn't know JS had `??` for a nil coalescing operator, or, more specifically, I thought it already had `||` for that purpose, since I've been using it for that for a decade or so without any problems. How do the two differ?
?? only coalesces nullish values (hence the name), which only includes null and undefined. || coalesces falsey values, which include false, 0, and empty strings. || might work most of the time, but it requires extra checks when falsey values are valid.
I love articles like this. I largely transitioned from obj-c/Swift/Kotlin mobile app dev to “modern”JS via Babel/Flow/webpack and now TS. I love it. I love the control of building my own language.
As a JS hater, I have to admit it was a pleasant read.
I would still love a "20 mistakes you need to avoid when writing JS".
One of the most horrible "WHAT IS HAPPENING HERE?" moment in JS was when there was a missing semicolon after some multiline code and error messages were not helping at all. I'm wondering if JS compilers will have some linter or will one day help beginners be warned of "possible mistakes".
Isn't there a list of "good practices" or "js coding standards"?
Because errors dude to missing semicolon will happen so rarely, people skip them for various reasons, but the fix for these errors are to use semicolon, or a tool that will tell you where a semicolon would change the "abstract syntax tree" (AST). Because the JS ecosystem is so diverse, there are many "best practices". And the languages itself has many, many ways to do the same thing, espcially with ES6/2015 onward you have many more options, which are mostly picked by personal preferences and synthetic reasons.
JavaScript has grown a lot in the last 10 years, the last ~5 in particular with ES5/ES6.
There are still “fucking JavaScript” moments but those are few and far between compared to what they used to be. The “...” operator in particular has been hyper useful for neatly modifying complex objects without turning into spaghetti code.
SPA+node/express is a pretty solid stack these days because of these improvements. I no longer find myself missing Rails for Ruby’s syntactic sugar and knowing that operations on the server will work exactly the same on the client has been great for browser console debug sessions.
The holy grail would be for HPC JavaScript libraries to allow the same ease of implementation to use something like NVIDIA RAPIDS (especially RAPIDS itself) as easily as we get with Python. Given how far js has come, I don’t think that’s an unrealistic proposition.
Adding existing c libraries to python is trivial, and very C like experience for memory management etc. adding existing C libraries into node engine requires more skill and delicacy due to the C++ and the relatively more complicated v8 way of doing things.
Looking forward to the next article 10 years from now. Will code written now be incomprehensible then?
One thing seems clear: We won't be using webpack, react or any other current tool.
I'm not sure how organization can shoulder the costs associated with that kind of churn.
They are not needed for proper HTML. <html>, <head> and <body> are all defined as having optional start tags and end tags. It’s perfectly valid and reasonable to skip their start tags if you’re not putting any attributes on them. (I always skip <head> and <body>, but never skip <html> because I always have a lang attribute on it, and sometimes more, such as a class attribute. But I definitely still skip its end tag.)
There’s plenty of precedent for habitually skipping start tags in the HTML syntax. Few people write <tbody> if they are doing a simple table with no <thead>, because <tbody>’s start and end tags are both optional. <html>, <head> and <body> are the same.
(I’m spelling out “in the HTML syntax” here, because if you’re using the XML syntax—not common, but not unknown—no start or end tags are optional; if you write <table><tr>…</tr></table> in an XML syntax HTML document, you will get an invalid HTML document that lacks the <tbody> element.)
Great resource, I'd missed a few goodies. https://javascript.info is similarly good in teaching modern Javascript.
I wish there was such a resource for modern C++ though. I learned and used C++ in the 90s and early 2000s, and apparently the language has progressed a lot meanwhile. People say idiomatic modern C++ (C++14/17/20) can be pleasant and metaprogramming capabilities are really powerful.
> Using const implies that the value will not change as the reference is immutable. Use let if the value will change.
Lol, I love modern JS, but that’s factually wrong. Const means the variable cannot be reassigned in the same scope. It is 100% mutable though. It “implies” nothing. Indeed, one of the few good uses of const (it’s basically useless most of the time) is Vue’s composition API, where you want to prevent rebinding but actively mutate.
The wording around the value 'changing' is a bit ambiguous, but otherwise you're basically agreeing with them: the reference is immutable (not the referenced data).
Cool, but as someone who does mainly backend and only rarely tries to do some FE myself (because, come on, you are supposed to be at least somewhat full-stack!), I feel like what I actually missed over the last 10 years is the current consensus on go-to tools/frameworks/libraries, both JS and CSS. Some "best practices 2021" tutorial would be way more valuable to me, but somehow I can never find one.
If someone can explain to me one thing I still do not grasp about react, even though I have done some small websites and apps in react. I understand the virtual Dom concept and only refreshing the necessary DOM components.
But how is that much different than an ajax update?
I understand ajax causes a request or more, but it only refreshes part of the DOM, right? Or does it cause a full re flow/paint?
AJAX (Asynchronous Javascript and XML) is purely orthogonal to DOM updates. An AJAX request is just a network request initiated asynchronously via some Javascript on the page, as opposed to a request initiated synchronously when a user clicks a link or submits a form. Response data from an AJAX request could be used to make a direct DOM mutation, update React state, log to the console, or anything else the developer wants.
AJAX does not update the DOM at all. You have to write some JS to mutate the DOM based on the response data, which is one of the things React is good at.
Great writeup, these new features are a godsend for JS developers.
That said, on some level it's all just lipstick on a pig. I just want a type-safe strongly-typed language in the browser. Maybe Java, Kotlin, Scala, etc. Mark my words: Someone will make a browser where a Java VM is a first- citizen like the JavaScript VM is, and people will start writing apps specifically for that browser.
Repeat after me: Semicolons are not optional in JavaScript.
ASI is an error correction mechanism, not a language feature. You can also do things like not using the var keyword when declaring variables or something like a = 2 < "4"; and it'll work fine. But you don't because they're all errors.
Try using Array.from(arrayish).forEach() to convert the thing that looks like an array to an actual array. For instance, you can't use map() on a NodeList (document.querySelectorAll returns a NodeList), so you have to use Array.from(NodeList) to first convert it to an array.
Good point. I don't think I've run into many non-iterable arraylikes, but I understand they used to be more common (e.g., a number of standard things that are now specced as iterable arraylikes used to be just the latter) and there’s probably a lot lurking in library/legacy code.
Someone already commented that you can use `[...iterable]` to convert any iterable into an array, but if you're doing this just to call forEach on it then it's probably better to use for-of in order to avoid allocating an additional array:
for (const item of iterable) {
// do forEach stuff here
}
I hated on JS a lot when I was writing.NET until I tried it. After some love-hate moments I really respect the genesis of the language and the use in the modern Web Development.
Helpful article. Since I’ve avoided directly coding in JS for a while: So getters and setters add complexity and ambiguity to avoid typing “()”? Did I get that right?
Is there any chance javascript will get comprehensions (array, set, map, generator)? I know there was a proposal a few years ago that didn't go forwards.
Apart from the arguable syntactic attractions, does it not bother people that chained maps/filters traverse the iterable multiple times, whereas comprehensions would give the language a chance to compile a complex comprehension down to a single traversal?
They need to add iterator versions of the built-ins. At that point, not only this, but a ton of other efficiency issues go away. At present, chaining lodash functions together will integrate once, so I’d recommend using them to save time and memory.
I love how JavaScript has become the lingua Franca of the browser world but there are some things that JavaScript allows the others languages don’t allow.
Absolutely, unless you’re using node or library functions that require callbacks. Even then there is usually a non-callback-based alternative or you can wrap in a promise to use async/await.
Js optimizes for the wrong thing. Writing code quickly. It's unmaintainable if you walk away from it for a year. Try doing a what you missed in 10 years for go. Lol.
Dude. 5 different ways to handle asynchrony and zero consensus on which is best. A dynamic type system that contains errors like "null is null or not an object". A number system that consists of entirely of floats. Var let const. hoisting. Classes that are sugar on top of prototypes. Classes intermixed with prototypes. The fact that typescript exists says so much.
I think of javascript like perl. It makes things work where you need it but god I don't want to work on a codebase of more than a few files.
I'm so disapointed by the committee.
So many utterly useless or easily bootstrappable features and yet, no pattern matching and pipeline operator stage 3 proposals. 0 progress for so many years.
Lack of those roadblocks Typescript implementations.
ReasonML and KotlinJS will faster become practical general purpose web languages than committee would start doing something usefull.
It took 6 years to ship ES6. We've now had a new spec iteration from every year after 2015. They are moving much, much faster and, having lived through ES5 to much pain and angst, I'm completely ok with them taking their time shipping these (very nice to have) features.
First of all Typescript, is now more mainstream JS dialect than vanilla-js itself and, honestly, the only one i care about.
And i thought it's kind of obvious for anyone, that until *JS* proposals are staged far enough - Javascript won't have those features too. There is a good reason why TS waits for the stage 3.