The reason why sqlite3 won’t behave is threefold:
- When node sqlite3 is installed using
npm install sqlite3, it fetches all dependencies and installs it. It then fetches the precompiled binary binding file for the target arch and platform. In my case we would want
napi-v6-darwin-unknown-arm64for ARM64 and darwin for Apple M1. There is no precompiled binary available yet for this Apple ARM64 and even if there is, the next paragraph will detail why it still won’t work.
- The problem is that it determines the the system’s platform and architecture using the binary compiling package
node-pre-gypand this very savior of a Github issue details how
node-pre-gypis not handling ARM architecture detection properly and basically mixing everything up. Because it’s not detecting properly, even if we build our own binding with
--build-from-sourcewhen installing, it still won’t work because it is compiling the wrong binding file for the wrong architecture. To make matters worse, if we don’t use
--build-from-source, it just simply fetches the Intel precompiled binding file.
- Now for some reason, during runtime, it now detects the architecture properly and tries to look for the ARM64 version of the binding file, it won’t find it and will throw the feared error ‘module not found’ for
napi-v6-darwin-unknown-arm64. It obviously won’t find it and even if it does, it will throw wrong architecture error because we have the Intel version on board
The magic solution
npm uninstall sqlite3
Install a fresh sqlite3, build it from source, specify the target arch and use fallback build with node-pre-gyp just to be safe:
npm install sqlite3 --build-from-source --target_arch=arm64 --fallback-to-build
Now the correct binding file is compiled for the correct platform and architecture, on runtime it will find it and will run!