prisma / prisma

Next-generation ORM for Node.js & TypeScript | PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, MongoDB and CockroachDB
https://www.prisma.io
Apache License 2.0
39.46k stars 1.54k forks source link

Cloudflare Pages + Neon + Remix not working #23536

Closed HenrikFricke closed 7 months ago

HenrikFricke commented 7 months ago

Bug description

I tested the new adapter for Neon databases, but I'm not able to start the Remix dev server. The error message:

TypeError: WebAssembly.Instance(): Argument 0 must be a WebAssembly.Module
at null.<anonymous> (file:///…/node_modules/@prisma/client/runtime/wasm.js:11:895)
      at async Object.loadLibrary (file:///…/node_modules/@prisma/client/runtime/wasm.js:11:985)
      at async gt2.loadEngine (file:///…/node_modules/@prisma/client/runtime/wasm.js:11:3169)
      at async gt2.instantiateLibrary (file:///…/node_modules/@prisma/client/runtime/wasm.js:11:2767)
      at async gt2.start (file:///…/node_modules/@prisma/client/runtime/wasm.js:11:4565)
      at async gt2.request (file:///…/node_modules/@prisma/client/runtime/wasm.js:11:6227)
      at async Object.singleLoader (file:///…/node_modules/@prisma/client/runtime/wasm.js:22:5571)
      at async or2.request (file:///…/node_modules/@prisma/client/runtime/wasm.js:22:6063)
      at async f (file:///…/node_modules/@prisma/client/runtime/wasm.js:27:10798)
      at async loader (file:///…/app/routes/_index.tsx:31:17) {
    clientVersion: '5.11.0'
  }

How to reproduce

  1. Create a new Remix + Cloudflare Pages stack: npx create-remix@latest --template remix-run/remix/templates/cloudflare-pages
  2. Setup Prisma following the Quickstart guide: https://www.prisma.io/docs/getting-started/quickstart
  3. Setup Prisma / Neon: https://www.prisma.io/docs/orm/prisma-client/deployment/edge/deploy-to-cloudflare#neon
  4. Create a Neon database and set DATABASE_URL in .dev.vars
  5. Run npm run dev and open a route with Prisma client

Expected behavior

The Prisma client works in Remix loader and can connect to the database.

Prisma information

Schema:

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["driverAdapters"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
}

Remix route example:

import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/cloudflare";
import { PrismaClient } from "@prisma/client";
import { PrismaNeon } from "@prisma/adapter-neon";
import { Pool } from "@neondatabase/serverless";

interface Environment {
  DATABASE_URL: string;
}

export const meta: MetaFunction = () => {
  return [
    { title: "New Remix App" },
    { name: "description", content: "Welcome to Remix!" },
  ];
};

export async function loader({ context }: LoaderFunctionArgs) {
  const neon = new Pool({
    connectionString: (context.env as Environment).DATABASE_URL,
  });
  const adapter = new PrismaNeon(neon);
  const prisma = new PrismaClient({ adapter });

  const users = await prisma.user.findMany();

  return { users };
}

export default function Index() {
  return (
    <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
      <h1>Welcome to Remix</h1>
      <ul>
        <li>
          <a
            target="_blank"
            href="https://remix.run/tutorials/blog"
            rel="noreferrer"
          >
            15m Quickstart Blog Tutorial
          </a>
        </li>
        <li>
          <a
            target="_blank"
            href="https://remix.run/tutorials/jokes"
            rel="noreferrer"
          >
            Deep Dive Jokes App Tutorial
          </a>
        </li>
        <li>
          <a target="_blank" href="https://remix.run/docs" rel="noreferrer">
            Remix Docs
          </a>
        </li>
      </ul>
    </div>
  );
}

Environment & setup

Prisma Version

prisma                  : 5.11.0
@prisma/client          : 5.11.0
Computed binaryTarget   : darwin-arm64
Operating System        : darwin
Architecture            : arm64
Node.js                 : v21.6.1
Query Engine (Node-API) : libquery-engine efd2449663b3d73d637ea1fd226bafbcf45b3102 (at node_modules/@prisma/engines/libquery_engine-darwin-arm64.dylib.node)
Schema Engine           : schema-engine-cli efd2449663b3d73d637ea1fd226bafbcf45b3102 (at node_modules/@prisma/engines/schema-engine-darwin-arm64)
Schema Wasm             : @prisma/prisma-schema-wasm 5.11.0-15.efd2449663b3d73d637ea1fd226bafbcf45b3102
Default Engines Hash    : efd2449663b3d73d637ea1fd226bafbcf45b3102
Studio                  : 0.499.0
Preview Features        : driverAdapters
jkomyno commented 7 months ago

Hey @HenrikFricke, can you please share your remix.config.js file?

HenrikFricke commented 7 months ago

@jkomyno Sure, some essential files:

remix.config.js:

/** @type {import('@remix-run/dev').AppConfig} */
export default {
  ignoredRouteFiles: ["**/*.css"],
  server: "./server.ts",
  serverBuildPath: "functions/[[path]].js",
  serverConditions: ["workerd", "worker", "browser"],
  serverDependenciesToBundle: "all",
  serverMainFields: ["browser", "module", "main"],
  serverMinify: true,
  serverModuleFormat: "esm",
  serverPlatform: "neutral",
  // appDirectory: "app",
  // assetsBuildDirectory: "public/build",
  // publicPath: "/build/",
};

server.ts:

import { logDevReady } from "@remix-run/cloudflare";
import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
import * as build from "@remix-run/dev/server-build";

if (process.env.NODE_ENV === "development") {
  logDevReady(build);
}

export const onRequest = createPagesFunctionHandler({ 
  build, 
  getLoadContext: ({ context }) => ({ env: context.cloudflare.env }), 
});

tsconfig.json:

{
  "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
  "compilerOptions": {
    "lib": ["DOM", "DOM.Iterable", "ES2022"],
    "isolatedModules": true,
    "esModuleInterop": true,
    "jsx": "react-jsx",
    "moduleResolution": "Bundler",
    "resolveJsonModule": true,
    "target": "ES2022",
    "strict": true,
    "allowJs": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "baseUrl": ".",
    "paths": {
      "~/*": ["./app/*"]
    },
    "noEmit": true
  }
}
arjunyel commented 7 months ago

@HenrikFricke Remix is now using Vite https://remix.run/docs/en/main/future/vite#getting-started

HenrikFricke commented 7 months ago

Awesome, that works! I wasn't aware I need to migrate to Vite. Thanks for your quick help 🙏

SevInf commented 7 months ago

For remix.config.js users: you can also solve the issue by excluding @prisma/client from bundled dependencies. See example here.