Simple tilde paths as described under getting started don't seem to be resolving.
A repo of the error. My folder structure:
node_modules
xhook
dist
xhook.js
folder1
index.html
index.html
package.json
And both index.html
files have:
<html>
<body>
<script src="~/node_modules/xhook/dist/xhook.js"></script>
</body>
</html>
When I run parcel folder1/index.html
it should build.
parcel index.html
works fine but parcel folder1/index.html
returns:
D:\dev\parcel-test\folder1\node_modules\xhook\dist\xhook.js: ENOENT: no such file or directory, open 'D:\dev\parcel-test\folder1\node_modules\xhook\dist\xhook.js'
It seems to be treating the tilde as a relative path rather than looking for the folder containing node_modules
.
| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.12.2 |
| Node | 11.12.0 |
| npm/Yarn | npm 6.7.0 |
| Operating System | Windows 10 |
What is the expected behaviour here? Do we want ~
to work same as in webpack? Means that a lookup is performed against node_modules to resolve the path? If yes, then the path should have been
<script src="~xhook/dist/xhook.js"></script>
. However, even in this case, parcel does not work as expected, but I could try to fix that if the specification is to be compliant with other bundlers?
Think the relevant code is here
~/node_modules/...
is actually correct: https://parceljs.org/module_resolution.html#~-tilde-paths
that if the specification is to be compliant with other bundlers?
That difference isn't ideal though
I've looked a bit more into it and looks like the behavior is expected?
parcel folder1/index.html
would mean that this.options.rootDir
would be path/to/folder1
, therefore parcel tries to resolve the resource relative to path/to/folder1/
- the entry root.
entry root: the directory of the entrypoint specified to Parcel, or the shared root (common parent directory) when multiple entrypoints are specified.
On an unrelated note, line 133 seems suspicous to me that it could result in another issue (in a much more obscure case though where package root has priority, but I haven't verified this).
The code does appear like it's set up how it's supposed to be, but ~
is also not working for me as described in the above issue report.
~
should resolve to the package root (closest node_modules), but it is resolving to the entry point, not the package location. As soon as I changed my entry point from ./index.html
to ./src/index.html
, my ~
references broke, and I had to change them to relative folders with ..
.
Just to add to the above comments, I find myself building modules that are nested in several folders like myapp/path/to/my/module/module.js
.
Now if I import ~/utils/anotherModule.js
in my module, I would expect Parcel to resolve myapp/utils/anotherModule.js
But it resolves to myapp/path/to/my/module/~/utils/anotherModule.js
and fails.
The doc states:
~/foo resolves foo relative to the nearest package root or, if not found, the entry root.
But the code states:
Tilde path. Resolve relative to nearest node_modules directory, or the project root - whichever comes first.
They are both very different behaviors. I wonder what is the use case for the latter...
I have the same issue on OSX and I'm a little bit confused as to how it should work. The way OP describes it was in line with my intuition, but the documentation and code comments are IMO unclear. Specifically the definition of package root
here. What does it mean:
the directory of the nearest module root in node_modules
What exactly is _module root_ and what if my project is not _in node_modules_, e.g. it's an application in ${HOME}/my-app
? And what is _project root_ mentioned in the code comment? This seems not to be defined anywhere. Looking at source code I found this:
and this:
Does it really have to be that complicated? Couldn't tilde just resolve to the working directory or it's nearest ancestor that contains package.json
file? Also, maybe there could be a CLI option --root-dir
for special cases. I'm sorry if I am missing something. These are sincere qustions.
For reference, there is also this comment from @mischnic: https://github.com/parcel-bundler/parcel/issues/2857#issuecomment-478719089 . It explains the intended tilde resolution mechanism very clearly. The problem is that currently it does not work that way.
In the mean time I use the following workaround:
<link href = "/../node_modules/some-module/some-file.css" />
It seems to be working from anywhere inside src/
, provided that entry is src/index.html
.
Hello, just to mention that I also had to use ~/../node_modules/..
when having the entry file in src/index.html
. I'm using parcel-bundler
as middleware with express.
@import url('../node_modules/...');
also works.
node_modules
carbon-components
src
App.jsx
App.scss <-- @import '~/../node_modules/carbon-components/css/carbon-components.css'
index.html
server.js
package.json
That was for that simple structure, now in other complex project structure I'm struggling with importing some css in a scss.
node_modules
client
node_modules
carbon-components
public
index.html <-- <script src="../src/index.js"/>
src
index.js
index.scss <-- @import '~/../node_modules/carbon-components/css/carbon-components.css'
server.js <-- const bundler = new Bundler("client/public/index.html"); // etc.
package.json
The entry file is located in /Users/devniel/dev/da/project/client/public/index.html
and the import is resolving to /Users/devniel/dev/da/project/client/public/Users/devniel/dev/da/project/client/node_modules/carbon-components/css/carbon-components.css
in the Resolver.js
๐
I think that it should be /Users/devniel/dev/da/project/client/public/node_modules/carbon-components/css/carbon-components.css
, the thing is that the shown error is in the parcel building is reporting this path as cannot resolve...
, but inside it's using the mentioned above.
Same issue, ~ seems to be resolving to the entry root, rendering it pretty much useless.
Hey y'all, here's another reproduction repo for anyone who wants to quickly see this bug in action:
https://github.com/savovs/parcel-tilde-bug
In my case (MacOS) tilde resolves to... nothing really. It's just taken literally:
Cannot resolve module [...] at '/project-root/src/styles/~/normalize.css/normalize.css'
รฑ~
Adding ~/node_modules/...
does nothing.
I've resorted to using the full relative path:
@import "../../node_modules/normalize.css/normalize.css";
This is still broken. For some reason, parcel tries to resolve ~
in the entry root, not the project root. I have a normal package.json
and node_modules
in my root folder, and this is not a monorepo.
/Users/loyi/nm-frontend/src/components/App/App.tsx:48:39: Cannot resolve dependency '~/routes' at '/Users/loyi/nm-frontend/src/components/App/~/routes'
at Resolver.resolve (/Users/loyi/nm-frontend/node_modules/parcel-bundler/src/Resolver.js:71:17)
I don't think this is getting fixed since all the focus is on Parcel 2.
https://github.com/parcel-bundler/parcel/issues/2813#event-2432647097
@YassienW this is broken in Parcel 2
@mjgerace pretty sure this works perfectly in Parcel 2. What exactly is broken about it?
@DeMoorJasper it resolves to entry-pont directory as root instead of the package.json (or node_modules) parent directory as root. I can upload an example project/provide more details when out of work, if you'd like.
Pretty sure #3141 fixed that
@DeMoorJasper I am on the absolute latest version, but I can see when I get home and give you more information.
Still not working for me in latest version (alpha 2.3). TS compiles fine, Visual Studio autocompletes fine, parcel says path doesn't exist.
tsconfig:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": [
"./src/*"
]
},
....
},
"include": [
"./src/**/*"
]
}
Folder structure:
root
- package.json
--src
---index.html
Command: parcel src/index.html
or parcel ./src/index.html
.
Error:
@parcel/resolver-default: Cannot find module '~/config/Config' from 'C:\project-root\src\components\sidebar'.
I also get Build failed. Error: Got unexpected undefined.
sometimes when building, after I clear the cache this undefined error goes away.
I also have to note that in Parcel v1 this worked as expected.
Parcel 2 is broken with respect to TypeScript tilde paths.
In the Parcel docs it tells us to use ~
to refer to files relative to the src
folder. See this tsconfig.json
from the example:
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"~/*": ["./*"]
},
"typeRoots": ["node_modules/@types"]
},
"include": ["src/**/*"]
}
And this from the gist:
import { Reset } from '~/ui/shared/Reset'
No src
path in the example -- and in Parcel 1 it worked.
Apparently Parcel 2 is using ~
as a relative path to the package.json
folder? That profoundly breaks all TypeScript code which depends on the original example. The original approach is frankly a _more sane_ assumption, too; otherwise you're adding src
redundantly to all imports.
The original approach is frankly a more sane assumption, too; otherwise you're adding src redundantly to all imports.
The problem with Parcel 1's ~
is that was never really was src
but rather the nearest parent folder of all entries:
โโโ package.json
โโโ src
โโโ index.html (entry) with `<script src=./index.ts`
โโโ index.ts
-> ~ = root/src
โโโ package.json
โโโ index.html (entry) with `<script src=./src/index.ts`
โโโ src
โโโ index.ts
-> ~ = root
Understood. But the _sane_ approach includes _let us define what the root folder should be_. Don't just pick one arbitrarily; let us have a say in it.
And let us pick src
in the second example, even though index.html
is outside of src
. In fact, the _best_ case would be to let us pick an array of root folders, and just search for every ~
file sequentially in each root.
Don't break hundreds of lines of existing code because of some arbitrary new rule you'd like to add. Make the feature actually _useful_.
Even better: Respect the paths
entry from the TypeScript file instead of relying on a hack.
Understood. But the sane approach includes let us define what the root folder should be. Don't just pick one arbitrarily; let us have a say in it.
Parcel 2 has support for custom resolver plugins, so even a non-core userland plugin could resolve ~
however it wants.
(Not that we don't want to support this, but we also have other priorities at the moment)
All of that is typescript specific. Parcel has supported tilde resolution for literally years, and it applies the same way across all file types. TS doesn't get to dictate how all of Parcel works.
As @mischnic said, Parcel 2 supports custom resolver plugins, and these can be chained. So we could easily support a @parcel/resolver-typescript
package for better TS support, which could override the default resolver for TypeScript files.
A TypeScript resolver sounds perfect, so that would address my immediate request. Something that is linked from the TypeScript docs would be even better.
Any documentation on how a resolver should work?
WIP docs: https://parcel2-docs.now.sh/plugin-system/resolver/
default resolver plugin: https://github.com/parcel-bundler/parcel/blob/f65aa4c53ab130debfc88f4628eb001f52fb5f63/packages/resolvers/default/src/DefaultResolver.js
default resolver implementation: https://github.com/parcel-bundler/parcel/blob/f65aa4c53ab130debfc88f4628eb001f52fb5f63/packages/utils/node-resolver-core/src/NodeResolver.js
Something that is linked from the TypeScript docs would be even better.
Sure
Merging this into https://github.com/parcel-bundler/parcel/issues/202.
The original issue post and the most +1'ed comment say
~ should resolve to the package root (closest node_modules),
which is already the case in Parcel 2.
Most helpful comment
The code does appear like it's set up how it's supposed to be, but
~
is also not working for me as described in the above issue report.~
should resolve to the package root (closest node_modules), but it is resolving to the entry point, not the package location. As soon as I changed my entry point from./index.html
to./src/index.html
, my~
references broke, and I had to change them to relative folders with..
.