JacopoPatroclo / nx-react-native-expo

Expo Managed Plugin for Nx
39 stars 18 forks source link

Trouble importing with paths like: '@coolmono/cool-library/CoolComponent' #10

Open Enricopv opened 3 years ago

Enricopv commented 3 years ago

I get the below issue when I try to import using something like:

// This is fine as usual ✅
import { CoolComponent } from '@coolmono/cool-library'

// These ones produces the error below ❌
import { CoolComponent } from '@coolmono/cool-library/CoolComponent'
import CoolComponent from '@coolmono/cool-library/CoolComponent'

Error 😞

(node:10116) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open 'fs.js'
    at Object.openSync (fs.js:457:3)
    at Object.readFileSync (fs.js:359:35)
    at formatBundlingError (C:\Users\Enric\Desktop\Projects\fluentsolar\node_modules\metro\src\lib\formatBundlingError.js:93:10)    at C:\Users\Enric\Desktop\Projects\fluentsolar\node_modules\metro\src\HmrServer.js:435:32
    at Generator.throw (<anonymous>)
    at asyncGeneratorStep (C:\Users\Enric\Desktop\Projects\fluentsolar\node_modules\metro\src\HmrServer.js:72:24)        
    at _throw (C:\Users\Enric\Desktop\Projects\fluentsolar\node_modules\metro\src\HmrServer.js:95:9)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:10116) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)(node:10116) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

All of those three patterns of importing works fine in my Next.js apps and all my React or normal JS libraries. Metro seems to be the one having the issue.

I prefer to import with @mono/lib/component as a general convention because I don't want to import all the components / utilities of that library (Next.js chokes really hard in local development on > 100mb pages because @mono/lib will have a lot of components). Obviously for react-native projects I can just do @mono/lib, but my other libs use @mono/lib/component and this error pops up again.

Maybe I'm just a newb and there's a way to import with @mono/lib (with an index.ts with a lot of exports) where I don't get absolutely everything from it. Maybe this might be a more appropriate issue to report in the nx-react-native repo?

My tsconfig.base.json looks something like this:

"baseUrl": ".",
"paths": {
      "@coolmono/cool-library/*": ["libs/cool-library/src/lib/*"], <-- has ./CoolComponent/index.tsx
      "@coolmono/cool-library": ["libs/cool-library/src/index.ts"],
}

My package.json

 "@nrwl/cli": "11.2.12",
    "@nrwl/cypress": "11.2.12",
    "@nrwl/eslint-plugin-nx": "11.2.12",
    "@nrwl/express": "11.2.12",
    "@nrwl/jest": "11.2.12",
    "@nrwl/next": "11.2.12",
    "@nrwl/node": "11.2.12",
    "@nrwl/react": "11.2.12",
    "@nrwl/react-native": "^11.4.1",
    "@nrwl/storybook": "11.2.12",
    "@nrwl/tao": "11.2.12",
    "@nrwl/web": "11.2.12",
    "@nrwl/workspace": "11.2.12",
    "nx-react-native-expo": "^0.0.9",

I enjoy using this tool in my monorep. Thanks for all the work you do!

Enricopv commented 3 years ago

I'm going to try to reproduce this in a none expo project. If the issue is also there I'll hit up the @nrwl/react-native issues and link to it from here.

JacopoPatroclo commented 3 years ago

Hi, @Enricopv. First thanks for the clear exposition of the issue. I'll look in to it the next weekend. If the issue is also present in the @nrwl/react-native and I found a viable solution I'll create also a pull request for that package too. There is a lot in common between that package and this one (obviusly).

Two words about this issue, metro let you opt in and customize the module resolution process. And that is what this pachage and the @nrwl one do. The problem is that in order to resolve where the libs are inside the monorepo we use a package called ts-config-paths here. Basically is that library that creates the matching function that tell metro where to get the files. I think that if in the tsconfig there is not a direct reference to a .ts file the package is not smart enought to figure out the correct path. I'll get a definitve answer and a fix after later this week.

A "workaround" could be to define each library by hand in the tsconfig, but obviusly is not a definitive solution.

Enricopv commented 3 years ago

@JacopoPatroclo thanks for explaining where the issue might be. I'll take a stab at the path resolution issue!

RWOverdijk commented 3 years ago

@JacopoPatroclo thanks for explaining where the issue might be. I'll take a stab at the path resolution issue!

How's the stabbing going? 😄

Enricopv commented 3 years ago

I was able to find the problem @JacopoPatroclo was referring to and found a way to hack it, but have left it alone as I had to focus on other things for work. I'll be looking at it again this week as it's becoming more important for us to work this out.

The problem is in this file here.

The import { createMatchPath, loadConfig } from 'tsconfig-paths'; used by getMatcher can't seem to find the paths.

I got this to work for a specific file by adding the path for it manually instead of the matcher = getMatcher() line.

  // const matcher = getMatcher();
  // const match = matcher(realModuleName);
  const match =
    'C:\\Users\\me\\Desktop\\Projects\\coolmono\\libs\\cool-library\\src\\CoolComponent\\CoolComponent.tsx';

Of course this would need to be done for each file imported in the pattern mentioned above in the issue. I plan on writing a fix for our needs soon, will share here. The solution might be a little hacky, but if it's cool with people I'll make a pull request.