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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions