21

I have a React/Redux typescript project A. My team decided to split out some of the React components and Redux code into an NPM module, so I created another React/Redux TS project B.

Initially, when I tried to install B from A, I got errors due to type redeclarations, since both A and B depend on the same type declarations files (react, redux, etc). So I moved all of B's @types dependencies to be peer dependencies. This allows me to properly install B from A.

However, for development purposes, I would like to npm link to B from A, so I don't constantly have to recompile and reinstall B. But because npm link creates a symlink, it points to the entire B project, including the type definitions that I need to avoid.

Does anyone know how to solve this conundrum?

gardenhead
  • 2,299
  • 2
  • 19
  • 17
  • 1
    Did you find a way to work around this? I'm running into the same issue. – chkal Aug 18 '17 at 16:41
  • 1
    @chkal Fortunately, I was able to convince my team lead to just keep everything in a single repository, eliminating this issue (and many others). – gardenhead Aug 18 '17 at 20:20
  • In our situation we have many projects that depend on a shared library module containing our React components. Therefore it is not that easy. However, googling a bit around it looks like more recent versions of TypeScript and Webpack may also fix this issue. – chkal Aug 19 '17 at 09:06
  • In projectA's tsconfig.json could you exclude `node_modules/projectB/node_modules/@types/react` etc... – Arcath May 02 '18 at 10:26
  • you can use yarn workspaces. https://yarnpkg.com/lang/en/docs/workspaces/ – Eduard Jacko Aug 01 '18 at 11:20
  • I don't think it is possible, you have to install new version of dependent module. But TypeScript 3.0 has new concept of having dependent projects, that may be independent of npm dependencies. You can simply include folder as source files inside tsconfig.json – Akash Kava Aug 15 '18 at 14:16
  • Have you looked into [yalc](https://github.com/whitecolor/yalc)? this looks like a use case where having a local NPM repo can help. – Diego Zacarias Dec 09 '18 at 23:14

1 Answers1

3

This problem isn't particularly related to typescript, but is a general problem of how to link two javascript packages together and prevent libraries from loading multiple times. A big factor on how you solve this is based on what build/bundler you use. I think this stackoverflow answer is pretty good if you only care about de-duping react.

Here is an example of solving it using webpack.

The first thing is make sure any shared dependencies in your child package are devDependencies and peerDependencies and your parent package is setting them as the needed dependencies and devDependencies.

A - package.json

{
  "dependencies": {
    "B": "1.0.0",
    "react": "x.x.x",
  },
  "devDependencies": {
    "@types/react": "x.x.x"
  }
}

B - package.json

{
  "version": "1.0.0",
  "peerDependencies": {
    "@types/react": "x.x.x",
    "react": "x.x.x"
  },
  "devDependencies": {
    "@types/react": "x.x.x",
    "react": "x.x.x"
  }
}

If you are running webpack from package A, you need to make sure to resolve node_modules when applicable only from package A's node_modules.

const path = require('path')
module.exports = {
  // rest of your webpack condig...
  resolve: {
    modules: [path.resolve(__dirname, 'node_modules'), 'node_modules']
  }
}

Here is also another solution using react-app-rewired that does the same thing

const path = require('path')
module.exports = function override(config) {
  config.resolve = Object.assign({}, config.resolve, {
    modules: [path.resolve(__dirname, 'node_modules'), ...config.resolve.modules]
  })

  return config
}
jjbskir
  • 8,474
  • 9
  • 40
  • 53