Flow: Paths aliasing for import resolution

Created on 18 Jul 2015  路  6Comments  路  Source: facebook/flow

I'm trying to get analogous behavior to paths from CurlJS, RequireJS, and SystemJS. Suppose that I have a couple of files:

/.flowconfig
/lib/a.js
/external/root/someFile.js

How can I reference someFile.js from a.js without a relative import, i.e. import * from "rootAlias/someFile"?

Rummaging around, it looks like I can use the name_mapper option described at https://github.com/facebook/flow/issues/345#issuecomment-102141382 for aliasing. My first guess is

[include]
/external/
[options]
module_name.name_mapper = (
  '^rootAlias/\(.*\)' -> 'root/\1',
  ...
)

I hope that this configuration admits import * from "rootAlias/someFile". Is anybody already doing this successfully?

(I'm bummed by the weakness of specifier from ES6's 15.2.1.17 Runtime Semantics: HostResolveImportedModule (referencingModule, specifier): "The actual mapping semantic is implementation defined but typically a normalization process is applied to _specifier_ as part of the mapping process. A typical normalization process would include actions such as alphabetic case folding and expansion of relative and abbreviated path specifiers." I expect that all implementations will include a paths affordance--is there anything forthcoming for Flow?)

Most helpful comment

@jeffmo's <<rootDir>> landed as <PROJECT_ROOT> at v0.18.1.

All 6 comments

I've got a suboptimal solution. I can't see any way to get Flow to look at /external/ for all absolute paths. I think my expectation was guided by AMD's baseUrl. My solution uses absolute paths under the rewrite rules:

[options]
module.name_mapper='^rootAlias/\(.*\)'->'/absolute/path/to/root/\1'
module.name_mapper='^anotherAlias/\(.*\)'->'/abs/\2'

I can move forward with this, but I would describe it as a hack. Eventually I'll have a build step that populates a base template parameter analogous with baseUrl. Is there a less embarrassing solution?

I think you've found the only solution I can think of. @jeffmo is our local ES6 expert...maybe he'll have some ideas on thoughts on this.

Your name_mapper config looks correct. Over in Jest I found it useful to build in a special <<rootDir>> token that one could use in directory paths within the config (that would essentially be substituted with the absolute path prefix to the root of the project). For some obscure regexes this gets a bit weird...but 99% of the time it did the trick. Maybe we should include something like this for flow so you don't have to hardcode the absolute path.

On name resolution specification; This is being worked on over here: whatwg.github.io/loader/

It was not included in the ES spec because it wasn't clear what the optimal platform-agnostic algorithm should be (node may have differing needs from browser environments, etc).

Once this loader spec settles a bit more, we'll need to start thinking more about how we can integrate it with Flow...but it's probably going to be a bit tricky since it allows for dynamic resolution (and Flow needs to understand imports statically). Hopefully we can find some way of wrangling it, though.

For now in Flow we just opted to build support for Node's resolution algorithm as it seems to be the most pervasive algorithm out there and it works for both node and the browser (given Browserify/webpack/etc); The name_mapper config is currently our most flexible point of extension to this, but as you're discovering it does have its limits on expressivity.

Hope that answers your questions! I'll leave this issue open to track progress on a <<rootDir>>-like token a la Jest.

I also discovered module.system=haste, where it seems like Flow treats the directory containing .flowconfig as the AMD baseUrl directory. I've added a build step to my project that dumps my library root into an es6 directory beside my .flowconfig. My typical npm link-based workflow has become an ln -s-based workflow (for library root with alias rootAlias, ln -s /path/to/root /path/to/es6/rootAlias).

When I find the time to verify my intuitions against the source, I'll cobble together a docs-PR for module.system=node versus module.system=haste under "advanced configuration".

FYI: @mroch just added some docs that cover the [options] section of the config a bit better to hopefully surface their details more here: https://github.com/facebook/flow/pull/663

The module.system section could still probably use some more detail about what the differences between haste and node are, but it's a good start.

@jeffmo's <<rootDir>> landed as <PROJECT_ROOT> at v0.18.1.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mmollaverdi picture mmollaverdi  路  3Comments

jamiebuilds picture jamiebuilds  路  3Comments

funtaps picture funtaps  路  3Comments

john-gold picture john-gold  路  3Comments

philikon picture philikon  路  3Comments