denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.14k stars 5.36k forks source link

Compiled executable failed to find modules from custom npm registry containing subpath #26628

Open imfing opened 1 day ago

imfing commented 1 day ago

Version: Deno 2.0.3

I have encountered this issue while working with a custom npm registry such as JFrog npm-registry. While Deno successfully caches, and executes scripts respecting the NPM_CONFIG_REGISTRY environment variable, compiling the script into an executable results in an ERR_MODULE_NOT_FOUND error for npm modules.

Steps to reproduce

the example was taken from the blog post, I was running Deno 2.0.3 in blank GitHub codespace (Linux), with custom public npm registry mirror:

$ export NPM_CONFIG_REGISTRY=http://mirrors.tencent.com/npm/

$ cat main.ts
import { say } from "npm:cowsay@1.5.0";
console.log(say({ text: "Hello from Deno!" }));

$ deno run --allow-read main.ts
 __________________
< Hello from Deno! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

$ deno compile --allow-read -o main main.ts
Compile file:///workspaces/codespaces-blank/main.ts to main

$ ./main
error: [ERR_MODULE_NOT_FOUND] Cannot find module 'file:///tmp/deno-compile-main/.deno_compile_node_modules/localhost/cowsay/1.5.0/index.js' imported from 'file:///tmp/deno-compile-main/codespaces-blank/main.ts'

Screenshot:

Additional info:

I found that using custom npm registry like $ export NPM_CONFIG_REGISTRY=http://registry.npm.taobao.org would work without issues. This leads me to suspect that the problem may be related to how Deno compile handles npm modules located under a subpath (e.g. http://custom-registry.com/path/to/npm/)

imfing commented 8 hours ago

https://github.com/denoland/deno/blob/a8846eb70f96445753fe5f8f56e6155cb2d0fac6/cli/standalone/binary.rs#L767-L774

seem that the issue is caused by the assumption that all npm modules are located in <root_dir>/<registry_host>/...

in reality, the cached packages are actually stored in subdirectories, specifically under <root_dir>/<registry_host>/sub/path/...