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

Cannot resolve dependency (with Typescript import relative to project root) #4014

Closed
uglycoyote opened this issue Jan 17, 2020 · 7 comments
Closed

Comments

@uglycoyote
Copy link

uglycoyote commented Jan 17, 2020

🐛 bug report

I have a Typescript source tree with files in many directories. When importing a file (e.g. src/SomeLibrary/SomeHelperFile.ts) into a file in another directory (e.g. src/Foo/FooComponent.tsx) I would like to import relative to the project root, and avoid imports that are relative to the current file.

Typescript allows this, and VSCode does this by default (when I allow it to write the import statement for me), but Parcel gives me "Cannot resolve dependency" errors, forcing me to change it to a relative import (relative to the importing file), e.g. ../SomeLibrary/SomeHelperFile.tsx.

With more deeply nested directories I get into situations where have imports beginning with ../../.. which is annoying and brittle.

Related issues

I have read through the following issues but none of them seemed exactly the same nor did they contain an answer that I was satisfied with.

Issue #1624
Issue #1555
Issue #88
Issue #1324
Issue #1993

🎛 Configuration

My understanding from reading the Typescript module resolution page is if a "non-relative" import (i.e. one which does not start with slashes or dots) is resolved relative to the baseUrl specified in the tsconfig.json (or, looked up in places like node_modules).

I'm simply using:

        "baseUrl": ".",

with a tsconfig.json in the root of the project.

💻 Code Sample

I have created a repo with a test case at https://github.com/uglycoyote/parcel-import-problem

just npm install and npm start should repro (with error displaying in browser)

🤔 Expected Behavior

Parcel should not have difficulty finding the file when I do something like

import { AddOne } from "src/SomeLibrary/SomeHelperFile";

😯 Current Behavior

D:\Mike\Dev\parcel-import-problem\src\Foo\FooComponent.tsx:24:31: Cannot resolve dependency 'src/SomeLibrary/SomeHelperFile'

the parcel-import-problem repo builds successfully when I change the import to read:

import { AddOne } from "../../src/SomeLibrary/SomeHelperFile";

or

import { AddOne } from "../SomeLibrary/SomeHelperFile";

but again I am trying to avoid using imports relative to the current file.

🔦 Context

This is painful when writing a large application in VSCode. I can type the name of a class that has not yet been imported in to the current file, and VSCode will automatically import it, but the import statement will fail to work and I will need to change it to an awkward import starting with ../../../ to satisfy Parcel.

🌍 Your Environment

Software Version(s)
Parcel 1.12.4 (just updated before writing this report)
Node 10.16.3
npm/Yarn 6.4.1
Operating System Windows 10 (though, pretty sure I got same behaviour on my Macbook)
@mischnic
Copy link
Member

Have you tried ~/src/SomeLibrary/... or ~/SomeLibrary/... (https://parceljs.org/module_resolution.html#~-tilde-paths)

@uglycoyote
Copy link
Author

uglycoyote commented Jan 18, 2020

@mischnic Thanks for the suggestion. I was not aware of tilde paths so I tried it just now, but I don't think this is what I want.

importing from the root of the project did not work

import { AddOne } from "~/src/SomeLibrary/SomeHelperFile";

reading the parcel doc for this a bit more closely, it seems that the tilde paths are interpreted as being relative to the entrypoint's location (in the case of this test project the entrypoint is src/index.html so the following actually works:

import { AddOne } from "~/SomeLibrary/SomeHelperFile";

I'm unsatisfied with the solution for a few reasons:

  • As far as I can tell, tilde is a Parcel-specific thing, that doesn't appear to be a standard thing in any Typescript (or JS/ES) documentation. I'd rather be using a standard approach that does to tie my code specifically to Parcel. (note, Webpack also seems to allow the use of tilde's but I'm not sure if it has the exact same interpretation of them as Parcel)
  • VSCode does not understand the import with the tilde, it puts a red squiggle under it, and features like "go to definition" are broken due to the import not being understood. (I assume this again is related to it not being a standard import syntax for Typescript)
  • In my actual project I have several entry points that live in different folders, so since Parcel is interpreting the tilde import as being relative to the entry point, it's not going to work (the tilde path would have to be different depending on where the entry point lived)

In my opinion Parcel should be able to understand the import that I give it in the same way that Typescript and VSCode understand it, which would be as relative to the baseUrl specified in the tsconfig.json file.

@mischnic
Copy link
Member

which would be as relative to the baseUrl specified in the tsconfig.json file.

Please follow #202 for that

@uglycoyote
Copy link
Author

More information:

  • I Tested my parcel-import-problem repo on MacBook, behaviour was same, so not a Windows-specific issue
  • I noticed that in some places in my real project I am using imports relative to the project root successfully, such as
import { BoundingBox } from "src/generic/Math/BoundingBox";

It's not clear why Parcel would be OK with this in some places and not in others, e.g. the line right before that i have another import which fails

import { SVGAnimatedTransformGroup } from "src/generic/SVG/SVGAnimatedTransformGroup";

but it works if I change it to be

import { SVGAnimatedTransformGroup } from "../generic/SVG/SVGAnimatedTransformGroup";

it's not clear why Parcel would be able to understand the BoundingBox import but not understand the SVGAnimatedTransformGroup import when they are basically the same syntax

@uglycoyote
Copy link
Author

Tilde imports seem to work reasonably well with VSCode and Typescript when using

    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "~/*": ["./src/*"]
        },

This was suggested by @croaky and improved upon by @Inori-Lover in the gist https://gist.github.com/croaky/e3394e78d419475efc79c1e418c243ed which I found linked off that #202.

When doing this, VSCode will understand the tilde imports and even auto-suggest them (sometimes, but not always, I haven't figured out the pattern as to why it works sometimes and no others.)

I think my issue is basically a duplicate of #202 and so I'll close it. The heart of the matter is that Parcel is not respecting the baseUrl which is what #202 was about. Pity that this has gone unsolved for more than two years though when Parcel is supposed to work nicely with Typescript out of the box. I put my +1 in on that issue for what it is worth. Sounds like this is kind of, sort of on the radar for Parcel's version 2, though it sounds like even then it's not planned to be part of the core and just something that will be easier to "implement better resolvers in plugins", as I believe I read somewhere else.

I also think that it's strange that the current behaviour is inconsistent as mentioned in my previous posting, but perhaps that's a separate bug, or maybe there's a logical reason.

@uglycoyote
Copy link
Author

P.s. I was attempting to change my code over to use tilde imports after figuring out the paths config trick above, but I ran in to other issues with this, my Jest tests were failing because Jest did not understand the tilde imports. Maybe there is some way to get that to work as well but the best solution for me would be if parcel understood baseUrl, as in issue #202.

@NordlingDev
Copy link

NordlingDev commented Oct 21, 2020

I actually got this to work by doing the following with tsconfig.json:

{
    ...
    "baseUrl": ".",
    "paths": {
        "~/*": ["./src/*"]
    }
}

Then, index.html needs to be inside src directory in order for it to interpret the tile path the same as VS Code.

Now, wherever you are inside src directory, this would resolve correctly:

import { App } from "~/app"; // Resolves to: "src/app/index.ts"

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

No branches or pull requests

3 participants