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

Feature: support new package.json exports field #670

Closed
jsamr opened this issue Apr 28, 2021 · 16 comments
Closed

Feature: support new package.json exports field #670

jsamr opened this issue Apr 28, 2021 · 16 comments
Assignees

Comments

@jsamr
Copy link

jsamr commented Apr 28, 2021

exports field is a new standard which adoption will inevitably grow further as the ecosystem switches to full ESM as NodeJS 10 reaches EOL. It's probably best to support it before things break. Features:

  • Export submodules with sub-path exports;
  • Specific exports for both CJS and ESM modules.

Example of subpath exports from NodeJS docs:

{
  "type": "module",
  "name": "es-module-package",
  "main": "./main.js",
  "exports": {
    ".": "./main.js",
    "./submodule": "./src/submodule.js"
  }
}

The consumer of the library can now use:

import submodule from 'es-module-package/submodule';
// Loads ./node_modules/es-module-package/src/submodule.js
@kamleshchandnani
Copy link

Is there any plan to support this any time soon?

@alamothe
Copy link

alamothe commented Mar 1, 2022

Any workarounds?

@jamesgpearce
Copy link
Contributor

jamesgpearce commented Apr 15, 2022

Here's a workaround I used. In https://github.com/tinyplex/tinybase, I omit the "main" field in my package.json to prefer "exports".

To get this to work with Metro, I added a "react-native" field that points to the file. It's apparently not documented, but this is used as a higher-priority location than "main". "browser" is another option you might prefer.

Works a charm in tinyplex/tinybase#17:

image

@kamleshchandnani
Copy link

kamleshchandnani commented May 16, 2022

@robhogan any plans to support this? or we can enable it if it's behind some flag?

@pleerock
Copy link

Without this feature it basically makes impossible to use most of ESM modules out there with react-native.

@huntie
Copy link
Member

huntie commented Aug 24, 2022

Hi all 👋, happy to share that exports field support is on our roadmap for the second half of 2022. We haven't scheduled this work immediately, but once we have progress I will make sure to post an update here.

@evelant
Copy link

evelant commented Sep 7, 2022

That's good news. @huntie hopefully this can get bumped up in priority. Lots of popular packages are beginning to drop commonjs support. Without full ESM support in metro react-native users are stuck on increasingly old/broken/insecure versions of packages.

@Tjerk-Haaye-Henricus
Copy link

Hey Folks 👋
Since we are in the seccond half of 2022 already do we have an estimation when this feature will arrive or is there any workaround already ?

@huntie
Copy link
Member

huntie commented Oct 17, 2022

Update:

Workarounds for apps remain possible by configuring resolver.resolveRequest (configuring as documented). This will allow you to set overrides for specific import paths, to patch "exports" functionality on a case-by-case basis.

@Tjerk-Haaye-Henricus
Copy link

Wow thats great, thanks for your answer 🙏 I'm glad to have a workaround. I will try it immediately 🤓

@david-zacharias
Copy link

We ran into this issue while using fp-ts-std. Our current workaround within a monorepo setup is this:

// packages/app/metro.config.js

const path = require('path')
const { createMetroConfiguration } = require('expo-yarn-workspaces')

module.exports = (() => {
  const workspaceRoot = path.resolve(__dirname, '../..')
  const config = createMetroConfiguration(__dirname)

  const { resolver } = config

  config.resolver = {
    ...resolver,
    extraNodeModules: new Proxy(resolver.extraNodeModules, {
      get: (target, name) => (name === 'fp-ts-std' ? path.resolve(workspaceRoot, `node_modules/${name}/dist/esm`) : undefined)
    })
  }

  return config
})()

@matthew-dean
Copy link

Also missing is subpath imports, which was added in Node v14.6.0, v12.19.0.

@pke
Copy link

pke commented Dec 1, 2022

All bundlers will always be behind nodejs itself. Makes me wonder why nodejs can't bundle JS itself.

@paulmillr
Copy link

Any updates? This is painful for JS library authors.

@huntie
Copy link
Member

huntie commented Feb 17, 2023

Yes I can give an update! 😅 The implementation is well underway — the most recent batch of commits starts with 38b96f8.

We're planning to ship Package Exports in the next Metro release, and — fingers crossed — in time for React Native 0.72. For this launch, the feature will be disabled by default and marked "unstable", enabled by the resolver option unstable_enablePackageExports.

Furthermore, this will be accompanied by a blog post on the React Native blog. I'll be writing up an explanation of the feature, plus instructions and gotchas for app developers and package maintainers who want to enable the feature today.

After this, we're aiming to stabilise Package Exports for React Native 0.73 (pending other priorities).

@huntie huntie assigned huntie and unassigned robhogan Feb 17, 2023
@Albert-Gao
Copy link

Great news, it is in beta now! 😍

https://reactnative.dev/blog/2023/06/21/0.72-metro-package-exports-symlinks#new-metro-features

image

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