Support Node native modules (.node) and __non_webpack_require__ in Expo API Routes / Metro server environment
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 5.6k
- Forks
- 696
- Avg merge
- 8m
- Merged PRs (30d)
- 7
Description
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 definedbecausebindingsattempts 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 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
- Set up an Expo project with API Routes enabled.
- Install
better-sqlite3and@prisma/adapter-better-sqlite3. - Initialize and call the Prisma/SQLite client inside any
+api.tsroute. - 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
.nodebinary 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the failure with an Expo API route using better-sqlite3, then read node_modules/bindings/bindings.js, node_modules/better-sqlite3/lib/database.js, and Expo's metro-require/require.js around the reported errors. Determine how Metro's server environment should handle non_webpack_require and .node files; done means the route loads and executes the native module without either reported error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- backend, build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100