RefugeRestrooms / refugerestrooms

REFUGE restrooms indexes and maps safe restroom locations for trans, intersex, and gender nonconforming individuals.
http://www.refugerestrooms.org
GNU Affero General Public License v3.0
892 stars 262 forks source link

Update app to run on Node 18 or newer (NodeJS 16 has reached End of Support) #682

Open DeeDeeG opened 1 year ago

DeeDeeG commented 1 year ago

See:

NodeJS 16 has reached End of Support as of 11th September 2023.

We should update some things to get the app running on newer NodeJS, which for still-supported versions would be Node 18 or newer.

I tried to do so during https://github.com/RefugeRestrooms/refugerestrooms/pull/678, but ran into issues with our older version of Webpack not working with Node 18, and it not being obvious to me personally how to properly migrate to newer Webpack either.

If anyone can help get the app running and functional (passing our CI tests, etc.), that would be much appreciated! I'm marking this issue as "Help Wanted" just in case it helps draw attention from some helpful folks to get us past this tech stack upgrade. Thanks in advance for any help with this.

Best Regards, - DeeDeeG

DeeDeeG commented 1 year ago

Posting my notes from the commit message of https://github.com/RefugeRestrooms/refugerestrooms/pull/678/commits/562e635557ef5cf931a35fb23eaa5c7412be7480 (from PR https://github.com/RefugeRestrooms/refugerestrooms/pull/678), in case it is helpful:

We can't use NodeJS 18 until we work through this issue: https://github.com/webpack/webpack/issues/14532

There was a default hashing algorithm for webpack (md4) that is now considered quite old/obsolete/flawed. It was removed from OpenSSL 3.0. OpenSSL 3.0 is the version of OpenSSL used in NodeJS 17 and up.

In order to use an LTS version of Node that will receive long-term support over the next months, but not hit this issue where webpack errors out due to the md4 hash algorithm not being available in Node 17+, we need to stay on NodeJS 16.x for the time being.

NOTE: NodeJS 16.x will be EOL on the 11th of September 2023, matching the EOL date for OpenSSL 1.1.1.

See: https://nodejs.org/en/blog/announcements/nodejs16-eol/ https://github.com/nodejs/release#release-schedule

So this workaround only buys us time until September of this year!!

The "proper" fix for this would be updating to webpack 5 and webpacker 6.x (which was never given a final release, but got as far as a release candidate), or move to something that is actively supported, like the alternatives discussed here: https://world.hey.com/dhh/rails-7-will-have-three-great-answers-to-javascript-in-2021-8d68191b https://rubyonrails.org/2021/12/6/Rails-7-0-rc-1-released

ice1080 commented 10 months ago

Hey @DeeDeeG I did some work on this one and from what I can tell, it looks like webpacker did release a version 6.0.0.rc, but the npm package @rails/webpacker did not, which is something else this project relies on. I'll attempt a few other things, but not sure this one is going to be possible without upgrading rails to v7 (which probably needs its own issue if it doesn't already have one).

DeeDeeG commented 10 months ago

On the topic of webpacker 6:

I believe the closest thing is either the @rails/webpacker 6.0.0.rc.6 tag (https://github.com/rails/webpacker/tags), as you mentioned, or shakapacker, the "official successor ro rails/webpacker" (whatever that means, since it's rather unconventional): https://github.com/shakacode/shakapacker.

As for the git tag of @rails/webpacker, it is possible to specify JS dependencies as a git URL, such as "@rails/webpacker": "https://github.com/rails/webpacker#v6.0.0.rc.6" in package.json. Although I have not tested to see if this works or required the webpacker team to do some further packaging steps before publishing it, in order for it to be usable.

I did try to upgrade to newer webpack + webpacker myself, but the configuration files and project setup for using Webpack are very unfamiliar to me, the docs weren't clear enough to me, and I got stuck somewhere through attempting this myself. Anyone more familiar with Webpack might have more success with this, hopefully.

On the topic of Rails 7:

Yes, if we can manage to upgrade to Rails 7 in all this, or even by itself without breaking anything else, that would be welcome in its own right.

Last time we got to Rails 6, I was expecting it to require a large migration effort, but someone upgraded Rails 6 in-place over Rais 5 with essentially no further changes. (Here: https://github.com/RefugeRestrooms/refugerestrooms/commit/520e8c5e95a825c37c54ab52d579d6e13f906a95 from https://github.com/RefugeRestrooms/refugerestrooms/pull/675.)

(I have been nervous to attempt this myself, but perhaps it will "just work" updating Rails to version 7 in the Gemfile? Even if not, upgrading to Rails 7 would be welcome.)

DeeDeeG commented 10 months ago

It's possible we can "cheat" a bit, or use a workaround, by exporting the environment variable NODE_OPTIONS=--openssl-legacy-provider in the environment where the app runs.

I can easily add it as an env var (and bump to newer NodeJS) in the Dockerfile in the root of this repo, to test that out with a newer NodeJS version. And then it would require one of the other maintainers' cooperation in order to set this env var in our Heroku environment as well, if this is something proven to work.

I will take some time to test this today, as a quick/minimal approach with the goal of getting to Node 18.

(I reviewed the issue thread https://github.com/webpack/webpack/issues/14532 again recently, and from a comment in that thread, I noticed this suggested workaround. Not sure why I hadn't tried this earlier, other than the want to properly upgrade anyway making "workarounds" seem like the wrong approach at the time. But since NoeJS 16 support is over, now may be the time for whatever quickest/smallest fix is possible.)

DeeDeeG commented 10 months ago

The workaround env var + bumping to NodeJS 18 (or 20) seems to be working.

And I believe I can set the env var for production via the Heroku app configuration file app.json. So, I will propose this as a PR and give the other maintainers a chance to review it, otherwise I will wish to go ahead with it if no feedback from them.

Being stuck on unsupported NodeJS isn't great. I consider this part of my ongoing dependency bumps.