evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.02k stars 1.14k forks source link

pnpm module resolution errors (on Windows) #3937

Open callumevans opened 1 day ago

callumevans commented 1 day ago

I'm seeing some issues resolving pnpm packages, specifically on Windows, via the Go API.

I'm not entirely sure it's the same issue as mentioned in https://github.com/evanw/esbuild/issues/67, but I'm able to reproduce it from the example given there (https://github.com/timsuchanek/esbuild-pnpm).

Given the following Go code (where C:/Users/callu/Desktop/esbuild-pnpm/index.js is the cloned repo mentioned in #67):

    workingDirectory, _ := os.Getwd()

    result := api.Build(api.BuildOptions{
        EntryPoints: []string{"C:/Users/callu/Desktop/esbuild-pnpm/index.js"},
        Bundle:      true,
        Write:       true,
        Format:      api.FormatCommonJS,
        Platform:    api.PlatformNode,
        Target:      api.ES2015,
        Sourcemap:   api.SourceMapLinked,
        Metafile:    true,
        GlobalName:  "exports",
        Outdir:      filepath.Join(workingDirectory, ".output"),
        LogLevel:    api.LogLevelVerbose,
    })

With the verbose output, I'm getting the following:

♦ [VERBOSE] Resolving import "chalk" in directory "C:\\Users\\callu\\Desktop\\esbuild-pnpm" of type "require-call"

  Checking for package alias matches
    Failed to find any package alias matches
  Read 8 entries for directory "C:\\Users\\callu\\Desktop\\esbuild-pnpm"
  Searching for "chalk" in "node_modules" directories starting from "C:\\Users\\callu\\Desktop\\esbuild-pnpm"
    Parsed package name "chalk" and package subpath "."
    Checking for a package in the directory "C:\\Users\\callu\\Desktop\\esbuild-pnpm\\node_modules\\chalk"
    Read 8 entries for directory "C:\\Users\\callu\\Desktop\\esbuild-pnpm"
    Read 5 entries for directory "C:\\Users\\callu\\Desktop\\esbuild-pnpm\\node_modules"
    The file "C:\\Users\\callu\\Desktop\\esbuild-pnpm\\node_modules\\chalk\\package.json" exists
    Read 5 entries for directory "C:\\Users\\callu\\Desktop\\esbuild-pnpm\\node_modules\\chalk"
    Attempting to load "C:\\Users\\callu\\Desktop\\esbuild-pnpm\\node_modules\\chalk" as a file
      Checking for file "chalk"
      Found file "chalk"
  Read 5 entries for directory "C:\\Users\\callu\\Desktop\\esbuild-pnpm\\node_modules"
  Primary path is "C:\\Users\\callu\\Desktop\\esbuild-pnpm\\node_modules\\chalk" in namespace "file"

● [DEBUG] Failed to read file "C:\\Users\\callu\\Desktop\\esbuild-pnpm\\node_modules\\chalk": read C:\Users\callu\Desktop\esbuild-pnpm\node_modules\chalk: Incorrect function.

X [ERROR] Cannot read file "../../../Users/callu/Desktop/esbuild-pnpm/node_modules/chalk": Incorrect function.

    ../../../Users/callu/Desktop/esbuild-pnpm/index.js:1:22:
      1 │ const chalk = require('chalk')
        ╵                       ~~~~~~~

Something tells me this is a me-problem, although I've been able to replicate this in other contexts.

It works great if I just use an npm install - no issues whatsoever. With a pnpm install, I start seeing the above errors.

This also seems to be Windows-specific. Works fine on macOS.

I've tried various tweaks to the api.Build config, but haven't managed to get it working consistently.

hyrious commented 1 day ago

Base on your log above, it seems the problem is that esbuild did not try to resolve symlinks created by pnpm on Windows. The correct log should be like:

  Searching for "chalk" in "node_modules" directories starting from "D:\\a\\esbuild-3937\\esbuild-3937"
    Parsed package name "chalk" and package subpath "."
    Checking for a package in the directory "D:\\a\\esbuild-3937\\esbuild-3937\\node_modules\\chalk"
    Read 9 entries for directory "D:\\a\\esbuild-3937\\esbuild-3937"
    Read 5 entries for directory "D:\\a\\esbuild-3937\\esbuild-3937\\node_modules"
+   Resolved symlink "D:\\a\\esbuild-3937\\esbuild-3937\\node_modules\\chalk" to "D:\\a\\esbuild-3937\\esbuild-3937\\node_modules\\.pnpm\\chalk@5.3.0\\node_modules\\chalk"
    The file "D:\\a\\esbuild-3937\\esbuild-3937\\node_modules\\chalk\\package.json" exists
    Read 4 entries for directory "D:\\a\\esbuild-3937\\esbuild-3937\\node_modules\\chalk"
    Looking for "." in "exports" map in "D:\\a\\esbuild-3937\\esbuild-3937\\node_modules\\chalk\\package.json"
      Checking path "" against target "./source/index.js"
        Joined "" to "./source/index.js" to get "./source/index.js"
      ...

The above log was generated from a windows machine on github actions. Maybe you are just using old versions of esbuild and pnpm?

evanw commented 23 hours ago

The file system on Windows has multiple roots (volume labels) while the file system on Unix has a single root (just /). I'm aware that this is problematic with some of esbuild's Yarn support (Yarn actually allows ../ to traverse between different volumes on Windows while Windows doesn't, and esbuild doesn't support that yet).

It's possible that cross-volume paths are the problem here. If that's the case, the reproduction steps would require spreading your source code across multiple volumes, and a possible workaround could be to make sure your source code is all on the same volume. Or if that workaround doesn't work then that wasn't the problem.

I'm sorry that I can't test this myself but I don't have easy access to a Windows machine.