transitive-bullshit / react-modern-library-boilerplate

Boilerplate for publishing modern React modules with Rollup

Home Page:https://github.com/transitive-bullshit/create-react-library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Local installation with npm link (peer dependencies)

pgegenfurtner opened this issue · comments

I'm using this boilerplate (via create-react-library) to build a react library.

My library has some peer dependencies, for example styled-components - which needs to be a single instance.

If I don't install styled-components as a devDependency in my library, npm-linkin won't work and I get an error in the example, that styled-components was not found. (styled-components is installed in the example project)
Second option is to install it as a devDependency in my library, but then I have to instances of it.

Is there any way to fix this? I googled a bit and only found that it's a common problem.

Thanks!

The general rule of thumb I've found useful is that anything that's a peerDependency should be installed also as a devDependency in the project's source. Then you'd install those as a dependency in your example project. There are technically 2 versions of each installed in example/node_modules/X and node_modules/X but it should not matter, because only example/node_modules/X should ever be used due to the way node module resolution works.

Also, if you're using npm>=5, there's no reason to use npm link at all which should simplify things here. Just have your example project use file:.. to reference your library instead of relying on npm link which is a lot simpler and error-proof.

If my first suggestion isn't working for you, I'd be happy to take a look if you can point me to your source, as it's entirely possible I'm overlooking something :)

There are technically 2 versions of each installed in example/node_modules/X and node_modules/X but it should not matter, because only example/node_modules/X should ever be used due to the way node module resolution works.

That is my understanding too. But the errors I get speak otherwise.
I tried the file:.. too (via npm install ~/path/to/lib) but the problem remains.

I will set up a demo repo with exactly my use case.

Okay, the example repo is ready: https://github.com/pgegenfurtner/react-lib-test

What I've done:

  • Installed styled-components in the library (added as dev- and peer dependency)
  • Installed styled-components in the example (added as dependency)
  • Created a styled-component in the library and used it in the ExampleComponent
  • Created a styled-component in the example and used it beside the ExampleComponent
  • Linked the library to the example via file:...

If I now start the example, I get the following error message:

index.es.js:4158 It looks like there are several instances of 'styled-components' initialized in this application. This may cause dynamic styles not rendering properly, errors happening during rehydration process and makes your application bigger without a good reason.

and the style of the library-styled-component is broken.
When I remove styled-components from the node_modules of the library, it works fine - in this example repo. In my project I get an error, that styled-components is not defined. I will dig a bit deeper why this is.

As soon as I publish everything to npm, it is working since only one version of styled-components is present. But for local development this is a pain.

I'm taking a look now, but the first thing I noticed is that you're using an old version of create-react-library.

Also, what version of node and npm are you using? We strongly recommend npm >= 5

With node v10.3.0 and npm 6.2.0 for me, everything works fine on your example (example installs and runs and the styled component has a red background as intended). I just get a warning in the dev console "It looks like there are several instances of 'styled-components' initialized in this application..." which seems completely safe to ignore.

Note: I removed the package-lock.json files in order to test things fresh.

I'm taking a look now, but the first thing I noticed is that you're using an old version of create-react-library.
Do you think there will be a difference with the new version?

I'm using node 8 with npm 5 and tried node 10.3 with npm 6.2 with a fresh install (removed package-lock.json)

The problem is, that the local styled-component works (red background), but the component from the library doesn't (should have a black background)

This is how it looks:
wrong

This is how it should look:
right

@pgegenfurtner interesting, I'm seeing the same thing.

Let me investigate further and get back to you.

I still think this needs further investigation, as I don't understand why the "best practice" isn't working for us, but @pgegenfurtner I've found a workaround that should work for you for now.

If I don't install styled-components as a devDependency in my library, npm-linkin won't work and I get an error in the example, that styled-components was not found. (styled-components is installed in the example project)

I just tried this approach (removing styled-components from devDeps in the root package.json), and everything works as intended. The only minor annoyance is a warning when you run npm install that the source package requires a peer dependency of styled-components but none was found. This warning can safely be disregarded, and the example with file:.. builds and displays the result as intended.

I think the only thing different about my setup versus your original setup is that I'm not using npm link.

I know we found this fix for Webpack, not sure about Rollup though...

credit: @christiannaths
https://www.styled-components.com/docs/faqs#duplicated-module-in-node_modules

setting styled-components as a peerDependency in a react library
updating the Webpack config in my react app to prioritize it's own node_modules folder
I'm using create-react-app and react-app-rewired, so my config-overrides.js file in my react app now looks like this:

const path = require('path');

module.exports = function override(config, env) {

  config.resolve = Object.assign({}, config.resolve, {
    modules: [path.resolve(__dirname, 'node_modules'), 'node_modules'],
  });

  return config;
};

@designjudo this solution seems solved from the perspective of create-react-library.

If you're having issues using the library outside of CRL, please create a separate issue. I may be misunderstanding your comment, so feel free to comment below and I'll re-open.

Thanks, everyone!