How to serve a React component library dependent on Styled Components to another library that also has a Styled Comopnents dependency? How to serve a React component library dependent on Styled Components to another library that also has a Styled Comopnents dependency? reactjs reactjs

How to serve a React component library dependent on Styled Components to another library that also has a Styled Comopnents dependency?


This is only a partial answer that I'm hoping will enable you or someone else to figure out the rest. I'm far from an expert on managing these kind of dependencies and am helping with this to further my own knowledge since I may want to do a similar setup soon.

Though it seems this should be doable with nwb, I switched to using webpack directly in order to have more control. Even using webpack directly I have only made it part of the way there. Everything works correctly when I do a build, but in dev mode (npm start) for the CRA app, the styled-components package is still getting pulled in twice and the styling doesn't work correctly. This seems like a potential webpack issue since the dev and production modes behave so differently, but it could be something with the CRA webpack dev configuration or (more likely) some aspect of this that I don't yet understand.

This is a good example to reference for the component library configuration: https://github.com/kalcifer/webpack-library-example

Here's my package.json for my test component lib (component-lib3 just because of trying several other approaches):

{  "name": "component-lib3",  "version": "1.0.7",  "description": "component-lib3 React component",  "main": "dist/component-lib3.js",  "peerDependencies": {    "react": "^16.6.0",    "react-dom": "^16.6.0",    "styled-components": "^4.0.3"  },  "devDependencies": {    "react": "^16.6.0",    "react-dom": "^16.6.0",    "styled-components": "^4.0.3",    "@babel/core": "^7.1.2",    "@babel/preset-env": "^7.1.0",    "@babel/preset-react": "^7.0.0",    "babel-loader": "^8.0.4",    "webpack": "^4.24.0",    "webpack-cli": "^3.1.2"  },  "scripts": {    "build": "webpack"  }}

Here's the webpack.config.js:

var path = require('path');module.exports = {  entry: './src/index.js',  mode: 'production',  output: {    path: path.resolve(__dirname, 'dist'),    filename: 'component-lib3.js',    libraryTarget: 'umd',    library: 'component-lib3'  },  externals: {     "styled-components": {       commonjs: 'styled-components',       commonjs2: 'styled-components',       amd: 'styled-components'     },     "react": {       commonjs: 'react',       commonjs2: 'react',       amd: 'react'     },     "react-dom": {       commonjs: 'react-dom',       commonjs2: 'react-dom',       amd: 'react-dom'     }  },  module: {    rules: [      {        test: /\.js$/,        exclude: /node_modules/,        use: {          loader: "babel-loader"        }      }    ]  }};

And then also .babelrc:

{  "presets": ["@babel/preset-env", "@babel/preset-react"]}

I tried a number of variations, and I don't understand why this won't work right for dev mode.


I am facing the same issue at this moment and I'm still not sure. I could fix it properly or not, so please don't take this answer as a guaranteed solution.There are two things you can try.

The first one is something that appears in the styled-components FAQs section. They suggest configuring Webpack (I assume you are using Webpack too) with an alias so that it always looks for the styled-components dependency wherever you specify. This should avoid having several instances of styled-components, but so far I couldn't make this work for me.

The second option is to use an alternative no npm link. Apparently when you have a symlinked dependency (this is what npm linkdoes actually). The bundler's resolver tries to look for the dependency in the same project. This is also mentioned in the linked styled components FAQs section.What you should do if you follow this approach is to avoid creating a symlink that points to your component library from the CRA app and copy the folder instead.

There is a tool called wml that can copy the contents of your component library into the node_modules folder of your CRA app. wml is also able to watch for changes in your component library folder and it re-copies the changes to your CRA app's node_modules. So, we could say wml is kind of alternative to npm link. In my initial attempts it worked fine for me so maybe this is something you can try.

Be careful: There is an issue in wml that causes the files on your project to be removed on the first time you set it up. It didn't happen to me but I saw others suffering the problem so if you are going to try wml, please ensure you have all the changes pushed to your source code version control system.

These are the steps you would need to follow to setup wml for your projects using the command line:

wml add <component-library-folder> <CRA-app-folder>/node_modules/<name-of-component-library>wml start

Ideally I would prefer to solve this without having to use any external tool but if what styled-components maintainers suggest on their site is not valid, it could serve as a workaround.