Exporting React Components in NPM

I’ve been working on a set of re-usable React components that I want to be able to be imported and used in other projects. I was happily developing and testing the components using “create-react-app” (that I strongly recommend for React development) and everything was working fine. Once I had a body of work that I was happy with I tried importing it into other another project and that’s where the fun started…

Transpiling the Components

The problem I had initially was that my components would simply not work when imported into another project (even one created with “create-react-app”). This was because they were written in ES6 and Webpack was not configured to transpile the imported code (at least that’s my understanding of the situation).

In order to resolve this issue I need as transpilation build step to convert my code into something that could easily be understood when imported. I found that the best solution to this was to use Gulp and Babel and created the following script:

The key thing to note here is the use of the react-app Babel preset. Most of this article is relevant to NPM projects other than React but this is essential in order to get React components transpiled correctly.

All For One or One for All?

The next issue was whether or not to export all my modules as a single file or as individual modules. I reasoned that I wanted people to be able to pick and choose which modules they were importing even if other options were available (such as tree-shaking) for reducing their final project distribution.

I didn’t want to manually list and maintain all of the exports in my project so I wrote a script to generate them (again using Gulp):

I used Regular Expressions to target the 3 different types of ES6 export that I would expect to find:

  • export default MyComponent
  • export { MyComponent }
  • export { MyComponent as SomeOtherComponent }

Modules Are Not All Equal

To the best of my knowledge there are 3 main types of JavaScript modules:

In my React project I was using ES6 to import and export modules and it was working perfectly as Webpack was taking care of everything for me.

The problem was that whilst I could guarantee my own development environment I could not guarantee that of anyone wishing to import my components. I therefore needed to work to the lowest common denominator and when building an NPM package that would be CommonJS (because it is native to Node.js).

Although I was now capturing all of the exports from my project they were still in ES6 format and as with my component source they needed to be transpiled into something that was more easily interpreted.

This required a minor addition to the last few lines:

…again I used Babel to perform the transpilation but this time I was using the es2015 preset to convert the exports into the correct format.

Exports Location

I now had all my components transpiled and a file defining an export for each of them. In order for consuming projects to know what is available it is necessary to configure this in the package.json file of your project. My exports were being written into a lib/exports.js file so this was simply a case of adding this as the main entry like this:

Source Maps

One final thing that I added was support for source maps in order for consumers of my project to be able to easily debug and report issues if they found any.

Updating my original transpilation was simple enough:

…but I found that it was necessary for the consuming project to ensure that Webpack was configured to use eval source maps.

In create-react-app this is set in the webpack.config.dev.js file as cheap-module-source-map by default so requires ejecting or forking the project.

NPM Scripts

Even though I’m using Gulp to perform this build step I still personally prefer to use NPM scripts to use them. The final step in the process was to add a script definition into my package.json file:

Importing the Components

Having published the my project to NPM another component can install the package and then import individual components using ES6 import syntax. It’s important not to forget the curly brackets!

Final Build Script

Hopefully this will be useful for other projects — please let me know if you have any feedback, suggestions or comments on the approach I’ve taken.

This is the final build script:

Like what you read? Give Dave Draper a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.