> Two hours of my life gone...
Two hours of work after 4 years sounds ... perfectly acceptable?
And it would have run perfectly right away if the node version was specified, so a good learning, too
This feels like making a mountain out of a mole hill
I've been using Jekyll/Ruby since 2014 for my website, with a few custom plugins I wrote myself. And I've never really needed to do anything like this. It "just works".
My Go and C programs are the same: "just works". I have some that are close to a decade old.
Try any old Spring project, where anything newer than JDK 8 will be incompatible. The only saving grace is that JDK 8 is still available, but even it will eventually reach EOL. And then you look at JDK 11 projects and realize that they won't run on anything newer due to Lombok issues, so that's another thing to update and fix.
I think the experience of code rot is universal and increases with the amount of dependencies you have.
`cmake ..` otoh, tends not to.
It was open much the same in both. If you're happy using outdated and unsupported components with security issues AND you can get hold of the right version of the dev tools and plugins AND your hiding environment still supports the old platform, you can maintain the old version with minimal change. But should any professional developer do this?
It's arguable whether this is the correct decision, but it makes things slightly harder than they used to be
For some definition of "without issues"...
Can remember trying to update a Unity project so it'd be still buildable for 64-bit Mac devices. The very first version bump I done resulted in several critical libraries no longer working and there being no clear alternatives to swap in.
This depends highly on what dependencies are in your C# solution.
Same for his node project. If he'd stuck with dependencies that are just plain js - I'd bet money his project would have installed & built just fine.
By the time you're hitting the native addon apis and doing things like compiling python and C/C++ code... you're going to feel all the pains of those ecosystems too.
Any C/C++ project with even mild complexity has a good chance of being extremely difficult to build due to either missing libraries that have to be installed manually, system incompatibilities, or compiler issues.
Python has like 28 competing package managers and install options, half of which are deprecated or incompatible. I can't even run `pip install` at all anymore on Debian.
Even Rust, which is usually great and has modern packaging and built-in dependency management, often has issues building old projects due to breaking changes to the compiler.
All this is to try to say that I don't think this is some problem unique to JS at all - but rather a side effect of complex interconnected systems that change often.
A big reason Docker and containers in general became so popular was because it makes this problem a lot less difficult by bundling much of the environment into the container, and Docker is very much agnostic to the language and ecosystem running inside it.
Most who are here saying that X, Y, or Z ecosystem "compiles and runs" fine after 4 years are talking about the time it takes to resume an old project in a language they're very familiar with running the same dependency versions, not the time it takes to version bump a project on a language that you don't know well without actually having it running first on the old version.
I can open my 4-year-old Node projects and run them just fine, but that's because I use the tools that the ecosystem provides for ensuring that I can do so (nvm, .nvmrc, engines field in package.json).
Does it, though? Node wasn't exactly new 4 years ago, and plenty of other languages would offer a better experience for even older code -- Java, C, C++ to name a few.
50% of Java developers are still regularly working in Java 8 [0], which is the same solution that the author could have arrived at immediately—when starting up an old project after 4 years, use the same version you ran last time, don't try to update before you even have the thing running.
> C, C++
Not my experience, but maybe it depends on your operating system and distro? In my experience sorting through the C libs and versions that you need to install on your system to build a new project can easily take a few hours.
1.5 hours to get running again?
1?
In exchange for needing to run C? How many hours would it take to build a Node app equivalent in C, I wonder.
I just got burned by an old js (vue 2) project. I ended up re writing it using good old ssr in Django with htmx and alpine when necessary. Now it’ll run until the end of time. It doesn’t even have a build step.
It seems luck of the draw. My old React projects (old as in 2018) still work great with class components. I guess the Vue guy did say he would be more revolutionary, when he launched it.
This whole thread just reeks of JS hate. I'm not perfectly happy with the language either, but nor am I perfectly happy with any other. If my employer wanted me to use C# or Go or whatever instead I'd be perfectly okay with that as well.
It's really not. I'm in the same situation with a Go + React project I haven't really touched in 3 years. The Go part is just `go build`, it still works after 3 years and I have a build in a fraction of a second. The React project doesn't build anymore at all. I used Parcel 2 at the time, and it turns out it's incompatible with a Mac M1 for some reason, and it's hard to update in my case. I also used Antdesign and some components (icons specifically) apparently disappeared. It should not be so hard.
and dare i say this is the lucky case. i had problems reactivating some older project because some dependencies were not version locked and newer versions of those were incompatible with other versioned ones. then it took forever to figure out the right versions. and i think i even had situations where the old version wasn't even available anymore (perhaps because of a linux dependency that wasn't available anymore on my newer linux system)
OTOH with Node I always find myself in dependency hell with dealing with old projects.
This was with zero awareness of Svelte 5 (I only knew it was released — I wanted to upgrade because Node 14 is EOL now and I’d noticed some npm audit warnings.) So I feel I also learned something in the process.
Npm at this point is probably the most used and most worked on package manager in history. If it is still one of the worst ones that is actually kind of interesting philosophically.
Locking env version is important.
Double points for using experimental / POC technology like gatsby or nextjs. They are expected to burn and fail
Pefectly acceptable? Perfectly? Really? I have 10 year old C and Go projects that build and run fine as if nothing has changed. I can upgrade the dependencies if I want to but that's on me. The projects themselves have no problem building and running fine.
On the flip side, anything that uses vanilla JS without a build will most likely run just fine, probably till the end of human civilization.
Basically a lot of AI depends on a bunch of absurdly optimized numeric libraries writen in Fortran.
Fortran is well into the way at becoming a centenarian programing language at 74 years of age.
There will also be someone playing Tetris, Doom and Final Fantasy VI on their neural interface, long after all modern games have been lost to time (and DRM).
Zombie JavaScript will be reduced to being glue code and then not even that.
You corrected yourself, but it's worth emphasizing here: a _NodeJS_ project, you mean.
Unless you're using non-standard APIs, stuff written to run in the browser generally keeps working just as well as it did before, no matter whether it was written 2 years ago or 10.
j/k - I'm slowly removing all the Zepto code I have and it's usually a relatively quick search&replace.
Go is much, much better on these terms, although not perfect.
I’d venture a guess that Perl 5 is outstanding here, although it’s been a few years since I tried to run an old Perl project. CPAN was dog slow, but other than that, everything worked first try.
I’d also bet Tcl is nearly perfect on the ‘try this 10 year old repo’ test
App::cpanminus (cpanm) is noticeably lighter, App::cpm (cpm) does parallel builds and skips tests by default.
An approach I've become quite fond of is using cpm to install fast into the local::lib I'm actually going to use, then creating a scratch setup in /home/tmp or similar and running cpanm in that under tmux/abduco/etc. to do a second install that *does* run the tests so I have those results to refer to later but don't have to wait for them right now.
(if I ever write a cpan client of my own, it's going to have a mode where it does a cpm-like install process and then backgrounds a test running process that logs somewhere well known so this approach becomes a single command, but I keep getting distracted by other projects ;)
CL is still one of the nicest languages there is, and the only language that skirts the line between being some combination of dynamic and interpreted yet typed and compiled.
It is showing its age though, particularly around the edges like what you're saying.
It also helps that if some library dependency generated Go code using a tool, the Go source code is checked in and you don’t have to run their tool.
It's just no guarantee that those old versions work on the new system, or with the outside world as it exists by time of installation - which can be as true for Go as any other language. If the XYZ service API client still gets you version 1.2.37, that's not actually any help if 1.2.37 calls endpoints that the XYZ service has removed. Or a cgo package that binds to a version of OpenSSL that is no longer installed on your system, etc.
What's been interesting is watching these devs age 10 years, and still mostly decide it's better to start new frameworks rather than treat legacy code as an asset. That feels to me like a generational shift. And I'm not shaking my cane and saying they're wrong -- a modern LLM can parse an API document and get you 95% of the way to your goal most of the time pretty quickly -- but I propose it's truly a cultural difference, and I suspect it won't wash out as people age, just create different benefits and costs.
To be fair, Python and Ruby also have this problem (for newer Pythons, popular extension modules at recent versions are more likely to Just Work due to wheels, but if you're building old code for the first time in 3+ years, all the old problems come back with a vengeance). It's more of a "scripting language that got popular enough that ordinary projects have a deep tree of transitives, many of which are compiled on-site" issue than a Perl specific problem.
Previously: You wouldn't conflate Windows development with "C" (and completely discount UNIX along the way) just because of Win32. <https://news.ycombinator.com/item?id=41899671>
A few weeks ago I was experimenting with a sound generation dsl/runtime called Csound and even most 30yo sources were working as long as they didn't use some obsolete UI.
If you must depend on node-gyp, perhaps use dev containers so at least every developer in your team can work most of the time.
I don't even develop against Node, it has just crept into our front-end build toolchain.
My favorite is the way that Python projects rot. Not only does Python's setuptools give you all the fun that node-gyp does, the common practice of versioning packages with packagename>=1.25.5 means you're almost guaranteed breakages as pip installs newer versions of packages than what the project was built with.
Most of the times it will not work with the newest shiny python, which I only notice after already installing it and then having searched search the Github issues.
Granted, my experience is mostly from the GPT-2 era, so I'm not sure if it's still this painful.
What really pissed me off about it was that Python 2 was already known to be nearing EOL when our project was started, so node-gyp should have been upgraded to work with Python 3 by then. And even more annoying was that node-gyp already had Node to run on, so why in the world was it coded to depend on Python at all!?
Hopefully the ecosystem as improved since then, but it was nearly impossible to get going.
Some packages had been changed and the version number overwritten with incompatible packages, and the conflicts were plenty.
It's OK. Not every language ecosystem is so busted that you can reliably expect a project not to work if someone isn't staring at it weekly and building it over and over again just in case. Now, it's always a risk, sure, no language anywhere is immune to the issue [1], but there's plenty of languages where you can encounter things from 5 years ago and your default presumption is that it's probably still working as well now as it did then. It may be wrong, but it's an OK default presumption.
[1]: Well... no language in common use anyhow. There's some really fringe stuff that uses what is basically content-based references for code dependencies, but I'm not aware of anything that I'd call "production quality" that even remotely looks like that, and is immune to someone just plain making an error with the semantic versioning or whatever.
Lol, my perspective is almost the opposite. If it's got a lot of commits in the last six weeks, I need to look for something that's stable. Unless there's a good reason for so many commits; I feel like that many commits means it's in active development, which implies the requirements and interfaces aren't yet determined and who wants to rely on that?
If there was an option to guarantee versions could exist for X amount of years (maybe even months?) then that would greatly help the stability of projects.
Since it's just a binary though, I wound up grabbing the OpenSSL from the old box and patching the binary to just point to that instead. Thing runs fine after that.
This is all, of course, still totally stupid - but I did find myself thinking how much worse comparable events in JS have been for me over the years. What would have been easily an entire afternoon ended up taking 15 minutes - and a chunk of that was just double checking commands I'd long forgotten.
Also, if it was statically linked, he wouldn't have that one problem. (Could have others, but not that one.)
For those reading this who don't know much about node - node-gyp is how you pull in native code libraries to Node projects, typically for performance reasons. You get the same sorts of build issues with it that you can get whenever you start having binary, or source, dependencies, and you need the entire toolchain to be "Just Right(tm)".
I run into this issue with older Node projects on ARM Mac machines (Still!), but I run into similar issues with Python projects as well. Heck some days I still find older versions of native libraries that don't have working ARM builds for MacOS!
Node used to have a lot more native modules, in newer code you typically don't see as much of that, and accordingly this is much less of an issue now days.
> I always try to remember to put the node version in my package.json
This 100x over!
I would prefer to remain blissfully ignorant, thank you!
The original dream for Node was that it would simply be a glue wrapper around libuv that allowed for easy packaging/sharing of modules written in C++. But everyone just started writing everything in JS, and the ecosystem ended up as a mish-mash of native/non-native. Ryan Dahl stated this was indeed his biggest mistake/regret with Node, thus we have Deno now.
Because the native written stuff breaks all the darn time and it creates cross-plat nightmares.
My stress levels are inversely proportional to how many native packages I have to try to get building within a project, be that project in Python, Java, or JS.
JS+Node runs on everything. Prepackaged C++ libraries always seem to be missing at least one target platform that I need!
It's a python codebase, largely abandoned by google. They used to use it for building Chrome.
When I was managing teams, whatever the language, I would ban any new dependencies which I didn't personally agree with. A lack of control just creates a nightmare.
Normally when I'm the one with that power we rapidly get to a general understanding of what's small enough that I (a) probably won't care (b) will take responsibility for tweaking the schedule to makre time to get rid of it if I do.
And 'big' dependencies are generally best discussed amongst the entire team until consensus is reached before introducing one anyway.
That way, the project has just the dependencies it needs, and I know I can rebuild it at some point in the future and will be unlikely to run into problems when I do.
I personally use Nix these days, but the complexity is too high for me to recommend it to everyone for every software project.
If upgrading is difficult because of 4 years of breaking changes, blame Gatsby for not being backwards compatible. Also blame your original choice of going with a hokey framework.
Speaking of hokey framework: 167 dependencies and 3000 versions of Gatsby in npm.
That's a quick fix, upgrading a framework is a guaranteed min hour of poking around before the system is even running.
I dunno why `engines` isn't in every `package.json` file, would certainly have saved me hours of nonsense.
If I had only wasted two hours every time I had to use npm for some reason I'd be significantly ahead of where I am now.
> run command xyz
I run xyz and I'm on to the next step in an average of ten or fifteen minutes (because yeah, stuff still goes wrong some times).
But if the instruction is to invoke npm, there's always some crazy side quest involved. It doesn't get any better with time because next time around it's a totally different side quest. I can't even offer any criticism towards fixing it, it just sucks for unique new reason every time.
In the JS ecosystem, I'm aware that Meteor is one major framework that takes backwards-compatibility seriously. Updating a project on an ancient version to a less-ancient version usually is not too hard. They try to keep APIs the same and introduce compatibility packages where possible.
Meteor 2.16 to Meteor 3 introduced major breaking changes due to an underlying technical issue that had no workaround. They had to refactor the whole project from using Fibers-based concurrency to typical async/await.
node-gyp in general has also been a source of issues in the past for me as well.
More recently, ESLint changed their configuration file format and all existing tutorials suddenly became outdated.
I firmly believe the ecosystem does not have to be like this, and we would save a lot of man-hours by being more committed to API stability where possible.
That's when I picked up the Node/React ecosystem...
> node-gyp errors > downgrade to 12.2
This is what I did until Vercel decided to not support Node 12 anymore...
for the latter i get around the problem by avoiding build tools altogether. i use a frontend framework that i can load directly into the browser, and use without needing any tools to manage dependencies. the benefit from that is that it will ensure that my site will keep running for years to come, even if i leave it dormant for some time. the downside is that it is probably less optimized. but for smaller sites that aren't under continuous maintenance this is a reasonable tradeoff. i built all my recent sites that way using a prebuilt version of the aurelia framework.
incidentally just today i tried to research if i could build a site with svelte that way. well, it turns out that although it should theoretically be possible, i was unable to find a prebuilt version to do so after a few hours of searching. for vuejs i found one within minutes. i'll be learning vuejs now.
see this thread for a discussion on going buildless: https://news.ycombinator.com/item?id=41479365
I haven't yet decided if/how I want to include a prebuilt version of it in the repo, I *think* I may go the approach of having a commit that modifies libs.js and/or the lockfile and then an immediately following one that commits an updated prebuild ... oh, huh, actually, I should probably also consider doing those two commits on a branch, then forcing a merge commit so they land on master atomically but it's easy to tease out the human changes and the regen changes by poking inside said merge commit ... yeah, like I say, still thinking about exactly how to do this, don't mind me.
Also for even simpler cases I've been using the preact-htm prebuild directly, since htm gives a lit-style html() tagged literal consuming function that can produce vnodes for preact so I can mess around without needing something that understands jsx between my editor and my browser window.
vue's component system is IIRC noticeably less nice to work with if you don't have a compile step, but it's still pretty nice even without that so please don't think I'm trying to dissuade you here :)
saving a prebuilt version of code that needs building is of course also helpful, and much better than having to rely on keeping your build tools working. but when you want to make changes to the site you have to either deal with the build tools anyways or work with the prebuilt version which may not be as practical.
either way i would simply save the prebuilt version to a branch and if any changes are made in that branch cherrypick them over to the dev branch if they even can be use, which i am not sure about. i'd probably rather avoid making changes to the prebuilt code in the first place
how does lack of a compile step affect the code? are there things i won't be able to do if i don't compile? i haven't started yet, and my website is not very complex so i think i'll manage either way, but i am curious. can you link to an example?
it's absolutely the expectation for C++ projects to support building on GCC, Clang and MSVC
On the other hand, there's a reason I regularly get annoyed enough at it to call it nope.js.
On the gripping hand, I mostly write perl, which argues for a different but unique set of masochistic tendencies on my part.
(you just have to remember that what 'perl' *really* stands for is 'Perenially Eclectic Rubbish Lister' and then you will have appropriate expectations and can settle back and have fun ;)
It is systemic. Part of it is due to too many people creating systems on the fly with too little forethought, but also because there aren't enough "really smart people" working on long term solutions. Just hacks, done by hacks. What did you expect when the people writing the systems don't have long term experience?
It's not hard. The explanation is simply that the dart version of SASS (the sass npm package) is much slower than node-sass.
At one point it was like 20x slower and I believe right now it's about 2-3x slower.
We're in ... let's call it a transitional period at work. I've got something like a dozen versions of node being managed by asdf. And in half of the projects I work on regularly, I consistently get warnings about this particular project failing to build.
One day, I'll actually look up what it actually is, and what it does, and why it's being built, but is apparently optional.
Everybody complains about it, and understandably so, but if it didn't exist you'd probably instead have one set of potential similar problems *per* native module which has a good chance of not actually being better overall.
The counterargument is, I guess, "well, only people who can write their own high quality build setup in-tree should be writing things that bind to external code," and I do sometimes dream of that, but it's not hard to see the downsides of living in *that* world instead either.
https://dubroy.com/blog/cold-blooded-software/
Sibling comments say in so many words, it's no big deal bro, just update. But it is a big deal over time if you have dozens of cold-blooded projects to deal with.
Node is an active project. If you build against the native API and don't pin your version to avoid breaking changes between versions, this is what happens. In my experience, JS very rarely breaks between major Node versions, but almost every native package requires a new major update.
This isn't a Node specific problem. Go ahead and upgrade your Go or Python version.
I had a similar experience with emberJS when it was still young. Every time I picked the project up I had one to two hours of upgrade work to get it to run again, and I just had a couple hours to work on it. So half my time went to maintenance and it wasn’t sustainable.
I’m trying a related idea now in elixir and José may be a saint. Though I fear a Java 5 moment in their future, where the levee breaks and a flood of changes come at once.
If Nix is too heavy, the learning curve for tools like asdf-vm and mise is much lower and offers similar benefits.
I really wish there was a good equivalent for Windows.
- bump patch or minor version from a react package but the maintainer rewrote the entire project breaking a lot of things, following semver it's bad to expect things don't break like that for such version; - another example, the ruby gem is removed/yanked from rubygems.org and you'd to find a fork available
On the end, we need to ensure the good practices from software engineering about tests and good release management, the last btw is decades old
Beat SSG I've found, and all from a medium or dev article on a SSG in 40 lines or less.
"Not Invented Here" is whats going on. Developers of this age need to learn this.
A recent exmaple is the RPI Foundation nullifying thousands of internet tutorials renaming "/boot" vs "/bootfs". Ask yourself a serious question, did that actually improve anything? No it did not.
Fortunately this mindset has been changing in the node ecosystem with projects like https://hono.dev/ (koa/express successor) and https://github.com/porsager/postgres having zero deps.
Gave up.
Then I ran `devbox init` and installed whatever it told me that was needed. `devbox shell`.
Anyways, npm ci should have been the first attempt, not npm install so that it installs the same package versions defined in the package-lock.json. Then as others have mentioned, pin your node versions. If you're afraid of this happening again, npm pack is your friend.
In the end, op could have done a bit more. BUT I'll give it to him that when bindings are involved, these things take more time than they should
https://medium.com/hackernoon/how-it-feels-to-learn-javascri... (beware the green background, I recommend reader mode.)
I'd like to see the consensus on most durable software packaging method.
"go mod init" + identify a working dependency version was all I had to do on any of those 10+ year old projects (5 minute work tops)
Experienced programmers will not pick up a "built on shifting sand" stack, because they can acutely perceive the pain and suffering before it happens, generally from past experience. With fast-crumbling stacks, you need to execute quickly and move on, and treat the whole codebase as an expiring entity. Stacks I personally try to avoid: anything node/javascripty, anything Androidy, anything iDevicey.
Those who don't understand Unix are condemned to reinvent it, poorly. - Henry Spencer
Also, do not run shit on a node version that is years out of date and out of service. Also, update your damn packages. I know I sound cranky, but running anything internet facing with god knows how many vulnerabilities in is an exceedingly bad idea.