Publishing a React component package on npm

Publishing a React component package on npm

Table of Contents:

  1. It isn't as easy as expected ๐Ÿ˜•
  2. Meet create-react-library ๐Ÿค“
  3. Using create-react-library ๐Ÿ‘จ๐Ÿผโ€๐Ÿ’ป
  4. The challenges ๐Ÿ˜ฌ
  5. Closing up ๐Ÿ‘‹๐Ÿผ

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