Publishing a React component package on npm
August 02, 2020 • 5 min read
Table of Contents
Recently at work I had to create and publish a React component on npm, which is planned to be used in multiple projects with little functionality or styles changes.
Due to being a company project, I can't share the source code, but I will share some important snippets as needed.
It isn't as easy as expected 😕
When I was asked to do such task, we already had the component built and working as a create-react-app
project, which was also a website and stuff.
I thought it would be as simple as running npm publish
and that I was going to be able to import it in the other project right away.
Unfortunately it wasn't like that and I ran into compilation issues in the project that implemented it. So I started looking for the right way to do it.
Meet create-react-library
🤓
While searching how to achieve that, I came across with create-react-library
.
I was looking for the simplest approach to do what I needed, and didn't want to deal with webpack
or babel
stuff and whatnot, so that project definitely came in handy because it was easy to use and pretty straight forward.
Using create-react-library
👨🏼💻
Creating a library project is as easy as running
npx create-react-library project-name
You will be prompted for some config, similar to create-react-app
, but once done, you get the project and everything setup to work right away.
I liked it because I didn't have to do much else, and it also comes with an example project inside, that uses your library, so you can test everything will be working properly after you've "published" the package.
Next thing for me was just migrating the component from the previous project to the library project. It was pretty much a copy-paste process with some little refactoring, but nothing significant else.
The challenges 😬
Despite requiring no configuration, I encountered a couple problems during the process...
1. React Fragments 🖼
I was getting compilation errors for using React Fragments like this <>{...}</>
, so I changed that to <React.Fragment>{...}</React.Fragment>
and they stopped... well, kinda.
Then I started getting ReferenceError: Fragment is not defined
errors. It wasn't easy to solve so I asked for help in the Unicorn Utterances discord server, and Corbin found an issue in the create-react-library
repo that mentioned adding --jsxFragment React.Fragment
to the build
and start
scripts.
And then it was all working again.
2. Included SVGs 📐
The component included an SVG (the company logo), imported and used something like this:
import CompanyLogo from './company-logo.svg'
...
return (
...
<img src={CompanyLogo} alt={'Company Logo'} />
...
);
It worked fine locally, even with the local project that imported the component library, but after published in npm and imported in the other project, compilation failed, because the svg file was "compiled" with a different name, similar to company-logo~aBcDe.svg
. Notice the ~
character. That was the issue, because it can't be used in JS var names.
The quick solution, was to make it a prop and allow passing it to the component, so it wasn't compiled by the library but the other project. Again, I didn't want to deal with webpack
or babel
or any extra config, so this was the easiest for me.
3. CSS 🎨
I was using css modules for the library components, but I also needed a little of normal css, because the component used other components from rmwc
, and they use that and I needed to override a few styles.
From what I understood create-react-library
the normal css and the module css files would coexist and work along normally, but for some reason, it wasn't like that, and the normal css was still compiled as a module, i.e. the compiled classes names would have some random suffix to make them unique, and therefore none of the overriden styles were applied.
At the end, I ended up changing the css modules to normal css, so no suffix was added during compilation, and then it all worked as expected.
Closing up 👋🏼
So, after struggling with those few things, I was able to use the component from the library without any other issues, and everything was working as expected, including react hooks like useContext
and useReducer
.
Also, create-react-library
definitely allowed publishing the package by just running npm publish
as I wanted it to be.
There are probably other approaches to build a react component(s) package, but this one worked for me and was easy to use, so I liked it and wanted to share my experience.
If you have further questions, I'll try to answer. Find more about me @ jahir.dev
Special thanks to Corbin Crutchley, Alex Dueppen and Robert Mennell from the Unicorn Utterances discord server, who helped me solve the issues and get the library working.
Cover image is from unsplash.com