Skip to content

Support Node 14 (again)#1112

Merged
ianstormtaylor merged 1 commit intoianstormtaylor:mainfrom
mcmire:support-node-14
Sep 22, 2022
Merged

Support Node 14 (again)#1112
ianstormtaylor merged 1 commit intoianstormtaylor:mainfrom
mcmire:support-node-14

Conversation

@mcmire
Copy link
Copy Markdown
Contributor

@mcmire mcmire commented Sep 21, 2022

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:

  • changes the Rollup configuration mentioned above to use node: "14.0" instead of node: true, so that Node 14 is always used to compute the transpilation rules regardless of the version of Node used locally to build and publish the package
  • updates the CI workflow to ensure that Node 14 is being tested (along with 16 and 18)
  • adds Node >= 14 to the engines field to communicate that it is supported

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 :)

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][1]:

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

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

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

In 0.16.1, the [original line is unchanged][3], but in the [published
version][4] 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][5], `@babel/preset-env` is configured with `node: true`, which
instructs Babel to [use the current version of Node as a target][6]. 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][7] (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][8] (which is being used in this case, since no explicit list is
provided). According to caniuse, [IE 11 does not support the `??=` syntax][9],
so its removal means that Babel doesn't need to transpile this syntax any
longer.

To address this problem, this PR:

* changes the Rollup configuration mentioned above to use `node: "14.0"` instead
of `node: true`, so that Node 14 is always used to compute the transpilation
rules regardless of the version of Node used locally to build and publish the
package
* updates the CI workflow to ensure that Node 14 is being tested (along with 16
and 18)
* adds Node >= 14 to the `engines` field to communicate that it is supported

---

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 :)

[1]: https://github.com/ianstormtaylor/superstruct/blob/v0.16.0/src/error.ts#L44
[2]: https://unpkg.com/superstruct@0.16.0/lib/index.cjs
[3]: https://github.com/ianstormtaylor/superstruct/blob/v0.16.1/src/error.ts#L44
[4]: https://unpkg.com/superstruct@0.16.1/lib/index.cjs.js
[5]: https://github.com/ianstormtaylor/superstruct/blob/v0.16.4/config/rollup.js#L26
[6]: https://babel.dev/docs/en/options#targetsnode
[7]: https://github.com/ianstormtaylor/superstruct/compare/v0.16.0...v0.16.1?diff=unified#diff-51e4f558fae534656963876761c95b83b6ef5da5103c4adef6768219ed76c2deL99
[8]: https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md#421
[9]: https://caniuse.com/?search=%3F%3F%3D
@mcmire mcmire changed the title Support Node 14 Support Node 14 (again) Sep 21, 2022
@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Sep 21, 2022

This is a carryover from the comment I left in this issue: #1111 (comment). 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
Copy link
Copy Markdown
Owner

@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.

@ianstormtaylor ianstormtaylor merged commit d9fc2ff into ianstormtaylor:main Sep 22, 2022
@mcmire mcmire deleted the support-node-14 branch September 22, 2022 20:29
@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Sep 22, 2022

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

mcmire added a commit to MetaMask/utils that referenced this pull request Sep 22, 2022
Published versions of `superstruct` between 0.16.1 and 0.16.4 contained
syntax (`??=`) that Node did not support until v15. This effectively
changed the minimum required Node version for this package, and any
other package using this package, to v15. A [fix for this issue][1]
landed in `superstruct` 0.16.5, so this commit bumps that library
accordingly so as to restore compatibility with Node 14.

[1]: ianstormtaylor/superstruct#1112
mcmire added a commit to MetaMask/utils that referenced this pull request Sep 22, 2022
Published versions of `superstruct` between 0.16.1 and 0.16.4 contained
syntax (`??=`) that Node did not support until v15. This effectively
changed the minimum required Node version for this package, and any
other package using this package, to v15. A [fix for this issue][1]
landed in `superstruct` 0.16.5, so this commit bumps that library
accordingly so as to restore compatibility with Node 14.

[1]: ianstormtaylor/superstruct#1112
mcmire added a commit to mcmire/core that referenced this pull request Jul 17, 2023
Published versions of `superstruct` between 0.16.1 and 0.16.4 contained
syntax (`??=`) that Node did not support until v15. This effectively
changed the minimum required Node version for this package, and any
other package using this package, to v15. A [fix for this issue][1]
landed in `superstruct` 0.16.5, so this commit bumps that library
accordingly so as to restore compatibility with Node 14.

[1]: ianstormtaylor/superstruct#1112
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants