electric-sql / pglite

Lightweight WASM Postgres with real-time, reactive bindings.
https://pglite.dev
Apache License 2.0
9.49k stars 204 forks source link

Running pglite in the browser: `Error: createRequire is not a function` #322

Open AdrianLThomas opened 2 months ago

AdrianLThomas commented 2 months ago

Following the install guide here: https://pglite.dev/docs/#install-and-start-in-the-browser

I span up a new Next.js app, installed pglite, then attempted to query the version. However when pulling in pglite, I get the error: Error: createRequire is not a function

Any ideas? works fine from Node & bun environments, but I cannot get it to work purely client side in the browser.

I've pushed an example repo here:

Many thanks!

samwillis commented 2 months ago

Hey @AdrianLThomas, thanks for the report.

PGlite requires some specific Next.js configuration, we have it documented here: https://pglite.dev/docs/bundler-support#next-js

I think this issue looks like it would be solved by that, but I'll leave this issue open till you confirm as I want to be sure the docs are correct.

AdrianLThomas commented 2 months ago

Hey @samwillis thank you for the speedy response.

Unfortunately I still see the exact same error when updating the config as per those docs you linked to: Error: createRequire is not a function

It also gave me an additional warning in the terminal: Disabling SWC Minifer will not be an option in the next major version. Please report any issues you may be experiencing to https://github.com/vercel/next.js/issues

Similar story when running npm run build:

npm run build

> nextjs-pglite@0.1.0 build
> next build

 ⚠ Disabling SWC Minifer will not be an option in the next major version. Please report any issues you may be experiencing to https://github.com/vercel/next.js/issues
  ▲ Next.js 14.2.11

   Creating an optimized production build ...
 ✓ Compiled successfully
 ✓ Linting and checking validity of types    
 ✓ Collecting page data    
   Generating static pages (0/5)  [    ]TypeError: e is not a function
    at /home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:105079
    at async e.ea (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:85897)
    at async e._checkReady (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:82203)
    at async e.exec (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:73377)
    at async oa (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:87292) {
  digest: '1300995704'
}
   Generating static pages (4/5)  [=   ]TypeError: e is not a function
    at /home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:105079
    at runNextTicks (node:internal/process/task_queues:60:5)
    at listOnTimeout (node:internal/timers:538:9)
    at process.processTimers (node:internal/timers:512:7)
    at async e.ea (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:85897)
    at async e._checkReady (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:82203)
    at async e.exec (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:73377)
    at async oa (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:87292) {
  digest: '560494367'
}
TypeError: e is not a function
    at /home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:105079
    at runNextTicks (node:internal/process/task_queues:60:5)
    at listOnTimeout (node:internal/timers:538:9)
    at process.processTimers (node:internal/timers:512:7)
    at async e.ea (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:85897)
    at async e._checkReady (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:82203)
    at async e.exec (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:73377)
    at async oa (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:87292) {
  digest: '560494367'
}

Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error

TypeError: e is not a function
    at /home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:105079
    at async e.ea (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:85897)
    at async e._checkReady (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:82203)
    at async e.exec (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:73377)
    at async oa (/home/adrian/Code/nextjs-pglite/.next/server/app/page.js:1:87292)
 ✓ Generating static pages (5/5)

> Export encountered errors on following paths:
        /page: /
AdrianLThomas commented 2 months ago

Not sure if related (yet it is a bundling error), but when creating a new React app: npx create-react-app create-react-app-pglite

and add the intro code (in original post), I see an error too (albeit different):

Failed to compile.

Module not found: Error: Can't resolve 'util' in '/home/adrian/Code/create-react-app-pglite/node_modules/@electric-sql/pglite/dist'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "util": require.resolve("util/") }'
        - install 'util'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "util": false }
ERROR in ./node_modules/@electric-sql/pglite/dist/chunk-SJVDOE3S.js 609:14-28
Module not found: Error: Can't resolve 'util' in '/home/adrian/Code/create-react-app-pglite/node_modules/@electric-sql/pglite/dist'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "util": require.resolve("util/") }'
        - install 'util'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "util": false }

webpack compiled with 1 error

I've tried on both an M1 Macbook Air and Windows 11 with WSL (Ubuntu).

ibolmo commented 2 months ago

Running into this as well with a fresh create-next-app@latest. with options:

here's the diff:

diff --git a/next.config.mjs b/next.config.mjs
index 4678774..342a6fb 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -1,4 +1,7 @@
 /** @type {import('next').NextConfig} */
-const nextConfig = {};
+const nextConfig = {
+  swcMinify: false,
+  transpilePackages: ["@electric-sql/pglite"],
+};

 export default nextConfig;
diff --git a/package-lock.json b/package-lock.json
index fb40716..b79593a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
       "name": "nextjs-pglite",
       "version": "0.1.0",
       "dependencies": {
+        "@electric-sql/pglite": "^0.2.7",
         "next": "14.2.11",
         "react": "^18",
         "react-dom": "^18"
@@ -21,6 +22,11 @@
         "typescript": "^5"
       }
     },
+    "node_modules/@electric-sql/pglite": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.2.7.tgz",
+      "integrity": "sha512-8Il//XHTAtZ8VeQF+6P1UjsIoaAJyO4LwOMoXhSFaHpmkwKs63cUhHHNzLzUmcZvP/ZTmlT3+xTiWfU/EyoxwQ=="
+    },
     "node_modules/@eslint-community/eslint-utils": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
diff --git a/package.json b/package.json
index 54ab8df..36c51d6 100644
--- a/package.json
+++ b/package.json
@@ -9,16 +9,17 @@
     "lint": "next lint"
   },
   "dependencies": {
+    "@electric-sql/pglite": "^0.2.7",
+    "next": "14.2.11",
     "react": "^18",
-    "react-dom": "^18",
-    "next": "14.2.11"
+    "react-dom": "^18"
   },
   "devDependencies": {
-    "typescript": "^5",
     "@types/node": "^20",
     "@types/react": "^18",
     "@types/react-dom": "^18",
     "eslint": "^8",
-    "eslint-config-next": "14.2.11"
+    "eslint-config-next": "14.2.11",
+    "typescript": "^5"
   }
 }
diff --git a/src/app/api/route.ts b/src/app/api/route.ts
new file mode 100644
index 0000000..9601830
--- /dev/null
+++ b/src/app/api/route.ts
@@ -0,0 +1,10 @@
+export const POST = async () => {
+  const { PGlite } = await import("@electric-sql/pglite");
+  const client = await PGlite.create({});
+
+  const result = await client.sql`SELECT 10;`;
+
+  return Response.json({
+    test: result.rows,
+  });
+};
○ Compiling /api ...
 ✓ Compiled /api in 628ms (50 modules)
 ⨯ TypeError: createRequire is not a function
    at eval (webpack-internal:///(rsc)/./node_modules/@electric-sql/pglite/dist/postgres.js:45:55)
    at async Z.Ue (webpack-internal:///(rsc)/./node_modules/@electric-sql/pglite/dist/index.js?94d4:479:41)
    at async Z.create (webpack-internal:///(rsc)/./node_modules/@electric-sql/pglite/dist/index.js?94d4:294:16)
    at async POST (webpack-internal:///(rsc)/./src/app/api/route.ts:7:20)
    at async /Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:55755
    at async eO.execute (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:46523)
    at async eO.handle (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:57089)
    at async doRender (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/base-server.js:1359:42)
    at async cacheEntry.responseCache.get.routeKind (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/base-server.js:1581:28)
    at async DevServer.renderToResponseWithComponentsImpl (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/base-server.js:1489:28)
    at async DevServer.renderPageComponent (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/base-server.js:1920:24)
    at async DevServer.renderToResponseImpl (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/base-server.js:1958:32)
    at async DevServer.pipeImpl (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/base-server.js:917:25)
    at async NextNodeServer.handleCatchallRenderRequest (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/next-server.js:272:17)
    at async DevServer.handleRequestImpl (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/base-server.js:813:17)
    at async /Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/dev/next-dev-server.js:339:20
    at async Span.traceAsyncFn (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/trace/trace.js:154:20)
    at async DevServer.handleRequest (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/dev/next-dev-server.js:336:24)
    at async invokeRender (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/lib/router-server.js:173:21)
    at async handleRequest (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/lib/router-server.js:350:24)
    at async requestHandlerImpl (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/lib/router-server.js:374:13)
    at async Server.requestListener (/Users/olmo/sandbox/nextjs-pglite/node_modules/next/dist/server/lib/start-server.js:141:13)
 POST /api 500 in 871ms
lirbank commented 2 months ago

I had a similar problem with https://www.npmjs.com/package/pdfjs-dist - it was a bug in Next.js 14. So the Next.js team made a fix, but they push the fix to Next.js 15, so I decided to upgrade to 15. It works really well and https://www.npmjs.com/package/pdfjs-dist too.

One could argue that Next.js 15 is still RC, which is true, but disabling the minifier (swcMinify: false) in Next.js 14 is a workaround, but not really a solution. The Next.js team even removed the option completely in v15, which kind of makes sense to me.

Has anyone seen any other workaround for Next.js 15? I am really stoked about ElectricSQL and I would love to use PGlite with it.

Thanks for an epic product!

AdrianLThomas commented 2 months ago

@lirbank

Unfortunately the suggested workaround for Next 14 also doesn't work: https://github.com/electric-sql/pglite/issues/322#issuecomment-2351505322

This is also an issue for a brand new create-react-app (not just Next.js):

lirbank commented 2 months ago

Next.js 15

I have PGlite running flawlessly in Next.js 15, and this may work for Next.js 14 too. Here's how:

// next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  serverExternalPackages: ["@electric-sql/pglite"],
};

export default nextConfig;

References

Next.js 14

The last link above points to the official docs, and at the very bottom they note that the feature moved from experimental to stable. Renamed from serverComponentsExternalPackages to serverExternalPackages.

image
AdrianLThomas commented 2 months ago

@lirbank

Fantastic. I can confirm that works in Next.js 14 too! Excellent work.

// next.config.mjs

  const nextConfig = {
    experimental: {
        serverComponentsExternalPackages : ['@electric-sql/pglite'],
    },
  }

  export default nextConfig;

Still a bit of a mystery for a brand new Create React App though: not sure if the maintainer wants to keep this issue open as this feels like a workaround.

lirbank commented 2 months ago

Nice! Seems like a documentation update is all there is to close this issue.