What’s the issue with the engines field? I don’t see any particularly strong reason to not use it.
Additionally, even with semantic versions, `engines` is often specified as something like `12 || 14 || >= 16`, so they span multiple major versions, which is where breaking changes can (and do) show up.
Pinning the Node.js version for tools like nvm is used by developers of the package or app developers who want to use the same version of node locally and in production, for example.