Skip to content

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

Description

@ensalada-de-pollo

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions