repack icon indicating copy to clipboard operation
repack copied to clipboard

`enablePackageExports: true` includes broken `byDependency` key for `Repack.getResolveOptions`

Open tringenbach opened this issue 6 months ago • 3 comments

Describe the bug

I am using repack 5.1.2 and creating a new project using react-strict-dom and respack. react-strict-dom says to turn on packageExports in Metro (but of course I am not using Metro). So I set that option in Repack.getResolveOptions

However, that caused it to import the dom version. I tracked it down to the byDependnecies: key that was being returned by getResolveOptions. I unset that key entirely and it fixed my issue.

See https://github.com/callstack/repack/blob/9793a503461e0dc5b8e830acb5b353477f5b895c/packages/repack/src/utils/getResolveOptions.ts#L112-L120 for the current code:

  /**
   * We add `import` and `require` to conditionNames everytime
   * because package imports are enabled at all times in metro
   * and they need condition names to be defined.
   */
  const byDependency = {
    esm: { conditionNames: ['import'] },
    commonjs: { conditionNames: ['require'] },
  };

I don't know if omitting that when packageExports is on is correct, or if it needs to be more complicated (by including react-native in there somewhere.

react-strict-dom's package.json:

https://github.com/facebook/react-strict-dom/blob/main/packages/react-strict-dom/package.json#L5-L19

  "exports": {
    ".": {
      "react-native": {
        "types": "./dist/native/index.d.ts",
        "default": "./dist/native/index.js"
      },
      "default": {
        "types": "./dist/dom/index.d.ts",
        "default": "./dist/dom/index.js"
      }
    },
    "./babel-preset": "./babel/preset.js",
    "./runtime": "./dist/dom/runtime.js",
    "./package.json": "./package.json"
  },

And here's a link to react-strict-dom's metro setup instructions: https://facebook.github.io/react-strict-dom/learn/setup/#metro-configuration

System Info

Sorry, I can't copy/paste between laptops.
- rnc/cli: 19.0.0
- react: 19.0.0
- react-native: 0.79.0

Re.Pack Version

5.1.2

Reproduction

I provided a lot of detail, but I don't have a repo. If you really need one I can try to make something to upload.

Steps to reproduce

  • Create a new repack project
  • add react-strict-dom
  • turn on enablePackageExports: true
  • import {html} from 'react-strict-dom'; and try to render a div or something. (It fails on import, so doesn't matter what you try to do with it)

Without turning on the packageExports flag, I was able to get rsd to work by using a deep import to the native directory. Once I turned it on, the deep import was not allowed and the shallow import also did not work. Once I cleared byDependency it started working again (with the the shallow import).

tringenbach avatar Jun 20 '25 21:06 tringenbach

hey @tringenbach

The byDependency configuration matches what Metro does. On the other side - I think we are missing parsing react-native as an exports condition before import/require in both cases. Then instead of going for dom we would end up with react-native first and then we would use import/require conditions.

The easiest way to check this would be to include react-native as a condition for these entries, like this:

const byDependency = {
  esm: { conditionNames: ['react-native', 'import'] },
  commonjs: { conditionNames: ['react-native', 'require'] },
};

Would you like to research this further and eventually contribute a PR with a fix for this?

jbroma avatar Jun 23 '25 09:06 jbroma

Thanks for your reply @jbroma

The easiest way to check this would be to include react-native as a condition for these entries, like this:

Ok, I tested that and I can confirm that that also works for importing react-strict-dom.

Which makes sense, the problem was that it wasn't choosing react-native.

Would you like to research this further and eventually contribute a PR with a fix for this?

I can make an attempt.

I actually had kind of a difficult time troubleshooting this. Does Repack, Rspack, and/or Metro have an option to log it's resolutions or anything like that? I was looking for something like tsc's --traceResolution but couldn't find anything. Probably just something obvious that I missed.

tringenbach avatar Jun 23 '25 14:06 tringenbach

I can make an attempt.

Since you've already checked that it works with react-native condition it should be as simple as adding react-native to byDependency config :)

I actually had kind of a difficult time troubleshooting this. Does Repack, Rspack, and/or Metro have an option to log it's resolutions or anything like that? I was looking for something like tsc's --traceResolution but couldn't find anything. Probably just something obvious that I missed.

I'm not aware of any package like this, but it should be doable in a simple form through existing webpack hooks (like normalModuleFactory.hooks.afterResolve) - you could obtain the resolved path there.

jbroma avatar Jun 23 '25 15:06 jbroma