Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update NodeJS to v18 #72245

Merged
merged 3 commits into from Jan 23, 2023
Merged

Update NodeJS to v18 #72245

merged 3 commits into from Jan 23, 2023

Conversation

noahtallen
Copy link
Member

@noahtallen noahtallen commented Jan 17, 2023

Proposed Changes

NodeJS 16 is now in maintenance, and v18 is the current LTS. This attempts to update to v18. Unsure what, if anything, will break, but figured I'd at least put up a PR and see what happens.

Testing Instructions

  • All CI passing (note: also create a custom base image build.)
  • Local dev working (yarn install plus yarn start after switching to node 18)
  • Smoke test with this calypso.live link (it was built from a custom base image with node 18): https://container-gifted-carson.calypso.live.

@matticbot matticbot added the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Jan 17, 2023
@noahtallen noahtallen requested a review from a team January 17, 2023 21:35
@noahtallen noahtallen self-assigned this Jan 17, 2023
@worldomonation
Copy link
Contributor

I've been using nodejs 18.x.x for the longest time to run everything, so I'm pretty sure it works 😆

@noahtallen
Copy link
Member Author

Love hearing that!

@noahtallen
Copy link
Member Author

noahtallen commented Jan 17, 2023

I get this error locally, which then lead me to this answer: https://stackoverflow.com/a/73027407. The gist is that we'll probably need to update some dependencies before we can merge this. We get a similar issue in the ICFY build.

ERROR in ../node_modules/moment-timezone/index.js 2:15-51
Module not found: Error: error:0308010C:digital envelope routines::unsupported
 @ ../node_modules/moment-timezone/moment-timezone-utils.js 12:33-46
 @ ../node_modules/@wordpress/date/build-module/index.js 6:0-47
 @ ../packages/components/src/gm-closure-notice/gm-closure-notice.tsx 2:0-41 36:17-23 37:18-24 42:18-24 55:12-18 56:13-19
 @ ../packages/components/src/index.ts 26:0-72 26:0-72
 @ ./landing/stepper/declarative-flow/internals/index.tsx 1:0-53 137:120-131
 @ ./landing/stepper/index.tsx 32:0-60 92:14-26

See also webpack/webpack#14532

Edit: this was fixed by bumping the moment-timezone packages.

@matticbot
Copy link
Contributor

matticbot commented Jan 17, 2023

Here is how your PR affects size of JS and CSS bundles shipped to the user's browser:

Sections (~16 bytes added 📈 [gzipped])

name              parsed_size           gzip_size
settings-writing      -4811 B  (-0.8%)       +5 B  (+0.0%)
scan                  -4811 B  (-0.7%)       +5 B  (+0.0%)
home                  -4811 B  (-0.5%)       +7 B  (+0.0%)
help                  -4811 B  (-0.6%)       +6 B  (+0.0%)
concierge             -4811 B  (-1.1%)       +8 B  (+0.0%)
comments              -4811 B  (-0.6%)       +7 B  (+0.0%)
backup                -4811 B  (-0.6%)       +8 B  (+0.0%)
activity              -4811 B  (-0.7%)       +8 B  (+0.0%)

Sections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to.

Async-loaded Components (~7 bytes added 📈 [gzipped])

name                                            parsed_size           gzip_size
async-load-signup-steps-clone-point                 -4811 B  (-2.2%)       +8 B  (+0.0%)
async-load-design-wordpress-components-gallery      -4811 B  (-0.6%)       +6 B  (+0.0%)
async-load-design-blocks                            -4811 B  (-0.2%)       +6 B  (+0.0%)
async-load-calypso-components-jetpack-sidebar       -4811 B  (-3.1%)       +5 B  (+0.0%)
async-load-calypso-blocks-inline-help-popover       -4811 B  (-0.7%)       +6 B  (+0.0%)
async-load-calypso-blocks-calendar-popover          -4811 B  (-1.7%)       +2 B  (+0.0%)
async-load-automattic-help-center                   -4811 B  (-0.8%)       +6 B  (+0.0%)

React components that are loaded lazily, when a certain part of UI is displayed for the first time.

Legend

What is parsed and gzip size?

Parsed Size: Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory.
Gzip Size: Compressed size of the JS and CSS files. This much data needs to be downloaded over network.

Generated by performance advisor bot at iscalypsofastyet.com.

@noahtallen
Copy link
Member Author

noahtallen commented Jan 17, 2023

I think ICFY is broken. Supposedly only "3669" bytes added, but the breakdown has the same number for everything

image

Edit: and also seems to only be broken in this branch

@tyxla
Copy link
Member

tyxla commented Jan 18, 2023

This appears to work for me great locally! Nice work @noahtallen!

I've run yarn run analyze-icfy locally and didn't reproduce the issue with similar stats. Perhaps @jsnajdr might have an idea of what's going on there.

@anomiex
Copy link
Contributor

anomiex commented Jan 18, 2023

I see eslint-plugin-wpcalypso still has a peer dep on eslint-plugin-jsdoc ^37.5.1, which doesn't declare support for node 18. An upgrade to at least 39.2.5 will be needed for that.

@jsnajdr
Copy link
Member

jsnajdr commented Jan 18, 2023

I think ICFY is broken. Supposedly only "3669" bytes added, but the breakdown has the same number for everything

That means that 3670 bytes were added not to the actual async-* chunks themselves, but to a (hidden) shared chunk that's shared between all of them. Then each of the async-* chunks grows by 3670 bytes, because we need to load more to load it, and the total delta is also just 3670 bytes, because the one bigger shared chunk counts only once.

@sgomes implemented this smart calculation method in Automattic/icfy#27.

A detailed view of the chunk deltas is visible on the ICFY page for the branch: http://iscalypsofastyet.com/p/branch?branch=update-to-node-18

The GitHub comments report only the "chunk groups" deltas (chunk group, in webpack lingo, is the set of "physical" chunks needed to load one "user-visible" chunk), and only in the "chunk delta" section you can see the actual offending shared chunk: it's the JSON file for the moment-timezone cache.

It's strange that the moment-timezone cache has grown so much, from 60kB to 360kB. The module apparently compresses very well, so the gzipped delta is much smaller, but moment-timezone is certainly worth a look -- what has changed?

@kraftbj
Copy link
Contributor

kraftbj commented Jan 18, 2023

@anomiex set up a Jetpack PR to update our side to v18, which looks good so far. I think Jetpack will be in position to merge ours when the Calypso one is ready to help developers not have to Node switch. Automattic/jetpack#28450

@noahtallen
Copy link
Member Author

noahtallen commented Jan 18, 2023

and only in the "chunk delta" section you can see the actual offending shared chunk: it's the JSON file for the moment-timezone cache.

Ahh that makes sense. Thanks for clarifying! That's very useful to know about.

what has changed?

We're updating it from 0.5.31 to 0.5.40, because the older version doesn't support Node 18. (Seemingly related to compatibility in the crypto library. See this error message.)

Looking at the changelog, I think the only thing which would impact us is the IANA TZDB updates. There are several of these. The old version was on TZDB version 2020a, and now it's on 2022g. From what I can tell, the other changes are mostly internal (like fixes in their grunt build or types).

However, I did find this issue: moment/moment-timezone#999, with the comment here being kinda helpful. They're exploring compression to bring down the size.

And this points back to this other issue about the package being too small, which I see @jsnajdr commented on at the time. 😆

From what I can tell, it sounds like the older version was missing data which now exists in the current version.

Buuuut, this doesn't explain why the moment timezone webpack plugin is including more data now.

My theory is that we're now including data from two more years of timezones, due to the database updates. But I don't understand why that's 300+KB of data.

I see eslint-plugin-wpcalypso still has a peer dep on eslint-plugin-jsdoc ^37.5.1, which doesn't declare support for node 18. An upgrade to at least 39.2.5 will be needed for that.

Added! See this PR: #72308

@noahtallen
Copy link
Member Author

@jsnajdr Let me know what you think about the moment timezone change. I'm not sure how to proceed with that!

@sgomes
Copy link
Contributor

sgomes commented Jan 19, 2023

It's strange that the moment-timezone cache has grown so much, from 60kB to 360kB. The module apparently compresses very well, so the gzipped delta is much smaller, but moment-timezone is certainly worth a look -- what has changed?

I just wanted to add a small note that even though it compresses well and thus isn't much of a problem on the network side, this can still be a large problem on the CPU side. CPU time scales with uncompressed code size, so this could potentially be introducing significant extra init time on slower systems with underpowered CPUs.

If you find that to be the case, let me know and I'll see what I can do to help! 👍

@jsnajdr
Copy link
Member

jsnajdr commented Jan 19, 2023

Let me know what you think about the moment timezone change. I'm not sure how to proceed with that!

My conclusion is that the increase in size is expected and we can proceed with this Node 18 upgrade PR as is. It upgrades moment-timezone from 0.5.31 to 0.5.40 and the source file in the new moment-timezone really is bigger:

0.5.31 (trunk):

$ ls -l node_modules/moment-timezone/data/packed/latest.json
-rw-r--r--  1 jsnajdr  staff  190712 Jan 19 14:49 node_modules/moment-timezone/data/packed/latest.json

0.5.40 (this branch)

$ ls -l node_modules/moment-timezone/data/packed/latest.json
-rw-r--r--  1 jsnajdr  staff  770755 Jan 19 14:38 node_modules/moment-timezone/data/packed/latest.json

The moment-timezone-data-webpack-plugin makes the JSON file smaller, but the 4x-6x ratio still remains.

In the newer moment-timezone they just fixed the moment/moment-timezone#768 bug. If you look at this ICFY comment from a Calypso moment-timezone upgrade PR back from 2019, you'll see exactly the same size delta, just reversed. We're just going back to normal now 🙂

But there's one path to make our moment-timezone bundle smaller. In the moment/moment-timezone#999 (comment) comment @noahtallen mentioned, this bit is interesting:

Along with the packed JSON file, each Moment Timezone release also contains 4 different pre-built files with different data ranges:

  • All possible data (either 32-bit or 64-bit range depending on the release version).
  • 1970-2030.
  • 2012-2022 (for backward compatilibity).
  • A rolling 10-year range that changes based on the year the release was built.

When importing the moment-timezone package, by default it loads the index.js file that imports the moment-timezone code, and then the latest.json data. In the /builds subdirectory there are versions that bundle the data inline:

node_modules/moment-timezone/builds:
total 4048
-rw-r--r--  1 jsnajdr  staff   55105 Jan 19 14:54 moment-timezone-with-data-10-year-range.js
-rw-r--r--  1 jsnajdr  staff   42455 Jan 19 14:54 moment-timezone-with-data-10-year-range.min.js
-rw-r--r--  1 jsnajdr  staff  148294 Jan 19 14:54 moment-timezone-with-data-1970-2030.js
-rw-r--r--  1 jsnajdr  staff  135644 Jan 19 14:54 moment-timezone-with-data-1970-2030.min.js
-rw-r--r--  1 jsnajdr  staff   56919 Jan 19 14:54 moment-timezone-with-data-2012-2022.js
-rw-r--r--  1 jsnajdr  staff   44269 Jan 19 14:54 moment-timezone-with-data-2012-2022.min.js
-rw-r--r--  1 jsnajdr  staff  787944 Jan 19 14:54 moment-timezone-with-data.js
-rw-r--r--  1 jsnajdr  staff  775294 Jan 19 14:54 moment-timezone-with-data.min.js
-rw-r--r--  1 jsnajdr  staff    7088 Jan 19 14:54 moment-timezone.min.js

For WordPress, the 1970-2030 build looks ideal: it can correctly format all plausible post dates. The 10-year-range and 2012-2022 don't go back far enough to show all old WP.com blogs. And the 150k size is very nice, close to what we had before this upgrade PR.

@sgomes
Copy link
Contributor

sgomes commented Jan 19, 2023

Ideally, there would be a version of moment-timezone that would make use of DateTimeFormat's built-in support for timezones, instead of shipping the massive IANA database... All of our supported browsers would handle that just fine.

@noahtallen
Copy link
Member Author

there would be a version of moment-timezone that would make use of DateTimeFormat's built-in support for timezones

Supposedly, this is what it does: https://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/:

Moment Timezone uses the Internationalization API (Intl.DateTimeFormat().resolvedOptions().timeZone) in supported browsers to determine the user's time zone.

It seems to use this for the .guess function. I don't know if that extends to all the other timezone calculations we seem to use, or if that's possible 🤔


For WordPress, the 1970-2030 build looks ideal: it can correctly format all plausible post dates. The 10-year-range and 2012-2022 don't go back far enough to show all old WP.com blogs. And the 150k size is very nice, close to what we had before this upgrade PR.

Interestingly, we do set the startYear in the webpack plugin:

new MomentTimezoneDataPlugin( {
startYear: 2000,
cacheDir: path.resolve( cachePath, 'moment-timezone' ),
} ),

This is supposed to "Only include data from this year onwards." Does this mean the webpack plugin isn't cutting out enough data?

If so, how would we use one of those builds? Just change our import statements everywhere?


I'm thinking at this point, given we won't deploy this today and tomorrow is Friday, we'll probably land this next week :)

@jsnajdr
Copy link
Member

jsnajdr commented Jan 19, 2023

Does this mean the webpack plugin isn't cutting out enough data?

Starting with year 2000 seems fine to me. WordPress history starts in 2003, so it should be format all WordPress dates. But starting in 2012 or 2013 is too late.

@noahtallen
Copy link
Member Author

Starting with year 2000 seems fine to me

Right... but this is the current behavior of the branch including the big size increase 🤔

@gilmoreorless
Copy link

Hiya, drive-by comment from the person somewhat responsible for your moment-timezone woes 😅. I'll address/clarify a few things.

First up, the error:0308010C:digital envelope routines::unsupported came from the mtz webpack plugin. Release 1.5.1 specifically addressed it for Node 18.

This is supposed to "Only include data from this year onwards." Does this mean the webpack plugin isn't cutting out enough data?

I think the problem here is that most of the added data in the latest moment-timezone releases is after 2038. The expanded 64-bit data range extends past the year 2400. I suggest also adding an endYear option in the webpack plugin's config.

Ideally, there would be a version of moment-timezone that would make use of DateTimeFormat's built-in support for timezones, instead of shipping the massive IANA database

Given how much of the internals would need to change to rely on Intl instead of custom JSON, that would be almost like writing a whole new library. Which is basically what Luxon is. With moment and moment-timezone now in maintenance-only mode, it might be worth looking at other libraries in the long term. (Or waiting until Temporal is ready.)

@jsnajdr
Copy link
Member

jsnajdr commented Jan 20, 2023

The expanded 64-bit data range extends past the year 2400. I suggest also adding an endYear option in the webpack plugin's config.

Thank you @gilmoreorless, this is a great suggestion. I pushed a commit setting endYear: 2030 and now the moment-timezone data are back to the original size, with a very little delta:

Screenshot 2023-01-20 at 10 08 05

@noahtallen
Copy link
Member Author

noahtallen commented Jan 20, 2023

First up, the error:0308010C:digital envelope routines::unsupported came from the mtz webpack plugin. Release 1.5.1 specifically addressed it for Node 18.

Cool, this is super helpful to know! I saw the error coming from moment-timezone in the build, and decided to update the related packages.

Or waiting until Temporal is ready

We're definitely looking forward to Temporal!

I pushed a commit setting endYear: 2030 and now the moment-timezone data are back to the original size, with a very little delta:

Fantastic. I think we should be ready to merge this Monday then!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants