4

I have a monorepo with the following structure:

repo
  packages
    native (expo app)
    server (express + graphql)
    shared (to be shared with the rest)
      build
        graphql
          index.d.ts
          index.js
        models
          user.d.ts
          user.js
          locale.d.ts
          locale.js
          index.d.ts
          index.js
        utils
          datetime.d.ts
          datetime.js
          index.d.ts
          index.js
        index.d.ts
        index.js
      src
        graphql
          index.tsx
        models
          user.ts
          locale.ts
          index.ts
        utils
          datetime.ts
          index.ts
        index.ts
      tsconfig.json
    web (nextjs app)
  lerna.json
  package.json
  tsconfig.json

I'm currently using the shared package like this:

import { getTodayFn, UserClass } from '@repo/shared'
import { getTodayFn } from '@repo/shared/build/utils'
import { UserClass } from '@repo/shared/build/models/user'

But I'd like to be able to import without build:

import { getTodayFn } from '@repo/shared/utils'
import { UserClass } from '@repo/shared/models/user'

What should I do to achieve what I want?

Configurations:

root/tsconfig.json:

{
  "compilerOptions": {
    "sourceMap": true,
    "removeComments": false,
    "preserveConstEnums": true,
    "downlevelIteration": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "allowUnreachableCode": false,
    "noFallthroughCasesInSwitch": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "pretty": true,
    "forceConsistentCasingInFileNames": true
  }
}

packages/shared/tsconfig.json:

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "jsx": "react",
    "lib": [
      "dom",
      "esnext"
    ],
    "skipLibCheck": true,
    "preserveConstEnums": true,
    "rootDir": "./src",
    "outDir": "./build",
    "declaration": true,
    "declarationDir": "./build",
    "declarationMap": true,
    "baseUrl": "./",
    "paths": {
      "@lib/*": [
        "src/*"
      ]
    }
  },
  "include": [
    "./src/**/*"
  ],
  "exclude": [
    "node_modules",
    "build"
  ]
}

packages/shared/package.json:

{
  "name": "@repo/shared",
  "license": "MIT",
  "version": "1.0.0",
  "main": "build/index.js",
  "typings": "build/index.d.ts",
  "scripts": {
    "build": "rimraf build && tsc",
    "watch": "tsc -w"
  },
  "dependencies": {
  },
  "devDependencies": {
    "rimraf": "^2.6.3",
    "typescript": "^3.5.3"
  }
}

Mehmet N. Yarar
  • 576
  • 9
  • 17
  • Are you looking for only changing the path or also creating different packages? – Doğancan Arabacı Jul 22 '19 at 14:05
  • i'd like to access to the folders separately, kind of "separation of concerns" if you will. for example, if i need some datetime function, i should be using `import { dateTimeFn } from '@repo/shared/datetime'` but with the current configuration i can't do that. whenever I put a slash in the VSC, `/build` is popping up. You can see [here](https://imgur.com/XPb2l9L). – Mehmet N. Yarar Jul 22 '19 at 14:29
  • For example, you can import lodash's get like this: `import { get } from 'lodash'`, but also like this: `import get from 'lodash/get'`. it's not like `import get from 'lodash/build/get'`. i don't know what I'm missing but I hope I was able to explain my concern. – Mehmet N. Yarar Jul 22 '19 at 14:34
  • I understood your concern but it actually has no benefit. Packages like lodash, material-ui etc, they separate the modules as well, so that your project becomes tree shakeable and your last bundle size is smaller. You can achieve what you want by publishing your build folder instead of publishing it from root level (don't forget to copy package.json). If you also want to separate into tree shakable modules, i'd recommend to check this => https://github.com/mui-org/material-ui/tree/master/packages/material-ui/src – Doğancan Arabacı Jul 22 '19 at 14:50
  • I'd appreciate if you could expand on this: > publishing your build folder instead of publishing it from root level (don't forget to copy package.json) - how can i publish the build folder? - do i suppose to copy `packages/shared/package.json` to `packages/shared/build/package.json`? – Mehmet N. Yarar Jul 22 '19 at 16:57
  • What you want to achieve is removing 'build' from path, essentially. So, when you created build directory in packages/shared/build, copy packages/shared/package.json, change main and typings fields of package.json to not include 'build' in path, go to build folder and npm publish from there – Doğancan Arabacı Jul 23 '19 at 08:41
  • 1
    `npm publish` is supposed to publish a package to the npm, right? I get 401 - unauthorized error and actually I don't want to publish anything to npm, since this is a **monorepo**. – Mehmet N. Yarar Jul 23 '19 at 17:58
  • 1
    You should use Project References. See [the second half of this answer, under "this is great for monorepos"](https://stackoverflow.com/a/61467483/8910547) – Inigo Apr 29 '20 at 01:19
  • 1
    @Inigo This looks very helpful. I'll try it out soon, thanks. – Mehmet N. Yarar May 12 '21 at 10:19

0 Answers0