tsx icon indicating copy to clipboard operation
tsx copied to clipboard

`ERR_UNSUPPORTED_ESM_URL_SCHEME` when dyanmic import in windows

Open tangdaoyuan opened this issue 2 years ago • 7 comments

Description

In windows, Using dynamic import with absolute path cause ERR_UNSUPPORTED_ESM_URL_SCHEME error

image

Reproduction

  1. create a.ts file following
import path from "path";

const abs_path = path.resolve('./b.ts', );  // absolute path
import(abs_path)
  1. run node --loader @esbuild-kit/esm-loader a.ts

extra

tsx has same error.

tangdaoyuan avatar Sep 20 '22 17:09 tangdaoyuan

Apparently this is by design: https://github.com/nodejs/node/issues/34765#issuecomment-674096790

Does this work in any other Windows environments? eg. different versions of Node.js or TypeScript

privatenumber avatar Sep 21 '22 05:09 privatenumber

Apparently this is by design: nodejs/node#34765 (comment)

Does this work in any other Windows environments? eg. different versions of Node.js or TypeScript

It works after temp fix in win10 with typescript v4.5 ~ v4.8, node v12.20.0, node v14.20.0, node 16.14.2. I have no other windows enviroments, so I try to create a repo for more tests by github actions.

here is test actions:

tangdaoyuan avatar Sep 22 '22 05:09 tangdaoyuan

Feel free to open a PR

privatenumber avatar Dec 01 '23 11:12 privatenumber

I ran into the same issue, but I got it working when using not an absolute path, but a relative path as configured in the path of tsconfig:

tsconfig

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
}

dynamic import The file that I want to import exists at src/mydynamicimport.ts.

const name = "mydynamicimport";
await import(`@/${name}`);

Actual problem: absolute path on Windows

So the "issue" here is the usage of an absolute path, which is not working on Windows. You would have to use a proper URL:

import path from "node:path";
import { pathToFileURL } from "node:url";

export async function dynamicImport(fullPath: string) {
  const fileURL = pathToFileURL(fullPath).href;
  return import(fileURL);
}

// Usage example, assuming your mydynamicimport.ts is inside of "src"
await dynamicImport(path.join(process.cwd(), "src", "mydynamicimport"));

This will produce an URL like this: file:///D:/src/mydynamicimport.

TimPietrusky avatar Jan 08 '24 10:01 TimPietrusky

It works when dynamic importing a literal:

import('file:///D:/foo.ts') works

so1ve avatar Feb 04 '24 03:02 so1ve

Is https://github.com/esbuild-kit/esm-loader/pull/39 a proper fix? I'd like to back-port it to tsx if it works.

so1ve avatar Feb 04 '24 08:02 so1ve

I'm currently wondering if this is even a tsx issue, or if this is a Node.js issue ya'll are trying to patch with tsx?

Specifically, does this work in Node (no tsx) on Windows?

import path from "path"

const abs_path = path.resolve('./b.ts', );  // absolute path
import(abs_path)

To determine this, I'd throw the above snippet in a GitHub repo with CI on ubuntu and windows running it.

privatenumber avatar Mar 20 '24 01:03 privatenumber

@privatenumber very much appears to be a Node issue itself

grafik

mvarendorff avatar Jun 06 '24 21:06 mvarendorff

Thanks for verifying @geisterfurz007

Closing as it's expected behavior.

privatenumber avatar Jun 06 '24 22:06 privatenumber