Parcel: 🙋 Support project-relative import paths

Created on 19 Dec 2017  ·  18Comments  ·  Source: parcel-bundler/parcel

Projects with a deep folder structure often have import paths with lots of "../../../../../a/b/c/d/actualFile.js" in them because import paths are kind of restricted.

One workaround in webpack is to define custom aliases for the resolver, but this approach would break the zero-configuration approach of parcel.

Would it be possible to have at least an additional notation for "project-relative" imports in parcel, so that the dotdot madness at the beginning could be stopped?

🎛 Configuration (.babelrc, package.json, cli command)

N/A

😯 Current Behavior

Apparently (??) no support for project-relative import paths.

💁 Possible Solution

  • Resolve './abc' relatibe to the current file (as is)
  • Resolve '/abc' absolute to filesystem (or webroot? as is)
  • Resolve 'x/abc' relative to module 'x' (as is)
  • Resolve '-/abc' or '.../abc' or similar relative to current or nearest parent folder with a package.json file in it (package root)
Good First Issue Help Wanted Feature RFC

Most helpful comment

@ is good to go on Windows. This seems to be widely accepted as the "package root" character, especially among webpack users which would ease adoption.

All 18 comments

Hmm I actually really like this idea! 😮 😃 👏

This would be supper useful

Resolve ‘-/abc’ or '.../abc' or similar relative to current or nearest parent folder with a package.json file in it (package root)

Not sure about the syntax for package root though…

  • I don’t really like like -/abc since - looks a lot like ~ (maybe this was intentional, but it could make the difference hard to spot)
  • …/abc wouldn’t work either since it kinda implies “go back 3 directories”, or at least it does for anyone using ZSH as their terminal 0_O

I propose using @ to represent “package root”:

@/abc

As far as I know the “@“ simple doesn’t have any reserved meaning in file paths (@brandon93s maybe it does on Windows?).

If not we could also use #:

#/abc

@ is good to go on Windows. This seems to be widely accepted as the "package root" character, especially among webpack users which would ease adoption.

I believe react-native(or one of the tools for it)allows you to define a package.json in any folder. The 'name' property defined in that json file can then be used as an alias for the folder, as if it was in node_modules, just like webpack alias.

For example: in app/someDir2/someDir2, i put a package.json file with name = 'myDep', now 'anywhere' in the folder hierarchy i can simply import ... from 'myDep/someFile', the same way webpack alias works.

https://medium.com/@davidjwoody/how-to-use-absolute-paths-in-react-native-6b06ae3f65d1

Please remember that @ is also a namespace indicator for scopes npm packages, so under no circumstances should a leading @ alone be treated as a reference to the package home; @/ should work though.

Another option that I've sometimes stumbled upon is ~.

Vue-loader uses tilde.

~assets/foo.png

It might be good to stick with existing conventions.

On Dec 19, 2017, at 5:06 PM, Ron Don Jon notifications@github.com wrote:

Please remember that @ is also a namespace indicator for scopes npm packages, so under no circumstances should a leading @ alone be treated as a reference to the package home; @/ should work though.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

Unless anyone has objections, I'm going to add tilde support, like vue-loader. Also I really like the package.json name idea; we might be able to do that.

This relies on some FS changes I've been working on; stay tuned.

@shawwn awesome, many thanks!

Hello, I wanted to try out parcel with my team's component library and ran into a snag, and i'm wondering if this issue will resolve it.
In our scss file we use the tilde to do an import of a scss file that is a separate package in our node_modules
@import '~terra-mixins';

Based off https://github.com/webpack-contrib/sass-loader#imports

webpack provides an advanced mechanism to resolve files. The sass-loader uses node-sass' custom importer feature to pass all queries to the webpack resolving engine. Thus you can import your Sass modules from node_modules. Just prepend them with a ~ to tell webpack that this is not a relative import:

Based off the conversation, it seems this fix might resolve my issue, just wanted to check.

Thanks!

IMO this should only resolve to the project root for files actually in the project. For node_modules, it should resolve to the root of that module. e.g. in node_modules/test/foo/bar.js, ~/baz should resolve to node_modules/test/baz. This way code in node_modules always works the same way regardless of what application it is installed in.

Sure, hence "nearest parent folder" in the initial suggestion.

So, we have two different approaches to basically the same problem: how to reference files starting at the root of a module. This issue proposes using tilde (e.g. ~/foo/bar.js), but #86 + #290 uses absolute paths (e.g. /foo/bar.js). Not sure we should support two ways to do the same thing. What do we think? Are there plusses and minuses to each?

@devongovett I think "~" would be the easiest one to implement as it will not be used for an actual absolute path inside the resolver for example when trying to implement it in my pull request i kinda hit a wall for the fs resolves as some already include __dirname and are absolute paths.

Also I think we should support absolute paths like /index.html, but solely for html assets, as this is supported by servers/browsers by default

I could change my PR to handle what I just said perfectly pretty easily, and it would probably end up being less code than the current implementation

@devongovett @DeMoorJasper I strongly advise against mixing absolute and project relative paths as it is done in the current implementation of #290. This makes the build machine-dependent! Resolving /foo to <PROJECT_ROOT>/foo or /foo depending on the existence of the absolute path is a build debugging nightmare waiting to happen:

  1. Build works
  2. > touch foo
  3. Build broken :scream:

IMO, absolute paths should be resolved as exactly that (apart from document-root-relative handling for HTML maybe; I have yet to look into that use case) and paths starting with ~/ should be resolved relative to the closest package containing the importing file.

Other than that, I can't wait for this feature to be released! :heart_eyes:

@shawwn @rondonjon Regarding the question of ~/ vs @/:

  • The official vue.js webpack template uses @
  • @ by itself is not a valid package name (checked by trying to create such a package with npm), so there is no potential for shadowing. I don't know if that is true for ~.
  • Unsuspecting Linux users could mistake ~/ as a reference to their home directory. On the other hand, this syntax could be seen as a kind of home directory metaphor in the context of a package.

That being said, I stand slightly in favor of @/, but ~/ would be perfectly fine for me too :relaxed:

See #850 for an implementation of both absolute and tilde paths, which mean slightly different things. Let me know if you have any feedback!

Is there any way to set root path once in configuration or CLI?
Like in Webpack it is possible via context configuration property.

For anyone using TypeScript, you're gonna need this to support ~ imports and keep tsserver happy:

In tsconfig.json:

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

Documentation: https://www.typescriptlang.org/docs/handbook/module-resolution.html in the _Path mappings_ section.

Was this page helpful?
0 / 5 - 0 ratings