The tragedy of running an old Node project
Fragility of Older Node Projects
- Many commenters report that Node projects “rot” quickly: even a few months’ or years’ gap can make them hard or impossible to build.
- Breakage often appears when trying to run old code on a newer Node version, or when dependencies have silently changed or vanished.
- Some argue two hours of work after four years is acceptable; others say that in other stacks they routinely revive 10–20‑year‑old code in minutes.
Native Extensions and node-gyp
node-gypand native addons (C/C++ bindings) are repeatedly cited as the main source of pain: toolchains change, Python 2 vs 3 issues, missing system libs, architecture mismatches.- Advice: avoid packages that depend on
node-gypunless absolutely necessary (e.g., password hashing, image processing). Prefer pure JS, or offload such concerns to external services.
Comparisons with Other Ecosystems
- Several ecosystems are described as more stable for old projects: Go, Java, C/C++, C#, Perl, PHP, Common Lisp, R, Tcl; others (Python, Ruby, Android, React Native) are reported to have similar or worse bitrot.
- Some note that problems correlate strongly with deep transitive dependency trees and native extensions, not just language choice.
- Debate exists: some say Go/Java/C# “just work” for decade‑old code; others recount hard upgrades (Java 8→9, Spring, Gradle, Xamarin, old Go without modules).
Dependency & Environment Management Tactics
- Recommended practices:
- Pin Node version (
enginesinpackage.json,.nvmrc, asdf/mise, devShells). - Commit lockfiles and, when possible, vendor dependencies.
- Use Docker or similar to freeze OS, toolchain, and Node version.
- Run CI to ensure builds stay reproducible.
- Pin Node version (
- Lockfiles and narrow version ranges improve reproducibility but can over‑constrain environments; some argue for libraries that support wider version ranges.
Cultural and Architectural Critiques
- Several see Node/npm issues as cultural: speed and churn, huge dependency graphs, frequent framework rewrites, loose attitudes about stability and semver.
- Others stress this is a general modern‑software problem: maintainers lack incentives to support old versions, and any stack with many moving parts will decay.
Alternatives and Mitigations
- Suggestions include:
- Buildless or low‑tooling approaches (vanilla JS, HTMX, Alpine, simple static site generators, Hugo).
- Choosing ecosystems with strong backward compatibility and big standard libraries.
- Keeping dependencies minimal and treating them like own code.