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?
Unmet Dependencies When Testing When you use peer dependencies, npm will not automatically install those dependencies (see comments above in respect to npm version 7).
It is not possible to use peer dependencies in TypeScript. WebStorm does not recognize them and marks import statement as invalid. package. json is completely valid and the code can be built by any bundler.
Npm link is a command that allows you to link a specific npm project to another. That's about it! It's mainly used to be able to test a library onto a project without having to publish the library into npm.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With