Make Prisma work with bundlers like esbuild

The Prisma client library is not just javascript files. It looks for a query engine binary as well as the Prisma schema file at runtime.

Query engine binary

Prisma is not just a Javascript library, its query engine is written in Rust and compiled to native. At runtime, Prisma expects to find the query engine binary at pre-defined locations in node_modules. For example, if you use pnpm to manage dependencies, these are locations that Prisma will look for its query engine binary

  • working script directory
  • /tmp/prisma-engines
  • .node_modules directory
const searchLocations: string[] = [
  config.dirname, // generation directory
  path.resolve(dirname, '..'), // generation directory one level up
  config.generator?.output?.value ?? dirname, // custom generator local path
  path.resolve(dirname, '../../../.prisma/client'), // dot prisma node_modules ???
  '/tmp/prisma-engines', // used for netlify
  config.cwd, // cwdPath, not cwd
]

Prisma code that looks for query engine library

When we use bundlers like esbuild, binary files are not included by default. Therefore, without extra steps, it will result in error like this

Invalid `prisma.nextgenSync.findFirst()` invocation:

Prisma Client could not locate the Query Engine for runtime "linux-musl-openssl-3.0.x"

It's essential to copy the binary output the build directory. Bundlers like Webpack has copy plugins to move file to the output folder, which can be found in the reference link below. If you are using esbuild, you can try on the esbuild-plugin-copy to move file to your output folder.

Why does Prisma need to build its query engine in Rust. The most likely reason is to go after performance gain, but we will need to jump deeper into the source code to understand why it's important as most of the querying is handled by Database engines, not at the ORM level.

Prisma.schema file

This is the file in which users define data models. It should also be copied to the build output folder. Otherwise, you will get this error at runtime:

thread 'main' panicked at 'Could not open datamodel file "/webapp/node_modules/.pnpm/@prisma+client@5.5.2_prisma@5.5.2/node_modules/.prisma/client/schema.prisma"', query-engine/query-engine/src/opt.rs:246:53

Again, i wonder if Prisma could have simplified the process by not requiring this file at runtime since most of the information contained there has also been implicit in the generated @prisma/client code.

References

Module bundlers (Reference)
This page gives an overview of the most important things to be aware of when using a module bundler to bundle an application that uses Prisma Client.
prisma/packages/client/src/runtime/core/engines/common/resolveEnginePath.ts at e8861e48ba45dd210205f4e5c8a56916a59dba19 · prisma/prisma
Next-generation ORM for Node.js & TypeScript | PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, MongoDB and CockroachDB - prisma/prisma