playwright icon indicating copy to clipboard operation
playwright copied to clipboard

[BUG] dynamic import of ESM results in ERR_REQUIRE_ESM

Open Janpot opened this issue 1 year ago • 6 comments

Context:

  • Playwright Version: 1.25.1
  • Operating System: MacOs
  • Node.js version: v16.17.0

Code Snippet

import { test } from "@playwright/test";

test("dynamic import of ESM", async ({}) => {
  const { default: getPort } = await import("get-port");
  console.log(await getPort());
});

Describe the bug

From the node.js docs

Dynamic import() is supported in both CommonJS and ES modules. In CommonJS modules it can be used to load ES modules.

Yet, trying to load an ESM only package like get-port with a dynamic import statement fails with the error:

Error [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/get-port/index.js from .../tests/example.spec.ts not supported.
    Instead change the require of index.js in .../tests/example.spec.ts to a dynamic import() which is available in all CommonJS modules.

It's complaining I'm trying to use require to load an ESM only module, but as can be seen in the snippet, it's an import().

Janpot avatar Sep 04 '22 16:09 Janpot

had a very similar issue, had to hardcode "@playwright/test": "1.22.2", in my package.json

ilanb1996 avatar Sep 07 '22 07:09 ilanb1996

@Janpot This indeed does not work. The workaround is to either not use dynamic imports, or set "type": "module" in your package.json. Perhaps in the future we'll make it work out of the box.

dgozman avatar Sep 07 '22 23:09 dgozman

I also suffer from this, many npm packages are moving to ESM only and using type: module makes it very hard in my case, since I have some imports to my code and requires me to turn everything to ESM.

It would be very much appreciated if this worked out of the box, or there was a workaround to avoid transpilation (I'm assuming there must be), as I like Playwright a lot and have been using it happily for a long time.

frontsideair avatar Feb 08 '23 17:02 frontsideair

I have a pretty robust workaround, which might be helpful to others as well. The workaround uses esbuild, but could work with other tools.

  1. Pull all ESM dependencies in a file like this.
// deps.ts
import findCacheDir from "find-cache-dir";
import getPort from "get-port";

export { findCacheDir, getPort };
  1. Install esbuild and add a pretest script.
"pretest": "esbuild --platform=node deps.ts --bundle --outfile=deps.bundle.js",
  1. Depend on deps.bundle in tests.
import { findCacheDir, getPort } from "./deps.bundle";

If the dependencies get too large, you may get a warning like this and lose some Playwright features.

[BABEL] Note: The code generator has deoptimised the styling of /path/to/deps.bundle.js as it exceeds the max of 500KB.

This is the best I could do given the circumstances, let me know if you have a better solution.

frontsideair avatar Feb 09 '23 18:02 frontsideair

@frontsideair curious what features are lost when that error appears? From what I understand, it's largely just a complaint from Babel that can be ignored.

D4N14L avatar May 07 '23 20:05 D4N14L

It's been a while, but IIRC you lose the nice error messages when a test fails, that shows the test code that failed as a snippet.

frontsideair avatar May 08 '23 08:05 frontsideair

Bump. I would like to connect TRPC to the project.

import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '@agent-b2b/trpc/src/server/routers';

export default async function setupTrpcClient() {
  const { default: superjson } = await import('superjson');
  return createTRPCProxyClient<AppRouter>({
    transformer: superjson,
    links: [
      httpBatchLink({
        url: `http://localhost:2022`,
      }),
    ],
  });
}

kodermax avatar Dec 08 '23 16:12 kodermax

I have the same issue

olayway avatar Apr 14 '24 23:04 olayway