parcel-bundler / parcel

The zero configuration build tool for the web. 📦🚀
https://parceljs.org
MIT License
43.5k stars 2.27k forks source link

Cannot resolve dependency, but file exists #1986

Closed timglabisch closed 6 years ago

timglabisch commented 6 years ago

❔ Question

i don't understand why pacel could not resolve a dependency.

when i run parcel build index.html i get the error

/Users/tim/proj_/parcel-example/index.html: Cannot resolve dependency '/Users/tim/proj_/parcel-example/index.js' at '/Users/tim/proj_/parcel-example/index.js'

but the file exists:

➜  parcel-example  cat /Users/tim/proj_/parcel-example/index.js
console.log("ok");

why pacel could not resolve the dependency?

🔦 Context

i debugged a little bit and it seems that pacel resolves the path as /Users/tim/proj_/parcel-example/Users/tim/proj_/parcel-example/index.js

the function https://github.com/parcel-bundler/parcel/blob/a3306688de7be54459163ae44e19c32e7a663168/src/Resolver.js#L121

is called twice, first call

‌‌this.options.rootDir
‌/Users/tim/proj_/parcel-example

‌‌filename.slice(1)
‌index.js

i expected this path as result, but parcel goes on and does a second call:

‌‌this.options.rootDir
‌/Users/tim/proj_/parcel-example

‌‌filename.slice(1)
‌Users/tim/proj_/parcel-example/index.js

which will result in ‌/Users/tim/proj/parcel-example/‌Users/tim/proj/parcel-example/index.js

💻 Code Sample

index.html

<html>
<body>
  <script src="/index.js"></script>
</body>
</html>

index.js

console.log("ok");

🌍 Your Environment

Software Version(s)
Parcel 1.9.7
Node v10.9.0
npm 6.2.0
Operating System osx and ubuntu
chocolateboy commented 6 years ago
Parcel876bfe214425d7588f2a9d1be137251a09b895cd (same error on 1.9.7)
Nodev10.9.0
OSLinux (Arch)

Here's an example of the stack traces I get for the first and second call to resolveFilename for the same asset:

Good:

Trace: XXX resolving filename: /src/js/index.js
    at Resolver.resolveFilename (/home/user/build/parcel/src/Resolver.js:122:13)
    at HTMLAsset.addURLDependency (/home/user/build/parcel/src/Asset.js:104:42)
    at HTMLAsset.processSingleDependency (/home/user/build/parcel/src/assets/HTMLAsset.js:95:26)
    at ast.walk.node (/home/user/build/parcel/src/assets/HTMLAsset.js:157:43)
    at traverse (/home/user/build/parcel/node_modules/posthtml/lib/api.js:105:26)
    at traverse (/home/user/build/parcel/node_modules/posthtml/lib/api.js:111:5)
    at traverse (/home/user/build/parcel/node_modules/posthtml/lib/api.js:105:17)
    at traverse (/home/user/build/parcel/node_modules/posthtml/lib/api.js:111:5)
    at traverse (/home/user/build/parcel/node_modules/posthtml/lib/api.js:105:17)
    at Array.walk (/home/user/build/parcel/node_modules/posthtml/lib/api.js:39:10)
XXX resolved filename: /home/user/build/parcel-test/src/js/index.js

Bad:

Trace: XXX resolving filename: /home/user/build/parcel-test/src/js/index.js
    at Resolver.resolveFilename (/home/user/build/parcel/src/Resolver.js:122:13)
    at Resolver.resolveModule (/home/user/build/parcel/src/Resolver.js:84:23)
    at Resolver.resolve (/home/user/build/parcel/src/Resolver.js:59:29)
    at Bundler.resolveAsset (/home/user/build/parcel/src/Bundler.js:409:38)
    at Bundler.resolveDep (/home/user/build/parcel/src/Bundler.js:460:25)
    at Promise.all.dependencies.map (/home/user/build/parcel/src/Bundler.js:583:37)
    at Array.map (<anonymous>)
    at Bundler.loadAsset (/home/user/build/parcel/src/Bundler.js:575:20)
XXX resolved filename: /home/user/build/parcel-test/home/user/build/parcel-test/src/js/index.js

The error occurs when either prefix is used — i.e. tilde (~) or forward slash (/) — and for every asset type I've tried (.html, .scss, .svg, .ts):

/home/user/build/parcel-test/index.html: Cannot resolve dependency '/home/user/build/parcel-test/src/js/index.js' at '/home/user/build/parcel-test/src/js/index.js'

chocolateboy commented 6 years ago

Related/Duplicates:

peanutbother commented 6 years ago

Did you notice in your index.html you are referencing index.js as absolute path

<script src="/index.js"></script>

did you mean to write

<script src="./index.js"></script>

What happens if you try to import your assets relatively? (like the one above)

Could you please provide a repo?

peanutbother commented 6 years ago

Also I don't think this is a sass related issue like in #1555 because sass handles file paths differently (sass can use .sassrc for resolving algorithm)

chocolateboy commented 6 years ago

Did you notice in your index.html you are referencing index.js as absolute path

As of #850, absolute paths (i.e. paths starting with a slash) are supposed to be resolved against the project root, and paths starting with a tilde are supposed to resolve against the package root (i.e. the nearest node_modules subfolder) or project root (whichever comes first):

Parcel (v1.7.0 and above) supports multiple module resolution strategies out of the box so you don't have to deal with endless relative paths `../../`.
chocolateboy commented 6 years ago

Also I don't think this is a sass related issue like in #1555

1555 is not a Sass-specific issue. The asset isn't being loaded with an @import from a .scss file. It's a Parcel dependency and the same error occurs with other asset types e.g.:

chocolateboy commented 6 years ago

Could you please provide a repo?

There's one provided in #1555, but I've just pushed another version which reproduces the error with a plain JavaScript asset here.

peanutbother commented 6 years ago

I tested both repos and both examples worked as intended. I had no errors. parcel v1.9.7, yarn v1.9.4

peanutbother commented 6 years ago

What I just noticed is, that in your issue you mention two different paths in the stacktrace:

Trace: XXX resolving filename: /src/scss/index.scss
    at Resolver.resolveFilename (/home/user/build/parcel/src/Resolver.js:123:13)
  [...]
XXX resolved filename: /home/user/dev/my-project/src/scss/index.scss

one path starting with /home/user/build/ and one /home/user/dev/ I guess build is a subdirectory of /home/user/dev/my-project which would lead me to conclusion that the path might got merged by two levels too high, resulting in filepaths missing dev/my-project

if that is the case, the output files should got to /home/user/dev/my-project/build/

can you explain why there are different paths?

chocolateboy commented 6 years ago

can you explain why there are different paths?

I've updated the stack traces to reflect the error from the minimal test case.

chocolateboy commented 6 years ago

I tested both repos and both examples worked as intended. I had no errors.

Which OS and node version?

peanutbother commented 6 years ago

I can still see two different path, now:

Trace: XXX resolving filename: /src/js/index.js
    at Resolver.resolveFilename (/home/user/build/parcel/src/Resolver.js:122:13)
    [...]
XXX resolved filename: /home/user/build/parcel-test/src/js/index.js

I guess you are using your own local-linked version of parcel-bundler? did you try to build with the npm-version of parcel-bundler?

Which OS and node version?

Node: 10.4.0 OS: Windows 10 [10.0.17134.228]

chocolateboy commented 6 years ago

did you try to build with the npm-version of parcel-bundler?

Yes. I get the same error with the stock v1.9.7 release. ~/build/parcel is just a checkout of parcel's git repo.

peanutbother commented 6 years ago

just to make sure... if you local-linked your own version, try unlinking it and install parcel locally. after that run the yarn dev command again. if that works, there you might have forgotten to unlink parcel properly.

chocolateboy commented 6 years ago

I'm not npm-linking the git version of parcel. I'm just using a symlink:

$ ln -s ~/build/parcel/bin/cli.js ~/bin/parcel-dev
$ parcel-dev watch index.html

But, like I say, the same error occurs with the released version. I'm only using the git version to troubleshoot this issue.

I've just installed node v10.4.0, and get the same error. Maybe it's an OS issue?

peanutbother commented 6 years ago

That's weird. despite I would never symlink any npm package on my own but use npm link / yarn link, that might not be the issue for this behaviour. I will try to reproduce this on an Ubuntu host.

chocolateboy commented 6 years ago

I would never symlink any npm package on my own but use npm link / yarn link

It's the way that's recommended in the contributing guidelines (the shebang uses /usr/bin/env, so the wrapper/alias isn't needed) :-)

Thanks for your help btw :+1:

peanutbother commented 6 years ago

My Ubuntu / WSL installation also fails with same errors:

https://github.com/absentees/parcel-test

$ parcel watch index.html
🚨  /c/Projekte/forks/absentees-parcel-test/index.html: 
Cannot resolve dependency '/c/Projekte/forks/absentees-parcel-test/src/css/main.scss'
 at '/c/Projekte/forks/absentees-parcel-test/src/css/main.scss'
 at Resolver.resolve (/c/Projekte/forks/absentees-parcel-test/node_modules/parcel-bundler/src/Resolver.js:69:17)

https://github.com/chocolateboy/parcel-test

$ parcel watch index.html
🚨  /c/Projekte/forks/chocolateboy-parcel-test/index.html: 
Cannot resolve dependency '/c/Projekte/forks/chocolateboy-parcel-test/src/js/index.js' 
  at '/c/Projekte/forks/chocolateboy-parcel-test/src/js/index.js'
  at Resolver.resolve (/c/Projekte/forks/chocolateboy-parcel-test/node_modules/parcel-bundler/src/Resolver.js:69:17)

Node: 10.4.0 Yarn: 1.9.4 OS: WSL (Debian 9.3) 4.4.0-17134-Microsoft running on: Windows 10 [10.0.17134.228]

chocolateboy commented 6 years ago

From what I can gather (someone correct me if I'm wrong), it looks like there are (at least) two passes over each dependency:

1) parsing/discovery: an asset-specific parser/processor discovers each dependency e.g. src/assets/HTMLAsset.js uses PostHTML to detect links to scripts, stylesheets etc. in HTML files. This is where the dependency objects originate and is represented by the "Good" stack trace above.

2) processing/bundling: an additional pass by the app itself (i.e. src/Bundler.js) processes the tree of dependencies discovered by the first pass. This is represented by the "Bad" stack trace above.

The dependency objects produced by the first pass only contain a few fields (at least to start with) e.g.:

{
    name: '/home/user/build/parcel-test/src/js/index.js',
    parent: '/home/user/build/parcel-test/index.html'
}

Note that the name, which appears as /src/js/index.js in the HTML, is resolved to its absolute path in the dependency object. However, the second pass is unaware of this, and blithely re-resolves the path.

An easy fix would be to add a field to the dependency which indicates that it has already been resolved e.g.:

{
    name: '/home/user/build/parcel-test/src/js/index.js',
    parent: '/home/user/build/parcel-test/index.html',
    resolved: true,
}

But it turns out this is already supported (in a slightly different form)! The processing/bundling pass checks each dependency object's resolved field for an absolute path (in Bundler#resolveDep) and uses that if it's available. It's just not being set when these dependencies are resolved in the first pass.

Adding that field (in Asset#addURLDependency) fixes this issue for me:

{
    name: '/home/user/build/parcel-test/src/js/index.js',
    parent: '/home/user/build/parcel-test/index.html',
    resolved: '/home/user/build/parcel-test/src/js/index.js',
}

I've raised a PR for this here. Let me know if there are any issues.

s3rgeym commented 4 years ago

у вас руки из задницы растут. я это разработчикам

tadinski commented 4 years ago

issue still exists

kevinhaas commented 4 years ago

Yes it does. I'd suggest moving to webpack, it's a much better experience. They seem to just ignore issues in this repo and mark stuff closed that is clearly still an issue.

mischnic commented 4 years ago

They seem to just ignore issues in this repo and mark stuff closed that is clearly still an issue.

This issue was closed because it was fixed (at the time). If it happens again, there might be a different cause (= new issue).

Clingonboy commented 4 years ago

I have the same problem

Server running at http://localhost:1234 🚨 /home/uge/Sandbox/webgame/foracciodue/src/game.js:1:21: Cannot resolve dependency './player' at '/home/uge/Sandbox/webgame/foracciodue/src/player'

1 | import {Player} from './player' | ^ 2 | 3 | export class Game { 4 | constructor (cards) {

ffigiel commented 3 years ago

If it helps, note that ~ resolves to the directory of your entry point. so if you have

.
└── src
    ├── app
    │   ├── ...
    └── index.html

and run parcel src/index.html, you should import ~/app/..., not ~/src/app/...

ctjlewis commented 2 years ago

Program is making bold assumptions about my project structure.

$ cd out
$ parcel build index.html

@parcel/core: Failed to resolve
'/_next/static/chunks/polyfills-5cd94c89d3acac5f.js' from
'./out/index.html'

@parcel/resolver-default: Cannot load file
'../_next/static/chunks/polyfills-5cd94c89d3acac5f.js' in
'./out'.

It's not wrong that this is a directory inside a project, but as a CLI, the project directory should be the current working directory. I do not need Parcel confusing itself about what the root directory is. Is it looking for package.json, or what? If you're going to ship logic like that, we need an escape hatch at the very least.

If you're inside ., and I feed you index.html and it contains a <script src="/_next/..." />, it is startling that you would come back to me with an error. /_next is ./_next relative to ., it's super straightforward? I would send in a PR but if this is possible this late in the software's lifecycle, I imagine it would be a waste of time.