Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failure to resolve dependencies from nested symlinked directories when bundling #2773

Closed
onebytegone opened this issue Dec 26, 2022 · 2 comments

Comments

@onebytegone
Copy link
Contributor

When bundling code that imports a dependency through nested symlinked directories, esbuild fails with Could not read from file. However, running the same code using node works.

Background: I'm looking to use esbuild for projects in a monorepo that has some fanciness with symlinks for various legacy reasons. The project structure looks like:

$ tree
.
├── bar
│   └── foo -> ../foo
├── baz
│   └── bar -> ../bar
├── foo
│   └── index.js # imports "../qux"
├── in.js # imports "./baz/bar/foo"
└── qux
    └── index.js

If the symlinks were resolved, a project's structure would look something like:

$ tree
.
├── baz
│   └── bar
│       ├── foo
│       │   └── index.js # imports "../qux"
│       └── qux
│           └── index.js
└── in.js # imports "./baz/bar/foo"

Putting aside debates about whether this structure is a Good Idea:tm: or not (there's definitely part of me that says this symlinking example is a little crazy), it seems like this might be an edge-case in esbuild. Both node and Webpack resolve the symlinks without issue.

MVCE

Download: symlink-mvce.zip

$ tree -I node_modules
.
├── bar
│   └── foo -> ../foo
├── baz
│   └── bar -> ../bar
├── foo
│   └── index.js
├── in.js
├── package-lock.json
├── package.json
└── qux
    └── index.js

6 directories, 5 files
$ cat in.js
'use strict';

const foo = require('./baz/bar/foo');

if (foo.foo === 123) {
   console.log('ok', foo);
} else {
   throw 'fail';
}
$ cat foo/index.js
'use strict';

const qux = require('../qux');

module.exports = { foo: 123, ...qux };
$ cat qux/index.js
'use strict';

module.exports = { qux: 321 };

Versions

$ node -v
v16.15.0
$ npm -v
8.5.5
$ ./node_modules/.bin/esbuild --version
0.16.10

Output

$ node in.js # Code works when run with node
ok { foo: 123, qux: 321 }
$ ./node_modules/.bin/esbuild in.js --bundle
✘ [ERROR] Could not read from file: /private/tmp/mvce/baz/foo/index.js

    in.js:3:20:
      3 │ const foo = require('./baz/bar/foo');~~~~~~~~~~~~~~~

1 error

FWIW, the --preserve-symlinks behavior is as expected:

$ ./node_modules/.bin/esbuild in.js --bundle --preserve-symlinks
✘ [ERROR] Could not resolve "../qux"

    baz/bar/foo/index.js:3:20:
      3 │ const qux = require('../qux');~~~~~~~~

1 error
$ node --preserve-symlinks in.js
node:internal/modules/cjs/loader:936
  throw err;
  ^

Error: Cannot find module '../qux'
Require stack:
- /private/tmp/mvce/baz/bar/foo/index.js
- /private/tmp/mvce/in.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/private/tmp/mvce/baz/bar/foo/index.js:3:13)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/private/tmp/mvce/baz/bar/foo/index.js',
    '/private/tmp/mvce/in.js'
  ]
}

Related

@onebytegone
Copy link
Contributor Author

At the moment, I think this is related to the symlink resolution code here. I'm happy to investigate further. However, figured it'd be better to create an issue before going too far.

@evanw
Copy link
Owner

evanw commented Dec 27, 2022

Thanks for the thorough issue description and PR. I'll publish your fix soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants