ianstormtaylor / superstruct

A simple and composable way to validate data in JavaScript (and TypeScript).
https://docs.superstructjs.org
MIT License
7.02k stars 224 forks source link

Support Node 14 (again) #1112

Closed mcmire closed 2 years ago

mcmire commented 2 years ago

It appears that between 0.16.0 and 0.16.1, the minimum version of Node required to use this package changed, from 14.x to 16.x. This was not explicit but seems to have been caused by a couple of factors.

But first, what changed. If you look at src/error.ts in 0.16.0 you will see this line:

return (cached ??= [failure, ...failures()])

In the published version of this file in 0.16.0 this gets transpiled to:

return (_cached = cached) != null ? _cached : cached = [failure, ...failures()];

In 0.16.1, the original line is unchanged, but in the published version it is transpiled to:

return cached ??= [failure, ...failures()];

The ??= syntax is not supported by Node 14, hence, developers are forced to upgrade to at least Node 16 if they want to use v0.16.1 or greater.

After looking at the diff between these two versions and running some experiments, I believe that there are two reasons why this line shows up differently in these two published versions.

  1. Different Node versions were used to build and publish these versions. It appears that Node 14 was used for the former whereas Node 16 was used for the latter. This assertion is supported by the fact that in the Rollup configuration, @babel/preset-env is configured with node: true, which instructs Babel to use the current version of Node as a target. So if the current Node version changes, so does the Babel config.
  2. Between 0.16.0 and 0.16.1, browserslist was updated from 4.20.3, to 4.21.4 (you will probably need to expand yarn.lock; if so, Cmd-F for "browserslist"). In browserslist 4.21.0, IE 11 was removed from the default set of browsers (which is being used in this case, since no explicit list is provided). According to caniuse, IE 11 does not support the ??= syntax, so its removal means that Babel doesn't need to transpile this syntax any longer.

To address this problem, this PR:


One thing you may wonder is why this change is needed at all. Node 16 is the current LTS, so shouldn't that be enough? True, but Node 14 hasn't hit end-of-life yet, and many people are still using it, including my company. We think this package is really great, but it would be even better if we didn't have to have a workaround for our libraries that we still want to keep on Node 14.

Thanks for considering :)

mcmire commented 2 years ago

This is a carryover from the comment I left in this issue: https://github.com/ianstormtaylor/superstruct/issues/1111#issuecomment-1253903140. I know originally I was going to submit a PR that set engines to >= 16.0.0, but after discussing with my team we felt like it would be more beneficial to not only us, but also everyone, if superstruct could support Node 14 in addition to the versions it supports now. Let me know what you think :)

ianstormtaylor commented 2 years ago

@mcmire this is an absolutely beautiful description and pull request. Thank you! I completely agree with everything you said. And I'm sorry for the regression.

mcmire commented 2 years ago

Super, no problem. Thanks for the fast merge/release!