Comments like this are what make it difficult for me to take HN seriously anymore. It's just an example of the hivemind at work, assume that an entire industry has the same ideas as you about what technology to use.
The Node/JS ecosystems are experiencing a Cambrian explosion in technology, with all that implies. If you don't like it, don't worry. It probably won't take 20 million years this time to settle in on the "best" ways of doing things.
Most of the developers where I am are running OS X, which is significantly more similar to our Linux production environments than is Windows and yet we determined that it was just easier to always run our node applications on Linux guest VMs. On Windows, I wouldn't even have the gall to try to make it work without this kind of setup.
You need to install the proper prereqs for node-gyp, but those are clearly explained on the node-gyp docs.
It still didn't work until I stumbled upon the --msvs_version flag for npm i. And this is for a dependency in mongodb!
Python 2.x is the bigger oddity to me... seems like python's role with gyp should be replaced with something self-bootstrapped at this point.
"Run anywhere" is really only descriptive of languages (e.g. Java), not implementations (e.g. Dalvik). You can't have a "run anywhere" implementation, unless you are grouping a bunch of implementations together...one for ARM, one for x86, one for FreeBSD, one for Windows, one for Minecraft, etc... because even under the same name the implementations would very significantly internally.
"Run anywhere" is a function of (1) the language spec (i.e. how much machine dependent behavior is permitted) and (2) the actual real-world support across platforms.
JS has the first, but the second is often conceeded, per the earlier comment.
We keep our dependencies up-to-date by occasionally running "npm outdated", checking the packages for their Changelog.md (or equivalent) and then enjoying the new stuff.
From my perspective you were just unlucky with your packages, or you might be doing something else wrong.
I spend about equal parts of my development time between OSX, Linux and Windows... they all have had pain points for me. The only difference is in OSX dev you're likely to have XCode & homebrew. In windows, you may have VS, and probably won't have Python ^2.7.0 installed.
Part of why I've at least participated enough to raise a possible bit of help with the situation[1]. There are times when all you can reasonably do is raise the issue, and suggested fix... there are others where you should proactively fix it.
Node/npm's community is very open-source driven, and very diverse. I don't liken it as much worse than any other platform, and far better than most.
For some of these core tools, authors explicitly state that windows is a second class citizen. It's just not worth the expense to support something that has so few comparative users, in some cases (ruby). It's a lot of work for something that will never feel "native".
I don't think node on Windows is so bad these days once you've got Python 2.x and VS 2015 Community installed... When I started with node (0.6-0.8 era), it was pretty bad in Windows. These days most popular modules just work, or work once you have gyp prereq's installed.
So I installed Ubuntu Server (latest) in a Virtual Machine via Hyper-V... set it to auto-boot.. setup OpenSSH, setup Samba ... I kind of just muddled through it, to be honest.. after that, I setup Docker, build-essentials and nvm, which covered my needs there.
On the windows side, I use Clover as an explorer replacement (file explorer, not the desktop), and use ConEmu for tabbed shell interfaces. It works pretty well for me. I use GUI stuff in windows, and the linux side via SSH.
We have apps that are stable and have been running for many months, until suddenly we need to add a small feature. With a missing package deep in the tree — not one we were depending on directly — we have to waste several hours being forced to upgrade packages to newer versions, just to work around the missing version. It's insane.
(It's possible to unpublish NPM packages, which is what happened here. That in itself is terrible, especially since all you get is a 404 from NPM — no reason for the unpublish provided.)
The NPM tool itself is a mess:
* It suffers from sporadic bugs (the dreaded "npm ERR cb() never called") and isn't resilient against network issues (e.g., timeouts).
* It can't use its own cache for packages that have compiled artifacts.
* npm-shrinkwrap.json isn't stable. Adding a package tends to rewrite the whole file depending on whether it has resolved packages from the network or locally.
* Lots of surprising disconnect between shrinkwrap and node_modules. For example, "npm i package" does nothing if it's in the shrinkwrap file, but "npm i package@latest" upgrades (but doesn't, obviously, modify the shrinkwrap file).
* It uses a lot of files. We've had inode issues on some boxes because the sheer size of the NPM cache + deploys use so many files. Production deploys includes all sorts of artifacts (tests, documentation, readme, etc.) that you can't exclude.
* The nested tree (fixed, I hear, in NPM 3.0) is really unmanagable.
The microscopic, mutating nature of NPM packages is chaotic. There's no practical way to do upgrades in a controlled manner. (My wish list item: A command that prints out all upgradeable packages and a complete changelog for each version bump.)
NPM could learn a lot from Ruby's Bundler.
I too am confused about Babel 6... but to be fair I haven't looked too much into it. I just think it's weird that something as "simple" as doing ES2015 -> ES5 now has plugins and a whole ecosystem around it. I understand the creator's ambitions, but I'd prefer to just install it and plug it to my build system.
I don't know much about Go, but I am personally looking into Elixir as another backend choice.
That's why the change, I do think they pulled the gun a bit soon though, but many would have jumped to it just the same.
The legacy of node will be nothing but sadness. (Sort of a joke, but also kind of true)
It seems like you have two choices if you'd like to work in the software industry: you can put up with shitty code and boring maintenance work in exchange for a steady, risk-free paycheck, or you can take on the risk that your code will fail outright and the certainty that it will be grumbled about and ultimately replaced in exchange for the intellectual thrill and potential financial rewards of working on a green-field project.
Meanwhile in node, and I'm just picking a random path here:
webpack -> watchpack -> chokidar -> anymatch -> micromatch -> extglob -> ansi-green -> ansi-wrap
(I might just write a tool to find the largest such path in all of npm.. accepting bets)
On the plus side, it keeps us employed as long as we are prepared to keep learning the new stuff, or earn a spectacular exit.
I will say for a 20 year old language, JavaScript has grown more in the past 6 years than it's first 14, and a lot of that is thanks to Node/npm.
Obviously, I'm not longer with that company, but still writing Node in the day job. As you mention, packages have minor updates with breaking changes, so if you don't shrinkwrap things explode. There is a huge number of JS packages that do a lot of interesting things but the average quality leaves a lot to be desired.
I've found people get something working very quickly with Node.js but then after a year...or three it's very hard to maintain the Node.js system. Especially when the original author is no longer on the team. This is the problem TypeScript tries to solve, and TypeScript is really nice in my opinion...but its 2015 and my computer has four cores and 4 virtual cores. Languages that do not enable developers to easily take advantage of these cores are not interesting and not something I want to invest too much time in for fear they are out of favor in the next few years when cores increase even more...
Go has this solved, but people don't quite trust Google yet. For one, they seem to have a history abandoning things (or completely rewriting from scratch them like Angular 2). Go is missing a few needed features that are preventing more wide spread adoption (things like better package management), but these features are not things that the core team is prioritizing at this time.
If your development methodology collapses when an original developer leaves, then the problem was that they were carrying tech debt by force of will rather than building a robust architecture. This isn't something TypeScript can solve.
> Languages that do not enable developers to easily take advantage of these cores...
Single-threaded runtimes, like Node, aren't intrinsically problematic, and multi-threaded solutions aren't a panacea.
If you have multiple cores and a single-threaded application that you'd like to scale, then assuming the other resources are plentiful, just spawn multiple instances and pin them to those extra cores.
> Go ...
I like Go, and its goroutines, but working with them still requires an understanding of locking and concurrency to get it right. If the plan is to throw a random front-end developer at Go and expect magic, I think that's wildly optimistic.
Not to mention, this is part of the core functionality of node. The cluster module is built in. https://nodejs.org/api/cluster.html.
Agreed on single-threaded runtimes... you can get around them, as far as robustness goes, you bring in the same techniques used to scale to multiple servers, you're just doing it a little sooner.
I haven't done enough in Go to really comment, it looks cool, though I haven't had a use case that I really needed more performance than what I already have with the other tools available.
For me it's that Go is purely an imperative language and is not ashamed of it. That's fine, it's a good imperative language, but I don't like them, so I won't use it. I don't care how great goroutines are (or are not, I really don't know), I'm not using a non-functional language again in my career.
Has it ever been better though? Technically, you could argue that webdev has never been as good as it is now.
Not that I like the current situation, I just think that things in webdevland are better now than ever before.
1. Shrink-wrapping: yes, of course. Semver ranges never made sense to me. All changes are breaking changes. The idea that we could safely auto-upgrade a project is insane. A semver range is an open invitation to allow people not on your team to arbitrarily change your code at any time in the future. If it was up to me, npm install -save would just shrink-wrap. The idea behind semver ranges is fundamentally flawed since it relies on a human making a determination of whether the change is patch or major or what have you. Even if you automate it and tie it to tests you can't know for sure: Even in a magical world where a "patch" upgrade could be guaranteed to not actually break behavior, it could still have dire perf consequences (which in an async world could absolutely change the behavior of your running program by surfacing new race conditions or what have you). That's why this is the behavior on tonicdev.com: when you require a package we magically shrink-wrap it at that point in time. Reproducibility should be the default. All changes are breaking changes.
2. The quickness of change is definitely also an issue. This may just be a price of progress thing though. I certainly wouldn't want to give up amazing rewrite the world changes like the development of React for a "stable" environment. I can also see the flip side to this though.
If you want to protect yourself and upgrade reliably - there are tools, like my https://github.com/bahmutov/next-update - runs your tests and only keeps upgrades that don't break stuff.
Thanks for the library.
I loved node when it came out. I did a lot of experimental projects with it. I also liked npm and the ability to use modules...
But at some point, this all turned into dependency insanity.
It didn't bite me as much, because i've never used node for production apps, but I imagine it has the potential to be a serious issue, when your bread-and-butter app depends on 694 other libraries.. who knows what lurks in them...
What did bite me was the apparent "infinity" of possibilities at each step of the development process. Whenever I need a feature - there's 20 different libs there to help you. Which one should I pick ?
The problem is this approach that somehow finds a monolith with 694 dependencies acceptable, yet turns around and praises node.js modules for being so "bite-sized".
>What did bite me was the apparent "infinity" of possibilities at each step of the development process. Whenever I need a feature - there's 20 different libs there to help you. Which one should I pick ?
This kind of choice paralysis used to bite me too. What totally fixed it for me was really weighing the consequences of adding a dependency every time I'd consider one. Most of my production services are a couple hundred lines and have fewer than 5 dependencies (of which, half are boilerplate that every other service has).
Rails is great at big CRUD MVC applications. If you want a Rails-like app in Node.js, you should start with an opinion "skeleton" MEAN/MVC framework rather than re-implementing rails and all its dependencies with every application.
Well, you're actually right. Babel 6 has had a lot of problems, particularly with async functions, but they are slowly being worked out. I think it's pretty clear at this point that it was released too early, and they really need smoke tests to prevent this kind of problem in future. If you've already built a significant project using Babel 5, definitely consider holding off the upgrade for another month or two.
Bug hasn't been fixed in almost a month: https://phabricator.babeljs.io/T6644
You'd think something like a basic language feature wouldn't break when you update your compiler. I did. I was wrong.
Thank the gods of software gardening that we were only using typeof in five or so places.
If you want stability, use a technology that was popular 10 years ago. If you want to work on the bleeding edge, you will be bleeding. Decide what's appropriate for your project. The reason people worked in Java in 2000 or Swift/Babel today is so they can take advantage of temporary market opportunities where other people get deterred by the pain of capitalizing on them. This can be very financially lucrative if you yourself are willing to put up with that pain.
How does Go solve this?
While Go doesn't have package management, it does have a framework (go get) for automatically fetching and compiling dependencies. However, people quickly realized that there's no way to pin dependencies; it will always fetch the master branch's HEAD, so if you "go get" a project, it will fetch some arbitary version depending what time of day it is. The community has devised various ways around it, and recent versions of Go have a way of resolving packages to a local "vendor" directory, but it's not a solved problem. There's no solution that stands out from the rest as particularly good or feature-complete when you look at the historical alternatives (Ruby's Bundler in particular).
But that may just be me. I think the same thing about generics, and others clearly don't.
FWIW, I've been using Go 1.5's vendoring alongside govendor and it seems pretty nice. While this situation is a bit of a disappointment given the generally awesome tooling in Go, it's hopefully something that will be resolved soon.
Brittle.
Before dismissing Go, please try to understand its history and the fact that it is changing.
I can't talk about Node on the server since I don't use that - already doing way too much javascript for the frontends - but the frontend side is hard to keep up with as well.
Between all the Babel and Webpack plugins it's hard just to get a working setup and the `do one thing and do it well` should not be a bigger thing than user experience.
TypeScript makes writing JavaScript less painful but doesn't solve the ecosystem for me: I do rm -rf node_modules/ && npm install semi regularly to make sure everything works (not using shrinkwrap yet) on a fresh install and I get install errors way too often (peer dependencies etc).
To save you time, don't bother with npm3 for now as it is extremely slow.
That seems crazy! Maybe I am out of touch but how is that even viable or smart? Seems like a time & money suck both of which can be spent on so many other valuable areas. Does the consumer or whoever the site services really care about what front-end framework is being used? No, they just want a decent user experience so why not focus on that rather than the latest shiny framework. I just don't get it.
I feel like some devs have lost site on what's really important with developing software. It is not about the latest shiny thing. It is about the target customer.
This is the case in any environment. This is the case for your OS, for python requirements, for java jars, everything. Your versions should be part of the source control (not necessarily the dependencies in your source, but at least a project file that has the versions listed).
Python has a requirements.txt. It's best practice to pin your versions in it.
I've been trying out jspm recently. It's quite nice and teaches you this out of the box. You pull down a npm package, it will put the version into your package.json so everyone can use the same version.
Node as npm, Perl has CPAN. Why are modules hard in Node, when modules in Perl work?
If you want things to just work like in the Ruby community, make sure you shrinkwrap.
I don't think most people run into this because most backend node programmers have moved to Go at this point, so they're not aware of the upgrade problems.
On the front end, people are probably re writing the front end every 3 or 4 months. Moving from javascript framework to javascript framework. Never dealt with upgrading 6to 5 to Babel to Babel 4 to 5 to 6, and npm from 2 to 3. Or browserify, browserify react hot reload, react-proxy v1 only, gulp. Ugh.
I'm not sure it's possible to move a project using Babel 5, async/await, generators and react to upgrade to Babel 6. I've spent hours on it.
Sometimes I think it's all some kind of cruel joke. Look at Babel. I mean a library that doesn't do anything without installing a plugin. At least support transpiling ES 6 and 7 to 5 out of the box and everything else with a plugin. I have to install like 4 plugins to get anything running.