standard-things / esm

Tomorrow's ECMAScript modules today!
Other
5.26k stars 146 forks source link

Get `esm` to work with `rooty`? #834

Closed chriscalo closed 4 years ago

chriscalo commented 5 years ago

We all run into this problem:

import foo from '../../../../foo';

There's a solution called rooty that fixes this for calls to require(). So, instead of:

const foo = require('../../../../../foo');

you can use:

const foo = require('^foo');

However, this doesn't seem to work out of the box with esm when using the import foo from "^foo" syntax.

Two questions:

  1. Is there some patch or config option that can enable interop between esm and rooty?
  2. Is there some other mechanism for intercepting and transforming import paths in esm?
tunnckoCore commented 5 years ago

To the questions: I don't think so.

You should avoid using such methods. Probably better way would be to rethink your architecture and organization. :) Or if you are using Babel, ESLint or Webpack, they have similar approaches (that work better?).

chriscalo commented 5 years ago

I ended up finding the following solution via link-module-alias that works well enough for me. (Plus postinstall-postinstall to run the postinstall function not only on install but also on uninstall.) I would prefer having some hook for rewriting any import path, but this suffices for my needs.

{
  "scripts": {
    "postinstall": "link-module-alias",
    "start": "node -r esm index.js"
  },
  "dependencies": {
    "esm": "^3.2.25",
    "link-module-alias": "^1.2.0",
    "postinstall-postinstall": "^2.0.0"
  },
  "_moduleAliases": {
    "~": "."
  }
}

This makes it possible to import from the project root from any module:

import { foo } from "~/foo";

FWIW, I'd rather not introduce a build step, and it would be nice if ESM's behavior was open for configuration / extension in some of the same ways require() is.

But my issue is solved if you want to close this. 👍