This is not to say that JS is shit but both JS and Rails have their place. If you want flexibility, you need JS. If you want iteration speed and dev productivity you need Rails.
From this hot take on JS, I'd think people are suggesting that the development experience of all the other available clients are a lot better, but then I became an Android and iOS developer and that's not true either.
Swift isn't bad, but the language isn't the only thing that dictates how hard client development is. I'd rather use React than UIKit abstractions, that's for sure. And CoreData is probably the worst and most outdated abstraction I've used across all platforms. And even if I think iOS development is the ideal way to write software... it only runs on iPhones and iPads.
I mean, of course the Rails side of your application is probably nicer than the client side where you get to stay in your simple request -> response realm that runs on the same machine. If given the option, I bet almost every HNer would rather be the person paid the same to build the API endpoints vs the crapshoot that is client and UI development.
But I see this perpetually confused as Javascript vs <my favorite language I use on the server>. For example, Ruby fares pretty poorly against Node if you forget the client, like Sinatra vs Express/Koa.
When you make a jump to a JS stack (whether client side or server side) you have a lot of options but no best practices or conventions to follow. You have to make a lot of choices which have already been made for you in RoR. Even though SPA frontend dev has settled between React and Vue, you still have to make a lot of decisions. React also bills itself as a view library. You have to make decisions about state management (if needed), routing etc etc. A vast chunk of these decisions are made for you in RoR so that you just work on the app. I think this is what the author was lamenting about.
If the platform is too unopinionated you will generally wind up with: 1) A project with many competing ideas (most js projects I see end up like this) Or 2) A team with some people feeling like they are not heard
These days I prefer building something up from microframeworks and I like to take the opposite side of the trade-offs you mention in your comment. There are a lot of aspects of Rails I ended up really disliking over time.
But at the same time, I still find myself thinking back to some of the pleasantries that Rails gives you and wishing I had them in my bespoke applications. Even just things like being able to enumerate your routes from the CLI or seeing your SQL queries and query response time in the terminal during development. If it's something you have to implement yourself, you just tend to not do it at all. And there's a lot a framework can do for you with some opinionatedness.
I think the classic example of this realization is when you deep dive on microframeworks, accumulate them in production, and encounter things like performance issues but realize you don't even have the tools to debug them because you didn't build them.
js and ruby were released in 1995, with rails coming 10 years later. so js development wasn’t fast in the least. after the little ajax blip resulting from outlook web access’s release in 98, js stagnated until node came along and made it interesting again.
prototype/jquery a little before it and later front-end frameworks like backbone, ember and then angular helped cement js as a thing. it only seems fast and wild because the ecosystem really only woke up again in the 2010s.
(i tooled around with js on netscape right after it came out but then lost interest)
while gmail brought a nicer ui/ux, i still credit ms owa for showing the world what js could be when it grew up.
Not true at all. Rails can be extremely flexible; it's all modular and you can reduce it down to almost nothing if you want. Javascript's only place is to run in the browser; it lost its way once people decided to make a server platform out of it. JS is far too forgiving of mistakes to be running backend code, full stop. ES6 and up are vast improvements but the damage has already been done.
And in any case I have yet to work in an environment where I am not writing at least some ES5...
For me, the more interesting question in all of this is where did this fervour for JS-and-the-way-down actually come from?
My hypothesis is that it's the natural result of a huge mess of new talent - fresh out of various overpriced Bootcamps and told that their 9-week educations give them a credible opinion in true post-modernist fashion - all being released on the world at the precise moment that a predictable police lineup of over-promised technologies were all at the top of their respective hype cycles.
Humans have a predictable tendency to assume that the thing they are thinking about at the moment is far more important than it actually is. If you have a very short institutional memory and everyone you know in your bubble has been programming for a relatively short period of time, pretty soon you can start to believe that if everyone is doing it, you couldn't all be wrong.
This community is full of experienced professionals who use Javascript even in the face of alternative options, and we belabor this topic every day.
So what excuse do you have for assuming and hypothesizing that everyone must be an unenlightened boot camp amateur when you could've turned to anyone and simply asked?
For example, to me, modern JS is not substantially worse than other dynamically typed languages. Give me Python and Ruby code and the Javascript version probably looks the exact same. Meanwhile, those languages don't have a 1:1 version of `results = await Promise.map(urls, (url) => crawl(url), { concurrency: 8 })`. And that's not to start a language war but rather to demonstrate a concise example of a technical strength, aka a purely technical ground that a craftsperson could reach for that tool.
But now fold in its advantages like ubiquity, async-everything, runs natively in the browser, and has a static-typing system that's actually catching on, and it should be pretty obvious why someone could pick it when given an option beyond "they don't know any better."
Also, there's the obvious trade-off of treating your server as the API for all of your clients and treating the web as just another client that runs on the user's device instead of essentially coupling it with the server.
But surely these things are obvious or easy to find out, so it's hard to assume good faith in your post.
Concurrency in this situation almost becomes free at the expense of changing
user = db.findUser(42)
to user = await db.findUser(42)
So when writing programs where you want more than one I/O thing to be happening at a time whether it's network requests or a bunch of concurrent workers, which is pretty much why you'd use Node, you get it trivially.Even something like running parallel DB queries trivially inside an Express route:
const [a, b] = Promise.all([db.findUser(42), db.somethingElse()])
Or starting one async early, waiting on another, and then ensuring that the first async thing is done later on: const a = runA() // returns a promise
const b = await runB()
return [a, await b]
And once again I think this is the a great example of a useful abstraction when writing anything with an I/O boundary: const results = await all(urls, url => crawler(url), { concurrency: 8 })
That code in Go would take me 40 lines and involve wait groups.Compare that to Netty or trying to write async code in Rust where it's really easy to block the event loop because all libraries and stdlib are sync by default. So you're passing around a CPU pool to run sync code inside your async context. It's hard to look at that sort of code and understand its runtime behavior. Oops, you accidentally blocked. Oops, the pool gets saturated immediately and starts blocking. It's hard to straddle both worlds, and the code is constantly trying to "return to its sync default" so you have to be eternally vigilant. Sync isn't necessarily the default you want, either.
Of course, this comes with other expenses like needing to run one process per core and you can't do CPU-bound work in-process. But you may be used to that limitation using Ruby or Python for example.
I'm not trying to start a language war or tell you that you should drop what you're doing to use Node because it's The Best.
What I'm responding to is this idea that you couldn't possibly have a technical reason to use Node given a choice unless you're fresh out of a boot camp and know no better.
However, you are (perhaps unintentionally) twisting my words. I brought up bootcamps because I can demonstrate a strong causal association on a timeline.
The beef, such as it is, is with the 750k npm packages, the brutal moving target that is the packaging/transpiling/dependency hell/OCD bikeshedding that comes with a commitment to the JS ecosystem. And given that you used to be a Rails user, you know full well what giving up sane defaults in favour of the pursuit of pure compositional bliss looks like, but you're choosing to forget the trauma.
Meanwhile, there's an entire generation of new devs that have been told that Rails (or your favourite server side alternative) have been eclipsed by better thinking. I don't think I'm just an angry old man screaming at cars from my porch when I call bullshit.
I assume you meant to instead draw a distinction between a large framework like Rails and a tiny one like Sinatra. And I'd say that ranges from a matter of taste to the composition of your team more than anything else. Obviously there are upsides and downsides to any point you can mark on the continuum.
But you're right that I made an invalid comparison to React. It's more the starting with Node and having to add a bunch of functionality that you would get out of the box in Rails, because a front-end framework like React is the preference, and lots of developers would rather write isomorphic apps/sites.
Meanwhile, there was once upon a time a perceived crisis of junior talent which led to the creation of the first code bootcamps, all of which were taught Rails, jQuery and Sass. I'm not trying to be shitty, classist or ageist in suggesting that the bootcamp phenomena suddenly started emitting a large number of blank-slate new devs that would understandably treat every exciting idea as the most incredible thing since <insert your fav noun>. After all, if you have few previous experiences, what can you compare against?
Previous generations of devs learned predominantly through either auto-didactic persistence or academic lectures; this new crop was suddenly predominantly learning from (and influencing) each other.
I recently read an excellent book called The Death of Truth, which technically has nothing to do with programming... except that in this conversation, it's totally about programming. If every coder's ideas are treated as equally valid truths even though there exists a massive gulf between their relative experiences, then we're confusing feelings with good engineering.
For me, the most compelling example of progress coming from the JS camp was my shallow investigation of the Expo platform for React Native. It has some genuinely sexy developer ergonomics features which I'd love to see make their way back into Rails.
Hartl is great, has his/its place etc. Sometimes you just need a smart person with experience to add personal context. Happy to be of service.
It's not perfect by any means, but I think it shows the shape of things to come.
This week I’ve been porting one of my Spring Boot apps to Kotlin and that was a great experience.
The only thing I’m waiting for is good reactive drivers for Postgres and then you can go with their new reactor based apis instead of the older one-thread per request Spring MVC.
Some API's are adapted to take advantage of modern Java features like for example JPA repositories that can return Optional<T> for single row queries and Stream<T> for multi row queries. Some API's have been improved with functional equivalents.
If you combine this with Kotlin you get all the power of the Spring framework together with excellent nullability checks and modern language features that Kotlin brings to the table.
https://github.com/ChangJoo-Park/amber-realworld-example-app...
(I couldn't find any code snippets on the official Amber framework page, I hope this is representative.)
We had a discussion about Ruby's type annotations 4 years ago at https://news.ycombinator.com/item?id=9481186
I found it by googling the status of the work on Ruby 3 type annotations. The top comment is mine and I still agree with the past myself.
I'd be really interested in a typescript like superset of ruby, and I've even thought about building a prototype of it, though it's quite outside my area of expertise.
But I don't know why you'd say that. ActiveRecord models are one of the main places you'll see a bunch of `use SomeGem::Thing` that introduce a bunch of magic methods on model instances.
And my point is that we aren't talking about method composition here that you can statically analyze with a bolted-on type system. Ruby's metaprogramming runs so deep that it's a substantially bigger challenge than other dynamically-typed languages.
One clue is that humans even have a hard time with it. The first shock that people have with Ruby is when you see a method or identifier and grep shows up with zero results.
Aside, I can kinda tell that Ruby is entering Perl territory when there are no beginners around to chime in with their gripes.
Stripe have been working on a type-checker. No idea when they're going to release it to the public though.
(but yeah, ActionCable was a no-go. We use Pusher instead)
I work on a hybrid React-on-Rails application and working on the React portions is so. fucking. painful. Seriously the shit people come up with with this "tool" makes corporate-hack Java programmers look good. I am always taking the backend Rails-y tickets if I have the chance