next.js icon indicating copy to clipboard operation
next.js copied to clipboard

PGLite: 'import', and 'export' cannot be used outside of module code

Open Neo-Ciber94 opened this issue 1 year ago • 4 comments

Link to the code that reproduces this issue

https://github.com/Neo-Ciber94/pglite-next-bug

To Reproduce

You can just clone the repo for reproduction, install dependencies and try build.

  1. Create a nextjs project 14
  2. Install @electric-sql/pglite
  3. Replace your page.tsx with this query, that just query the time:
"use client";

import { PGlite } from "@electric-sql/pglite";
import { useEffect, useRef, useState } from "react";

export default function HomePage() {
  const db = useRef<PGlite>();
  const [data, setData] = useState<unknown>("PENDING");

  useEffect(() => {
    if (db.current) {
      return;
    }

    (async () => {
      db.current = new PGlite();
      const result = await db.current.query("SELECT NOW()");
      setData(result);
    })();
  }, []);

  return (
    <div>
      <h1>PGlite</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}
  1. Update your next.config, the package uses fs and module import for nodejs but those are not used on the client.
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, options) => {
    if (!options.isServer) {
      config.resolve.fallback = { fs: false, module: false, path: false };
    }

    return config;
  },
  transpilePackages: ["@electric-sql/pglite"],
};

export default nextConfig;
  1. Try to build the project, npm run build, you will recieve this error:
static/media/index.a7d43220.js from Terser
  x 'import', and 'export' cannot be used outside of module code
   ,-[1:1]
 1 | import { a, b, c, d, e, f } from "./chunk-OVRU7FYL.js";
   : ^^^^^^
 2 | import "./chunk-EKNQE2HU.js";
 3 | export { a as Mutex, d as PGlite, e as messages, c as parse, f as protocol, b as types }; //# sourceMappingURL=index.js.map
   `----

Caused by:
    0: failed to parse input file
    1: Syntax Error
Error:
  x 'import', and 'export' cannot be used outside of module code
   ,-[1:1]
 1 | import { a, b, c, d, e, f } from "./chunk-OVRU7FYL.js";
   : ^^^^^^
 2 | import "./chunk-EKNQE2HU.js";
 3 | export { a as Mutex, d as PGlite, e as messages, c as parse, f as protocol, b as types }; //# sourceMappingURL=index.js.map
   `----

Caused by:
    0: failed to parse input file
    1: Syntax Error

> Build failed because of webpack errors

Current vs. Expected behavior

It should just bundle the @electric-sql/pglite without problems

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Home
  Available memory (MB): 16259
  Available CPU cores: 8
Binaries:
  Node: 20.11.1
  npm: N/A
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 14.2.3 // Latest available version is detected (14.2.3).
  eslint-config-next: N/A
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.4.5
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Module Resolution, Webpack

Which stage(s) are affected? (Select all that apply)

next build (local)

Additional context

I used next 14.2.3, the lib @electric-sql/pglite only exports esm and is already minified.

Neo-Ciber94 avatar May 04 '24 19:05 Neo-Ciber94

I found out nextjs is unable to resolve the location of @electric-sql/pglite maybe because is a monorepo.

Adding a loader that transpile the package its working for me

/** @type {import('next').NextConfig} */
let nextConfig = {
  images: {},
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.+(js|jsx|mjs|ts|tsx)$/,
      use: options.defaultLoaders.babel,
      include: fileURLToPath(import.meta.resolve("@electric-sql/pglite")),
      type: "javascript/auto",
    });

    if (!options.isServer) {
      config.resolve.fallback = { fs: false, module: false, path: false };
    }

    return config;
  },
  transpilePackages: [],
};

Neo-Ciber94 avatar May 12 '24 16:05 Neo-Ciber94

I found out nextjs is unable to resolve the location of @electric-sql/pglite maybe because is a monorepo.

Adding a loader that transpile the package its working for me

/** @type {import('next').NextConfig} */
let nextConfig = {
  images: {},
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.+(js|jsx|mjs|ts|tsx)$/,
      use: options.defaultLoaders.babel,
      include: fileURLToPath(import.meta.resolve("@electric-sql/pglite")),
      type: "javascript/auto",
    });

    if (!options.isServer) {
      config.resolve.fallback = { fs: false, module: false, path: false };
    }

    return config;
  },
  transpilePackages: [],
};

I tried this and worked in dev but not building. same error. any ideas?

prananta avatar Jul 24 '24 10:07 prananta

@prananta I use pglite-react and pglite-repl. The solution above didn't work.

I am able to fix the build error by adding these options to next-config.js

const nextConfig = {
  swcMinify: false,
  transpilePackages: [
    '@electric-sql/pglite-react',
    '@electric-sql/pglite-repl',
    '@electric-sql/pglite',
  ],
}

Notes: I must delete .next folder before build or it will error again rm -rf .next

If a similar error occurs, try removing the packages and add again

zelief avatar Aug 24 '24 07:08 zelief

Thanks @zelief! I noticed I only needed the swcMinify: false (i.e. it can work without transpilePackages). FWIW, I use bun v1.1.21 with next v14.2.6.

It shows warning that this approach won't work in the next major version, but at least it works for now.

image

wzulfikar avatar Aug 26 '24 20:08 wzulfikar

For me what helped was adding it as part of the experimental serverComponentsExternalPackages

...
experimental: {
    serverComponentsExternalPackages: ['@electric-sql/pglite'],
},
...

thebergamo avatar Aug 28 '24 10:08 thebergamo

Can confirm that this works with Nextjs 15 (from https://github.com/electric-sql/pglite/issues/322#issuecomment-2372563526):

// next.config.mjs
const nextConfig = {
  serverExternalPackages: ["@electric-sql/pglite"],
};

export default nextConfig;

carderne avatar Nov 17 '24 09:11 carderne