vercel / ncc

Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.
https://npmjs.com/@vercel/ncc
MIT License
8.99k stars 285 forks source link

ncc and prebuildify #1183

Closed sroussey closed 2 months ago

sroussey commented 2 months ago

I help maintain a few npm packages. I use prebuildify and prebuild all the versions of the binary .node files. All are included in the npm package itself so no install scripts need run (and the binary files are small anyway). Also, newer things like bun don't support lifecycle scripts out of the box, and you have to declare that your trust each one in order to run them.

People using ncc don't get the binary .node files however in this scenario.

How can I best alter the various npm packages such that ncc will recognize them, or will it never work because the npm package has binaries for multiple architectures?

styfle commented 2 months ago

require('./hello.node') will be statically analyzed properly

There's an integration test here https://github.com/vercel/ncc/blob/main/test/integration/binary-require.js

If you're running into a problem, its likely because you're doing dynamic require which can't be statically analyzed easily, something like function dynamic(str) { return require(str) }

The partially dynamic case should also work, something like function prebuildPath(str) { return path.join(__dirname, 'prebuild', str) } since the prefix is statically analyzable so the entire directory can be included.

sroussey commented 2 months ago

Yes, stuff is dynamic. I was able to get around it by adding this:

// dummy code for ncc to include the native module
if (process.uptime() < 0) {
  require(__dirname + "/../../../prebuilds/darwin-arm64+x64/usearch.node");
  require(__dirname + "/../../../prebuilds/linux-arm64/usearch.node");
  require(__dirname + "/../../../prebuilds/linux-x64/usearch.node");
  require(__dirname + "/../../../prebuilds/win32-ia32/usearch.node");
  require(__dirname + "/../../../prebuilds/win32-x64/usearch.node");
  require(__dirname + "/../../../build/Release/usearch.node");
}
styfle commented 2 months ago

Great, I'll close this issue since its working 👍