Resolving TypeScript dependencies in yarn workspaces

Viewed 2970

I'm currently trying to set up a React/TypeScript monorepo with two workspaces, @scope/project-lib and @scope/project-app. I have @scope/project-app's package.json importing @scope/project-lib: "*" under dependencies. I can get it to work by doing

import { MyComponent } from @scope/project-lib/build/components/MyComponent

but consumers are going to use

import { MyComponent } from @scope/project-lib/components/MyComponent

after I publish it, so obviously I'd like to use it that way inside the workspace as well.

I referenced the project-lib path in my tsconfig for project-app:

  "compilerOptions": {
    "paths": { "@scope/project-lib/*": ["../project-lib/build/*"] }
    // other config options
  }

I also import it into project-app's package.json:

  "dependencies": {
    "@scope/project-lib": "*",
    "react": "^16.12.0",
    "react-dom": "^16.12.0"
  },

The odd part is that omitting the /build/ part of the path shows this error: Module not found: Error: Can't resolve '@scope/project-lib/components/MyComponent' in 'path/to/user/folder/scope/packages/project-app/src'

I don't understand why it's looking in src (or maybe I should be pointing everything as src? But then how does it build TS and JSX on the fly?)

1 Answers

I too have a monorepo with TypeScript + Lerna (w/ Yarn Workspaces) with ~50+ packages.

It is configured to not use the path directive, because Yarn Workspaces can automatically detect those and symlink to the package directory in the root node_modules folder. That way, it will be as it is any 3rd party package and the package.json's main/module field will be read and used.

Graphically

node_modules/
-- @scope/ -> (this is automatically generated by yarn)
---- foo -> symlink /packages/foo
---- bar -> symlink /packages/bar

packages/
-- foo/
---- dist/ -> built by TypeScript
------ index.js
---- package.json -> contains "main": "dist/index.js"
---- index.ts
---- tsconfig.json
-- bar/
---- package.json -> contains "@scope/foo" as dependency
---- index.ts -> contains "import {baz} from '@scope/foo'"
---- tsconfig.json

package.json
yarn.lock

NB. packages must be built at least once before type checking and such, to ensure that their dist folder exist

Related