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

react-dom/server cannot be resolved with unstable_enablePackageExports and condition browser #1135

Open
robhogan opened this issue Nov 10, 2023 · 5 comments

Comments

@robhogan
Copy link
Contributor

(As reported by @EvanBacon)

Metro cannot resolve react-dom/server with unable_enablePackageExports (and condition browser?), reporting:

warning: Attempted to import the module "/Users/evanbacon/Documents/GitHub/expo/node_modules/react-dom/server.browser.js" which is not listed in the "exports" of "/Users/evanbacon/Documents/GitHub/expo/node_modules/react-dom". Falling back to file-based resolution. Consider updating the call site or asking the package maintainer(s) to expose this API.

Conditions

  unstable_conditionNames: [ 'node', 'require' ],
  unstable_conditionsByPlatform: { web: [ 'browser' ] },

package.json

  "exports": {
    ".": "./index.js",
    "./client": "./client.js",
    "./server": {
      "deno": "./server.browser.js",
      "worker": "./server.browser.js",
      "browser": "./server.browser.js",
      "default": "./server.node.js"
    },
    "./server.browser": "./server.browser.js",
    "./server.node": "./server.node.js",
    "./profiling": "./profiling.js",
    "./test-utils": "./test-utils.js",
    "./package.json": "./package.json"
  },
  "browser": {
    "./server.js": "./server.browser.js"
  },
@robhogan
Copy link
Contributor Author

We'll need to check other tools to see how browser/exports are expected to interact - there's no spec for this, but apparently we're taking a matching browser value and looking it up in the exports map, which must be wrong.

A browser field match should probably skip exports in the same way that main does.

@huntie
Copy link
Member

huntie commented Nov 15, 2023

There is no spec for this, but we've been building to the expectation that "browser" (or any other user redirection) does redirect fully. It specifies a package subpath, which we will resolve against the package, considering "exports" if present.

https://facebook.github.io/metro/docs/resolution/#resolution-algorithm

Changing this behaviour in Metro (so that a mainFields mapping is a target that bypasses "exports") would be non-trivial (given the wide applications of the redirectModulePath API under the current resolution algorithm).

Ideally, react-dom should be updated so that the ./server.browser.js target is accessible. (OR, we should move forward with removing redirectModulePath in a simplified resolver 😅)

    "exports": {
      "./server.browser": "./server.browser.js",
+     "./server.browser.js": "./server.browser.js"
    },
    "browser": {
      "./server.js": "./server.browser.js"
    },

@robhogan
Copy link
Contributor Author

There is no spec for this, but we've been building to the expectation that "browser" (or any other user redirection) does redirect fully.

Is there ecosystem precedent for this? In the absence of a spec we ought to align, and the situation with react-dom (a reasonably popular package 😅) does suggest it's Metro that's doing something different.

@robhogan
Copy link
Contributor Author

robhogan commented Nov 15, 2023

It specifies a package subpath, which we will resolve against the package, considering "exports" if present.

This doesn't seem right tbh. A package author can't write their main, browser, etc on the assumption that exports will be applied on top, so these will point to real file subpaths (eg ./dist/index.js), and then needing to add those targets (real file paths) to the exports map would defeat the point of the exports abstraction.

@huntie
Copy link
Member

huntie commented Nov 17, 2023

Hmm, fair point! This problem blocks stable Package Exports.

I'm thinking:

  • For "main", "browser", indeed these are pre-"exports" concepts — we should allow any mapped relative target to be resolved using file resolution (change).
  • We would still expect other redirectModulePath return values (which may be any type of import specifier — e.g. to another package) to consider "exports" during subsequent resolution (no change).

(⬆️ Within Metro, it's really time to kill off redirectModulePath IMO.)

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

2 participants