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

Making exports viable for CommonJS #26

Closed
guybedford opened this issue Jan 16, 2019 · 4 comments
Closed

Making exports viable for CommonJS #26

guybedford opened this issue Jan 16, 2019 · 4 comments

Comments

@guybedford
Copy link
Contributor

guybedford commented Jan 16, 2019

At today's meeting there was interest in upstreaming this proposal already to CommonJS.

If we do this, we need to have the ability to provide "exports" differently between ESM and CJS, in order to handle dual mode use cases (if we want that!).

I will start off with a proposal here, feedback and suggestions further are welcome.

The idea would be to branch based on a "condition" in exports:

{
  "exports": {
    ".": "./main.js",
    "./x": "./x.js"
  }
}

would still be supported fine, and apply for both CommonJS and ESM loaders.

But then we would also support an object form to branch between the two:

{
  "exports": {
    ".": {
      "cjs": "./main-cjs.js",
      "esm": "./main.js"
    },
    "./x": {
      "cjs": "./x-cjs.js",
      "esm": "./x.js"
    }
  }
}

The nice thing about this approach is the branch conditionals could also be extended to things like "browser", "node", "production", "development" allowing a general conditional subpathing based on the environment.

Do we want to move forward with a proposal along these lines? Perhaps we should set up a call to discuss further?

@jkrems
Copy link
Owner

jkrems commented Jan 16, 2019

Wouldn't it be easier to create the same general idea for CommonJS, just without the locked down default? It feels a bit fragile to allow this level of context-sensitive logic inside of exports. It opens the door to "what happens when some are mapped for CJS and some aren't". Does that introduce a new implicit deny..? I'm thinking about this kind of config:

{
  "./public/": {
    "esm": "./lib/api",
    "cjs": "./src/api"
  },
  "./public/data/": "./data"
}

Does this mean ./data is mapped for both? Just ESM? What if it would be "./public/data/": { "esm": "./data" }?

As an alternative, I would see the following as a lot nicer:

{
  "exports": {
    ".": "./main.mjs",
    "./x": "./x.mjs"
  },
  "main": {
    ".": "./main.js",
    "./x": "./x.js"
  }
}

@guybedford
Copy link
Contributor Author

Does this mean ./data is mapped for both? Just ESM? What if it would be "./public/data/": { "esm": "./data" }?

If we match ./public/data/ then it matches for both (specificity always wins). If there wasn't a CJS mapping for ./public/data then it falls through as a deny (we don't bubble up the match, or we could?).

As an alternative, I would see the following as a lot nicer:

Note we can't turn main into an object as that breaks backwards compat meaning no one would do it.

As for the suggestion of using a different key for CommonJS, I feel like there is a nice synnergy here with the "browser" mapping needs. It is a proven use case that we need to fork browser mappings sometimes. If we could support a "browser" condition just like "cjs" then we solve the browser problem as well very nicely.

@ljharb
Copy link
Contributor

ljharb commented Jan 16, 2019

What I like about exports is that it provides explicit renaming, and prevents requires/imports on non-export-declared files.

The problem of implicitly aliasing multiple files, including extensions, is something that i think should be different.

(Note that the "browser" field only provides 1:1 mapping, even in object form)

@jkrems
Copy link
Owner

jkrems commented Aug 15, 2019

exports is now an extended main field and applies to both CJS and ESM.

@jkrems jkrems closed this as completed Aug 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants