Habits of a Happy Node Hacker
blog.heroku.com
blog.heroku.com
But it is going to download the internet, will take forever, and if the network is patchy, any dependencies that weren't downloaded will remain unresolved, even if you reinstall the package, and you'll have to manually install them with the help of `npm list`, or nuke node_modules and start over, and pray that this time the network remains perfect for a few minutes at a stretch.
(someone please tell me I've got it all wrong)
1) you can install from cache with something like:
npm install --cache-min 9999999
2) npm's infrastructure has scaled extremely well. Gone are the days of spotty uptime and slow resolution. I maintain an npm proxy for one of—if not the—single largest consumer of npm modules and other than the very occasional 502 blip, npm has been rock-solid.I'll try the cache-min flag. But I suspect that if the cache contains packages with unresolved dependencies, then they'll also be of no use, and have to be removed too.
Also npm's servers has never given any trouble, the issue was always with my networks.
If you are grabbing from an external repo, the spotty network is going to mess you up either way. If it's internal and your internet is that spotty, consider hosting a local npm cacheing server like this -- https://www.npmjs.com/package/sinopia.
My only issue with this technique is that 'npm start' and the rest aren't smart enough (please correct me if I'm wrong and there is a way to make it care!) to grab dependencies if you upgrade a dependency version and check that in.
I install something --save and get "^1.0.0" into my package.json, which resolves to 1.0.0
Someone installs my stuff and on her machine it resolves to 1.0.3 and nothing works anymore, even if she cloned an exact copy of my repository etc.
Next step is to lock down all versions in my package.json, so all wildcards are gone.
But the packages I depend on still have wildcards and can break happily.
This happens far too often for my taste and can (as far as I know) only be solved with third party software.
People have historically experienced a lot of issues with shrinkwrap in older versions of npm; I'm optimistic that npm 3 solves a lot of them.
The alternative is, you shrinkwrap everything and lock it down, and your dependencies never change. Except that now it's been a year, and you want to update your dependencies, and it's this huge jump that requires so many changes that it's going to take a month of concentrated pain to do, so you never do it, and welcome to the world of legacy code.
Take your dependency-update hits in small bursts on the regular, and only lock down (via shrinkwrap or Docker images) for QA/release builds.
Uh, no, I don't want my dependencies to break out from under me, thanks.
This is a major problem with the JS culture that I cannot stand. Too many JS devs can't be bothered to write software that doesn't suck, and so they try to instead tell their users their crappy problems are actually what they want. No, if you push changes to a library that break your library users' software without warning and a reasonable upgrade plan, you're doing a bad job.
> The alternative is, you shrinkwrap everything and lock it down, and your dependencies never change.
Or I use dependencies that upgrade their dependencies intentionally instead of whenever the `^` does it for them. The problem is that most of the JS packages out there are garbage software that doesn't do that. So it's necessary to be careful and only use dependencies which are well-maintained and reliable. ...which isn't unique to npm or a new problem, it's been well-known since all the way back when CPAN was new. Just because installing libraries is easy doesn't mean it's a good idea.
> Except that now it's been a year, and you want to update your dependencies, and it's this huge jump that requires so many changes that it's going to take a month of concentrated pain to do, so you never do it, and welcome to the world of legacy code.
Or you can do your job like a competent professional and don't wait a year to upgrade your dependencies. Again, fewer, more reliable dependencies helps with this; if you are using reasonable dependencies, they'll push few breaking changes and give warnings and reasonable upgrade plans.
But I have to admit, the problems I mentioned only occur about once a month and only cost a few hours to fix and we have over 100 dependencies.
If we wouldn't use so much third party stuff we would probably end up fixing this every few months, which is okay-ish.
That actually isn't supposed to happen, because semver means don't do anything breaking in a patch release (or a minor release). Not that the system works perfectly, of course.
The usefulness of the tool (vs just straight env vars) is mostly in its ability to:
1) start multiple processes at once during local dev, much like a process manager can on a platform like Heroku or a compose file can in Docker. For instance, I'm working on a system now that uses `web`, `game`, and `sms` processes - which can all be started together via `nf start`, and then when one crashes during development the whole system spins down.
2) inject env vars into a local app via `.env` files (similar to your config.json example)
How is this possible in my multiplayer game where the whole world lives in the program? E.g. var map = [...] and then map[x][y] when I want to use it, var players = [], players.push(newPlayer) etc. How can I share this state in a cluster?
That being said, if you are planning on scaling, you'll likely be moving your map object into it's own process, or a more traditional database, etc. Then whatever node application you have that facilitates the communication between that db/process and your users (via websockets or http) will be the place where clustering will come in handy.
If you want a fun exercise, try monkeypatching your global objects (map, players, etc.) to have getters/setters/etc. that transparently handle the syncing stuff.
That's the ideal case anyway, its hard to avoid session state with websockets etc, but you can still push a lot down to the database layer
Is this becoming popular / the new standard?
Though I don't agree with every suggestion, memory tuning and clustering are both really important and not discussed widely enough. save-exact is a good tip too - I've just been mass-deleting the carets before committing.
Apart from the problems with Windows, npm, and path lengths.
http://www.felixrieseberg.com/npm-v3-is-out-and-its-a-really...
http://blog.codinghorror.com/filesystem-paths-how-long-is-to...
"Node is pretty impressive on Windows. You get the feeling that JavaScript (as well as HTML and CSS) are a first class citizen in the Operating System. I already have a list of dozens of Native Windows Apps I want to build using Node."
http://daverupert.com/2015/08/developing-on-windows/
(good contrast with other experiences from a polyglot)
"Node is quite awesome on Windows to be honest."
https://medium.com/@vernonk/surface-pro-4-the-ipad-i-always-...
Or try using child_process.spawn without resorting to a 3rd party module or adding platform specific code yourself. Yeesh.
For another node example - in Linux, you can successfully use paths like `let filepath='foobar/' + filename`. That's correct in the given environment. However, such code will break when run in Windows. This is why `let filepath = path.join('foobar', filename)` is a superior solution.
A Windows or OSX user can save Myfile.js all day long and require('MyFile') with success. That same code will break as soon as you try to run it in Linux.
These recommendations are the product of supporting the many thousands of Node apps built each week on Heroku.
If you want 100% confidence in being able to reproduce the specific bytes included in a deployment, you should use an additional mechanism that can verify contents rather than versions. For example, Amazon machine images, DigitalOcean snapshots, Heroku slugs, or simple tarballs."
https://docs.npmjs.com/misc/faq#should-i-check-my-node-modul...
Either because authors "bugix" their existing versions and don't bother to increase the version number. Or because a malicious network actor delivered modified code.
That's why I prefer to add a SHA-256 hash/checksum to every downloaded dependency file. In some settings that hash might be more important than the actual version number.
But I'm still uneasy with this, as the crypto hash approach provides some more safety features. For example, it protects against attacks the NPM platform itself (assuming they happen after you incorporated the library into your project). Also, it enables us to download the package from any other source (e.g. some archive/mirror), via plain HTTP, while still being safe from downloading a modified package.
That's why I still wish the crypto hashes were included in package.json (automatically on "install --save-exact", of course).
It's been changed now, but originally was titled "10 Habits of a Happy Node Hacker (2016)"