Corentin S.
Corentin S.

Reputation: 6000

Sharing a typescript library in a monorepo

I'm trying to setup a monorepo with 3 services sharing some library code.

This is the current situation:

repo: web
pdf/
  package.json
    reference to shared-ts using github url
  tsconfig.json
frontend/
  package.json
    reference to shared-ts using github url
  tsconfig.json
repo: mobile (react-native)
  package.json
    reference to shared-ts using github url
  tsconfig.json
repo: shared-ts
  package.json
  tsconfig.json

This works but it's a pain to commit to shared-ts, build, change the hash in package.json and commit again.

This is what I'd like to achieve:

repo: monorepo
pdf/
  package.json
    reference to ../shared-ts
  tsconfig.json
frontend/
  package.json
    reference to ../shared-ts
  tsconfig.json
mobile/
  package.json
    reference to ../shared-ts
  tsconfig.json
shared-ts/
  package.json
  tsconfig.json

So far I've tried:

Is there a good way of doing this? Any ideas on other things I could try?

Upvotes: 36

Views: 20585

Answers (5)

Muhammad Numan
Muhammad Numan

Reputation: 25413

Solution 1:

with Lerna

you can use workspace and Lerna

yarn workspace & lerna

├── README.md
├── lerna.json
├── package.json
├── packages
│   ├── pdf
│   │   ├── package.json   /*  "shared-ts": "^1.0.0" */
│   │   └──  src
│   ├── frontend
│   │   ├── package.json
│   │   └── src
│   ├── mobile
│   │   ├── package.json
│   │   └── src
│   ├── shared-ts
│   │   ├── package.json
│   │   └──  src
├── tsconfig.json
└── yarn.lock

here is an example repo

here you can see x-cli is getting shared x-core

Solution 2:

without Lerna

you can use mtsl package which enables us to make tangible symlinks. you can install this package globally

npm install -g mtsl

then you just need to start to separate these three commands in terminal.

mtsl startwithoutadd -s path_of_project/packages/shared-ts -d path_of_project/packages/pdf/node_modules/shared-ts

mtsl startwithoutadd -s path_of_project/packages/shared-ts -d path_of_project/packages/frontend/node_modules/shared-ts

mtsl startwithoutadd -s path_of_project/packages/shared-ts -d path_of_project/packages/mobile/node_modules/shared-ts

Note don't stop this three watcher. after testing, you can make single command from the package.json script

Upvotes: 8

Kanishk Anand
Kanishk Anand

Reputation: 1702

You can use NX to maintain your repos, wherein your web and mobile repos will be your apps, and the shared-ts will be a lib such that, web and mobile depends on shared-ts lib.

You have a common package.json, or a separate package.json for each repo individually. NX provides dependencyGraph and affected features, wherein if you change the common libs, it figures out which modules/app to build without having to build the complete thing.

Your code structure would look like:

apps:
  web:
    src
    package.json

  mobile:
    src
    package.json

libs:
   shared-ts:
     src
     package.json

workspace.json

It'll probably be best to lookup the official docs for the best setup and options, but I believe it provides what you're looking for.

Upvotes: -1

Sayan Pal
Sayan Pal

Reputation: 4956

Your use-case can be handled using the npm7 workspaces. In short your new monorepo structure should look like below:

repo: monorepo
package.json // <- here you define the workspaces
pdf/
  package.json
    reference to shared-ts
  tsconfig.json
frontend/
  package.json
    reference to shared-ts
  tsconfig.json
mobile/
  package.json
    reference to shared-ts
  tsconfig.json
shared-ts/
  package.json
  tsconfig.json

You need to list the workspaces in the root package.json which might look something like below:

{
  "name": "awesome-monorepo",
  "workspaces": [
    "pdf",
    "frontend",
    "mobile",
    "shared-ts"
  ]
}

After doing that, wherever in the monorepo you decide to use the shared-ts you can add that to dependencies or devDependencies simply referring by the version number instead of relative path.

All the node modules inclusive the workspaces gets hoisted to the root node_modules which is why the module resolution should work without friction.

Upvotes: 8

Hanan Mehmood
Hanan Mehmood

Reputation: 295

I have done the things you are curious about in a recent project. Desired results can be achieved by monorepo using lerna and yarn workspace. For details, please go to this link

With the above, we will be creating a package of types. In other packages, we will be just importing types from packages like below:

import { Post } from "@types";

Things are much easier this way than linking packages ourslef.

Upvotes: -1

Liu Lei
Liu Lei

Reputation: 1297

using yarn workspace & lerna

here is an example monorepo-template

Upvotes: -2

Related Questions