简体   繁体   中英

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:

  • TypeScript project references, but it seems like there is no way to have dependencies in the shared-ts project
  • "shared-ts": "../shared-ts" in package.json but it copies shared-ts into the node_modules of each package so I have to re-run yarn everytime I make a change
  • yarn link in postinstall : error TS2307: Cannot find module 'shared-ts' or its corresponding type declarations.
  • creating a symlink directly in postinstall with ln -s../shared-ts/ node_modules/shared-ts/ but it seems TypeScript fails to find the module
  • npm link in postinstall seems like the most promising but it's really slow and I'm having trouble running it in CI because of some permissions issues.

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

using yarn workspace & learn

here is an example monorepo-template

I have done the things you are curious about in a recent project. Desired results can be achieved by monorepo using learna 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.

Solution 1:

you can use mtsl package which us to make tangible symlinks. you can install this pacakge 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

Solution 2:

you can use workspace and lerna

yarn workspace & lerna

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM