Deno: importing absolute path does not resolve to current working directory

Created on 15 May 2020  路  14Comments  路  Source: denoland/deno

After reading https://github.com/denoland/deno/issues/203, I thought

import Dog from '/Dog.ts'

should import Dog from CWD/Dog.ts when run from local, but instead it resolves to the real root directory: file:///Dog.ts

Current workaround seems to be using import-map:

{
    "imports": {
       "/": "file:///path/to/my/cwd/"
    }
 }

But it's not ideal, since CWD could be different.

Am I missing something? Is CWD as absolute path on roadmap?

Most helpful comment

Import resolution has nothing to do with window.location (resource resolution root for web APIs) nor CWD (resource resolution root for FS bindings). Import URLs are based onto the URL of the importing module, so an absolute one is just appended to its origin: https://example.com/Dog.ts for https:// and file:///Dog.ts for file:// (though the latter is disabled altogether in browsers).

So the current behaviour is fine.

All 14 comments

think you can

import Dog from "./Dog.ts";

@fox-cat Yes, but that's not the absolute import.

an absolute import would be the root of your file system, that is what absolute paths mean... having an absolute path be relative to your CWD makes it a relative path and should be expressed as such... 馃し

@kitsonk, your conversation with @ry in #203 went like:


https://github.com/denoland/deno/issues/203#issuecomment-461617267
@ry: _Let's just assume that on the file system, the "root" is the current working directory_. If we resolve absolute paths and set window.location.origin to a file:// URL pointing to cwd, I think this solves the problem of working locally.

https://github.com/denoland/deno/issues/203#issuecomment-461619660
@kitsonk: to be clear...
If you run deno foo.ts then:
foo.ts requesting module /bar.ts will resolve to $cwd/bar.ts
(more)

https://github.com/denoland/deno/issues/203#issuecomment-461861965
@ry: I think we've reached consensus here on behavior. I will now accept implementations for abs path resolution


I believe the consensus is "CWD as root on the file system"

That was an absolute path of a remote module. We had a lot of debates about window.location and it just wasn't working in Deno. We agreed to remove it. Importing an absolute path of a local module refers to the root of the file system.

@nayeemrmn thoughts comments, as your head is more in this space these days than mine.

Import resolution has nothing to do with window.location (resource resolution root for web APIs) nor CWD (resource resolution root for FS bindings). Import URLs are based onto the URL of the importing module, so an absolute one is just appended to its origin: https://example.com/Dog.ts for https:// and file:///Dog.ts for file:// (though the latter is disabled altogether in browsers).

So the current behaviour is fine.

How importing urls work seems reasonable and well thought out, but I would like to focus our discussion on local imports.

Treating _real filesytem root_ as the root for local imports seems unbeneficial. With this behavior, using relative imports are kinda forced since it's very impractical to use absolute paths. Does anyone tried to use absolute path for local imports?

Wouldn't CWD as root give many advantages? Like @ry said in https://github.com/denoland/deno/issues/203#issuecomment-461617267,

this solves the problem of working locally

and makes absolute path a viable option.

I'm not just saying, I can work on this if it's desired.

@vincentvictoria No, CWD is out of left field and mutable.

@vincentvictoria I agree absolute URLs are very impractical. Not least because they behave differently from development to production for importable libs. I've almost suggested disabling outright. But we should just match browsers and let them be impractical, instead of misappropriating CWD for this.

Thanks, @nayeemrmn I didn't know CWD was mutable. Then it's no good. How about introducing startup directory (initial CWD) and use that for the import root? It may seem odd that import root is not real file root, but the key is that we can differentiate import from from regular file operations.

I agree that we should match browsers for most aspects, and the browsers actually do this. They don't treat / as file:// like deno but as a web root. Web servers know what / means in their real file system. deno currently doesn't have this (other than import maps) and left absolute paths impractical, and it's kinda giving up a good opportunity.

Nutshell:

  • deno is treating / as file://
  • browsers treat / as web root, and web servers know where / is in their file system.
  • Differentiating resolution strategy for imports and regular file operations makes absolute path practical.
  • For imports, how about using startup directory as import root?
  • For regular file operations, it stays the same.

Agree with @vincentvictoria. Having a / different of file:// is coherent with browser behaviour and a huge win for developer friendly import paths out of the box without additional external files.

It should be configurable, not just "starting cwd" as you may want it to be e.g. /src in development to match browser paths in production.

Ideally it should be configurable with just a command line flag and not depending on an external file like the importmap method.

Related to that I guess there is a good reason why an additional importmap file was prefereed instead of using the tsconfig standard baseUrl and paths. Maybe all this could come togeter and a --baseUrl flag make sense for configuring the / path?.

It should be configurable, not just "starting cwd" as you may want it to be e.g. /src in development to match browser paths in production.

"Production" for a Deno library isn't browsers, it's being accessible under an arbitrary CDN path:

import {} from "https://denoland/x/[email protected]/dist/liltest.js"
import {} from "https://unpkg.com/[email protected]/dist/liltest.js"

A library has no business using absolute imports for the reasons you describe or it wouldn't be portable. But if it really needs to, it can use an import map. We shouldn't provide two ways of doing that.

I just found that instead of specifying a full path in import maps:

{ "imports": { "/": "file:///a/long/path/to/my/cwd/" } }

I could use this:

{ "imports": { "/": "./" } }
It maps to starting directory. Now, I don't have to update the path every time.
Also for @drodsou :

{ "/": "./src" }

It solves the whole problem for me.

The import map section on deno manual gives a false impression that file:// is required:
supports only file:, http: and https: schemes
I will make a PR for the page and add this example.

Closing as it seems the discussion was settled. Feel free to reopen if need arises.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

watilde picture watilde  路  3Comments

JosephAkayesi picture JosephAkayesi  路  3Comments

ry picture ry  路  3Comments

sh7dm picture sh7dm  路  3Comments

kyeotic picture kyeotic  路  3Comments