Description
When building server-side logic using Expo API Routes (+api.ts), Metro fails to bundle and execute Node.js native binary modules (such as better-sqlite3, which relies on the bindings package).
This results in a two-stage failure:
- Initial Error: It throws
ReferenceError: __non_webpack_require__ is not defined because bindings attempts to use this global variable to bypass bundler interception, but Metro doesn't provide it.
- Secondary Error: Even after forcing a polyfill (
globalThis.__non_webpack_require__ = require;), Metro's internal require system intercepts the call and throws Error: Requiring unknown module "..." because it cannot resolve or process .node binary files.
Since Expo API Routes run in a Node.js environment on the server side, Metro should ideally have a mechanism to handle or bypass native Node binaries smoothly.
Steps to Reproduce
- Set up an Expo project with API Routes enabled.
- Install
better-sqlite3 and @prisma/adapter-better-sqlite3.
- Initialize and call the Prisma/SQLite client inside any
+api.ts route.
- Trigger the API route.
Actual Behavior & Logs
First error encountered:
ReferenceError: __non_webpack_require__ is not defined
at bindings (node_modules/bindings/bindings.js:93:9)
at new Database (node_modules/better-sqlite3/lib/database.js:48:64)
After polyfilling __non_webpack_require__:
Error: Requiring unknown module "/path/to/better_sqlite3.node". If you are sure the module exists, try restarting Metro.
at unknownModuleError (node_modules/expo/node_modules/@expo/cli/build/metro-require/require.js:282:12)
Expected Behavior
Metro's server-side environment should:
- Provide a standard way to bypass bundler rewriting for native modules (or support
__non_webpack_require__ / an equivalent external exclusion).
- Successfully resolve and execute
.node binary files when running in a pure Node.js server context.
Environment
- Framework: Expo (with Expo Router API Routes)
- Bundler: Metro
- Packages involved:
better-sqlite3, bindings, @prisma/client
I would love to contribute to this, I'm willing to open a Pull Request to fix this issue.
Description
When building server-side logic using Expo API Routes (
+api.ts), Metro fails to bundle and execute Node.js native binary modules (such asbetter-sqlite3, which relies on thebindingspackage).This results in a two-stage failure:
ReferenceError: __non_webpack_require__ is not definedbecausebindingsattempts to use this global variable to bypass bundler interception, but Metro doesn't provide it.globalThis.__non_webpack_require__ = require;), Metro's internal require system intercepts the call and throwsError: Requiring unknown module "..."because it cannot resolve or process.nodebinary files.Since Expo API Routes run in a Node.js environment on the server side, Metro should ideally have a mechanism to handle or bypass native Node binaries smoothly.
Steps to Reproduce
better-sqlite3and@prisma/adapter-better-sqlite3.+api.tsroute.Actual Behavior & Logs
First error encountered:
After polyfilling
__non_webpack_require__:Expected Behavior
Metro's server-side environment should:
__non_webpack_require__/ an equivalent external exclusion)..nodebinary files when running in a pure Node.js server context.Environment
better-sqlite3,bindings,@prisma/clientI would love to contribute to this, I'm willing to open a Pull Request to fix this issue.