Open achou11 opened 1 year ago
Ah, looks like I missed an important detail about how nmrn works. Seems like it'll copy the relevant native assets directory and place it in the nodejs-project (at runtime?):
So given a dir.list
that looks like:
node_modules
node_modules/sodium-native
node_modules/sodium-native/build
node_modules/sodium-native/build/Release
and a file.list
that looks like:
node_modules/sodium-native/build/Release/sodium.node
it should produce the following path:
/data/data/com.myapp/files/nodejs-project/node_modules/sodium-native/build/Release/sodium.node
Guess node-gyp-build
is assuming that it's being passed /data/data/com.myapp/files/nodejs-project/node_modules/sodium-native
while in my case, it's being given /data/data/com.myapp/files/nodejs-project/
, which isn't enough for it to work with I guess
Can someone confirm that this file copying only happens at runtime? i.e. I wouldn't be able to analyze the apk and see the copied over files/directories within the nodejs-project
directory
Also realizing that part of the issue may be how I'm bundling the app. Using Rollup with the esm-shim
plugin, which shims __dirname
but to the created bundle file (i.e. absolute path to directory containing index.js
) so the original directory references for the modules using that aren't preserved.
Not really sure if there's a way to work around that though, so still need to explore my options.
- Expose some kind of env variable that points to it
- A module that you can swap out with node-gyp-build that knows about the NodeJS mobile directory structure
Yes, I think (2) would be ideal because anyway both (1) and (2) require changing (or patching) the native addon repo, which is less than ideal, but (2) hides implementation details more than (1) does (in fact, (1) could be just one way of achieving (2)). In other projects using nodejs-mobile, I also discovered the need for such a package. We basically just need node-gyp-build
(or bindings
or whatever) to accommodate for the existence of nodejs-mobile
.
Guess
node-gyp-build
is assuming that it's being passed/data/data/com.myapp/files/nodejs-project/node_modules/sodium-native
while in my case, it's being given/data/data/com.myapp/files/nodejs-project/
, which isn't enough for it to work with I guessCan someone confirm that this file copying only happens at runtime? i.e. I wouldn't be able to analyze the apk and see the copied over files/directories within the
nodejs-project
directory
Strong yes to both of these paragraphs. In other projects I have used esbuild and/or patch-package to hack the path pointing to the native addon.
Also realizing that part of the issue may be how I'm bundling the app. Using Rollup with the
esm-shim
plugin
Might be. I don't have experience with Rollup, and I've used esbuild before which neatly handled __dirname
and ESM files.
Note: we have node-gyp-build-mobile that was created to solve a very different problem (patching the bin.js
that gets run in the terminal during package install) but could be a good home for new runtime logic.
Attempting to use some modules from the Holepunch ecosystem that have native counterparts but due to assumptions it makes about the project structure, a runtime error occurs related to trying to load the native module:
Will use
sodium-native
as the example since this error is stemming from there, but this issue applies to any module that usesnode-gyp-build
for loading native bindings.Noticed that
sodium-native
uses__dirname
to tellnode-gyp-build
where to start looking for the native binding:https://github.com/sodium-friends/sodium-native/blob/b4d2fec3262cb75a5d136046f56b5697606fe252/index.js
Unfortunately, in the context of a NodeJS Mobile React Native project,
__dirname
resolves to/data/data/com.myproject/files/nodejs-project
(as seen in error message above)This error comes from https://github.com/prebuild/node-gyp-build/blob/8419abba399ec01f28cfb02b207b659153052a69/node-gyp-build.js#L60
Their resolution strategy lives in https://github.com/prebuild/node-gyp-build/blob/8419abba399ec01f28cfb02b207b659153052a69/node-gyp-build.js#L62-L74
My understanding of the directory structure that NodeJS mobile creates for my application is generally as follows (other targets+archs omitted for brevity):
Wondering how NodeJS Mobile tells the application that it should look in the
nodejs-native-assets/nodejs-native-assets-arm64-v8a/node_modules/...
directory for loading native bindings.Think there are a couple of potential solutions:
node-gyp-build
to use the relevant native assets directory instead of__dirname
. For example,sodium-native
index file would look like:node-gyp-build
that knows about the NodeJS mobile directory structure, which you would use with a bundler. This is similar to what @staltz has for Noderify: https://github.com/staltz/bindings-noderify-nodejs-mobile.My guess is that 2 is probably a better solution because it wouldn't require patching every module. Only downside is that it assumes that you're using a bundler that allows you to swap out modules, which is recommended but not ideal to assume.
Environment info:
OS: macOS 14 (Sonoma) NodeJS Mobile version: 16.17.10 NPM version: 8.19.4