react / react/metro

Support Node native modules (.node) and __non_webpack_require__ in Expo API Routes / Metro server environment

Open
#1,761 0 comments 0 reactions 0 assignees View on GitHub

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:

  1. 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.
  2. 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
  1. Set up an Expo project with API Routes enabled.
  2. Install better-sqlite3 and @prisma/adapter-better-sqlite3.
  3. Initialize and call the Prisma/SQLite client inside any +api.ts route.
  4. 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:

  1. Provide a standard way to bypass bundler rewriting for native modules (or support __non_webpack_require__ / an equivalent external exclusion).
  2. 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.