Reviving an old Electron app

Today I needed to use a personal project I'd built and last modified 5 years ago. I followed the readme and installed dependencies. As expected, it wasn't smooth.

MacOS

First I had to install grunt.

npm install -g grunt-cli

added 56 packages, and audited 57 packages in 3s

5 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
npm notice 
npm notice New major version of npm available! 8.19.3 -> 10.9.2
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.9.2
npm notice Run npm install -g npm@10.9.2 to update!

Oh I can update npm? Let's do it

% npm install -g npm@10.9.2
npm ERR! code EBADENGINE
npm ERR! engine Unsupported engine
npm ERR! engine Not compatible with your version of node/npm: npm@10.9.2
npm ERR! notsup Not compatible with your version of node/npm: npm@10.9.2
npm ERR! notsup Required: {"node":"^18.17.0 || >=20.5.0"}
npm ERR! notsup Actual:   {"npm":"8.19.3","node":"v16.17.0"}

Oh, I have node 16 and it requires at least node 18. Fine, let's skip for now and simply install dependencies.

So much red!

npm ERR! info sharp Downloading https://github.com/lovell/sharp-libvips/releases/download/v8.7.0/libvips-8.7.0-darwin-armv8.tar.gz
npm ERR! /Users/anhtuan/git/bestpick/phone/www/node_modules/sharp/install/libvips.js:81
npm ERR!           throw new Error(`Status ${response.statusCode}`);
npm ERR!           ^
npm ERR! 
npm ERR! Error: Status 404
npm ERR!     at /Users/anhtuan/git/bestpick/phone/www/node_modules/sharp/install/libvips.js:81:17

First it looks like it downloads some binary of sharp, and since it's an old version, it's not hosted by their CDN anymore.

Let's update the dependency

The next time I run npm i, I get a similar error for electron.

npm ERR! code 1
npm ERR! path /Users/anhtuan/git/bestpick/phone/www/node_modules/electron
npm ERR! command failed
npm ERR! command sh -c -- node install.js
Downloading tmp-60315-0-electron-v4.0.4-darwin-arm64.zip
npm ERR! Error: GET https://github.com/electron/electron/releases/download/v4.0.4/electron-v4.0.4-darwin-arm64.zip returned 404
npm ERR! /Users/anhtuan/git/bestpick/phone/www/node_modules/electron/install.js:49
npm ERR!   throw err
npm ERR!   ^
npm ERR! 
npm ERR! Error: Failed to find Electron v4.0.4 for darwin-arm64 at https://github.com/electron/electron/releases/download/v4.0.4/electron-v4.0.4-darwin-arm64.zip

So I go to https://www.npmjs.com/package/electron and find the latest version.

When I try to install it, this time it complains about Node.

% npm i
npm WARN old lockfile 
npm WARN old lockfile The package-lock.json file was created with an old version of npm,
npm WARN old lockfile so supplemental metadata must be fetched from the registry.
npm WARN old lockfile 
npm WARN old lockfile This is a one-time fix-up, please be patient...
npm WARN old lockfile 
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'sharp@0.33.5',
npm WARN EBADENGINE   required: { node: '^18.17.0 || ^20.3.0 || >=21.0.0' },
npm WARN EBADENGINE   current: { node: 'v16.17.0', npm: '8.19.3' }
npm WARN EBADENGINE }
npm WARN deprecated boolean@3.2.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

Luckily I already have nvm installed.

% nvm

Node Version Manager (v0.37.2)
...
nvm install --lts                     Install the latest LTS version
nvm use --lts                         Use the latest LTS version

% nvm use --lts
Now using node v18.18.0 (npm v10.1.0)
anhtuan@MacMini www % nvm install --lts
Installing latest LTS version.
Downloading and installing node v22.12.0...
Downloading https://nodejs.org/dist/v22.12.0/node-v22.12.0-darwin-arm64.tar.xz...
################################################################################################################################################################################################## 100.0%
Computing checksum with shasum -a 256
Checksums matched!
Now using node v22.12.0 (npm v10.9.0)

It looks like nvm use --lts uses the latest installed version of npm. Also, nvm install --lts installs and sets up the current version of Node to that version. Good to know.

Finally npm i completes without any warning

% npm i

added 1 package, and audited 83 packages in 1s

20 packages are looking for funding
  run `npm fund` for details

1 high severity vulnerability

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

The last step is to download NW.js and run the webapp with it.

cd phone/www
% ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/MacOS/nwjs .

MacOS tells me the binary is corrupted and attempts to move it to the bin.

This GitHub ticket says we can fix it with this command:

xattr -c nwjs.app

What does that command do?

xattr

That page tells me absolutely nothing. Let's ask ChatGPT:

This command uses the xattr utility on macOS to manipulate extended attributes. Here’s a breakdown of the components:

  • xattr: This command-line utility is used to view and manage extended attributes of files and directories in macOS.
  • -c: This flag tells xattr to clear all extended attributes of the specified file or directory.
  • nwjs.app: The target application or file whose extended attributes you want to clear.

Very nice! Then it says:

Checking Extended Attributes

Before clearing them, you can list the extended attributes with:

xattr -l nwjs.app

Example Output

com.apple.quarantine: 0083;00000000;Safari;1234ABCD-5678

Caution

Clearing extended attributes removes metadata, which might impact the functionality or security of the file. Be cautious when applying this to apps or files you don't fully trust.


Let's try on nwjs:

% xattr -l ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/MacOS/nwjs           
com.apple.quarantine: 0081;675ce76c;Chrome;

What does com.apple.quarantine do?

What should I do about com.apple.quarantine?
I’ve downloaded some .jar files from the internet and want to use them under Mac OS X. But the OS seems to have tagged them with the extended attribute com.apple.quarantine (no indication of this u...
This attribute is added so that it can ask for user confirmation the first time the downloaded program is run, to help stop malware. Upon confirmation the attribute should be removed automatically, and then the program will run normally.

Alright, but MacOS does not actually ask me if I am ok running it. I guess that's why I should remove the flag with the commandline. Let's try it.

% xattr -l ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/MacOS/nwjs
% ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/MacOS/nwjs .       
zsh: killed     ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/MacOS/nwjs .

Even though I cleared the quarantine flag, MacOS still says the archive is corrupted.

Then I realized that the ticket tells us to clear the flag on the .app archive, not the actual binary inside it.

% xattr -l ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app                    
com.apple.provenance: 
com.apple.quarantine: 0081;675ce76c;Chrome;

% xattr -c ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app
anhtuan@MacMini www % ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/MacOS/nwjs .
[1214/121239.031028:ERROR:zip.cc(179)] Cannot open '/Users/anhtuan/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/Resources/app.nw': FILE_ERROR_NOT_FOUND: No such file or directory (2)

Now it runs! But it is missing some file it says.

% cd Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/Resources
anhtuan@MacMini Resources % ls
af.lproj		fil.lproj		pt_BR.lproj
am.lproj		fr.lproj		pt_PT.lproj
app.icns		gu.lproj		ro.lproj
ar.lproj		he.lproj		ru.lproj
ar_XB.lproj		hi.lproj		scripting.sdef
bg.lproj		hr.lproj		sk.lproj
bn.lproj		hu.lproj		sl.lproj
ca.lproj		id.lproj		sr.lproj
cs.lproj		io.nwjs.nwjs.manifest	sv.lproj
da.lproj		it.lproj		sw.lproj
de.lproj		ja.lproj		ta.lproj
document.icns		kn.lproj		te.lproj
el.lproj		ko.lproj		th.lproj
en.lproj		lt.lproj		tr.lproj
en_GB.lproj		lv.lproj		uk.lproj
en_XA.lproj		ml.lproj		ur.lproj
es.lproj		mr.lproj		vi.lproj
es_419.lproj		ms.lproj		zh_CN.lproj
et.lproj		nb.lproj		zh_TW.lproj
fa.lproj		nl.lproj
fi.lproj		pl.lproj

Indeed the file is not there. How could the archive be incomplete? I have modified nothing.

This ticket seem to mention the node version: https://github.com/nwjs/nw.js/issues/7946

But I do have Node 22.

This one mentions packaging. Could it be that instead of a path, it expects a packaged webapp?

Getting App.nw location on OSX
We’re building a node-webkit/NW.js application for OS X and want to create a updater for the application so that it will be kept up-to-date automatically. Because we deploy the nodeJS, css and htm...

Let's check the NW.js documentation

In the Getting Started page, they do instruct to run it locally like so:

cd /path/to/your/app
/path/to/nw .
/path/to/nw is the binary file of NW.js. [...] On Mac, it’s nwjs.app/Contents/MacOS/nwjs.

Should I check out the documentation on how to package it?

https://nwjs.readthedocs.io/en/latest/For%20Users/Package%20and%20Distribute/

On Mac, put the files of your app into a folder named app.nw in nwjs.app/Contents/Resources/ and done.

Yes they do mention app.nw. But why is it that packaging might work, but not running locally?

It'd be nice if I could modify the code and always run the latest version without having to cp -R every time. Let's try a simlink.

% cd ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/           
anhtuan@MacMini Resources % ln -s ~/git/bestpick/phone/www app.nw 
anhtuan@MacMini Resources % ls app.nw 
app.nw			config.xml		img			main.js			package.json		spec.html
bower.json		css			index.html		node_modules		res			test.js
bower_components	icon.png		js			package-lock.json	spec			tests
anhtuan@MacMini Resources % ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/MacOS/nwjs

This time there is no error and the NW.js icon pops up in my task bar. However nothing shows up.

Seems unlikely but... Could it be that symlinks won't work?

% rm -rf app.nw
% cp -R ~/git/bestpick/phone/www app.nw
% ~/Downloads/nwjs-v0.94.0-osx-arm64/nwjs.app/Contents/MacOS/nwjs

Same results. It hangs.

I am not willing to put in anymore effort on it on MacOS. Let's try on Windows, and if it does not work, this webapp is officially dead.

Windows

> bower
bower : 이 시스템에서 스크립트를 실행할 수 없으므로 C:\Users\[username]\AppData\Roaming\npm\bower.ps1 파일을 로드할 수
없습니다. 자세한 내용은 about_Execution_Policies(https://go.microsoft.com/fwlink/?LinkID=135170)를 참조하십시오.
위치 줄:1 문자:1
+ bower
+ ~~~~~
    + CategoryInfo          : 보안 오류: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess

Even though I ran it in a Terminal window as Admin, it says UnauthorizedAccess.

The Bower website also simply says "install bower", run "bower install". What a joke.

Instead I try this

npm exec bower install
bower                     invalid-meta for:C:\Users\atn83\git\bestpick\phone\www\bower.json
bower                     invalid-meta The "name" is recommended to be lowercase, can contain digits, dots, dashes

It does seem to have run. They must have added new rules to app names since. Let's tweak the name and run the command again. Finally it works:

This time since we're on Windows, we can run the app by drag and dropping the webapp code into nw.exe. See https://nwjs.readthedocs.io/en/latest/For Users/Getting Started/:

Drag & Drop on Windows
On Windows, you can drag the folder containing package.json to nw.exe to run your app.

Let's accept

Aaaaaand still an empty window.

Good bye webapp

It was good while it lasted...

This reinforces my conviction that after 15 years, web development and Electron is really not for me anymore. It is just too much of a mess. Flutter for the win!