How To Create A Local NPM package of React Components

One of the big benefits of React.js is reusable components. In fact, you’ve probably used one of the many awesome react.js components from npm. Rather than copy and paste your own components from project to project. Here’s how to create a local npm package of react components.

Useful Boilerplate

https://github.com/juliancwirko makes it easy to create a NPM Package of React Components. I wanted a package called myappincome, so I did the following:

  • Clone the repo into myappincome with git clone https://github.com/juliancwirko/react-npm-boilerplate.git myappincome
  • Remove the git repo that was cloned with cd myappincome; rm -rf .git
  • Edit package.json so the name of the package is “myappincome”
  • Initialize a new git repo with git init
  • npm install
  • Edit \src\index.js to create a very simple component like:
import React from 'react';

class MyComponent extends React.Component {

    render() {
    return (
      <div>
        FROM INSIDE MY COMPONENT
      </div>
    )
   }
};

export default MyComponent;

As you can see, not the most useful component in the world, but will demonstrate this works fine.

Let’s try it out.

Using it in a project

To keep things simple, I’ll use [Create-React-App] to demonstrate how our package can be used. The process will be similar for whatever project you’re working with.

create-react-app testlocalpackage
cd testlocalpackage
npm install --save /path/to/myappincome

You should see something very similar to this:

npm WARN prepublish-on-install As of npm@5, `prepublish` scripts will run only for `npm publish`.
npm WARN prepublish-on-install (In npm@4 and previous versions, it also runs for `npm install`.)
npm WARN prepublish-on-install See the deprecation note in `npm help scripts` for more information.

> myappincome@1.0.1 prepublish /tmp/myappincome
> babel --plugins transform-es2015-modules-umd src --ignore __tests__ --out-dir ./dist

src/index.js -&gt; dist/index.js
testlocalpackage@0.1.0 /private/tmp/testlocalpackage
└── myappincome@1.0.1 

You can see the package is called “react-npm-boilerplate” and version “1.0.1”. You can change this in package.json, but for now, I’m leaving it alone.

Now edit src\App.js to import and use our component:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import MyComponent from 'myappincome';

class App extends Component {
	render() {
		return (
		<div className="App">
			<div className="App-header">
				<img src={logo} className="App-logo" alt="logo" />
				<h2>Welcome to React</h2>
			</div>
			<p className="App-intro">
				To get started, edit <code>src/App.js</code> and save to reload.
			</p>
			<MyComponent />
		</div>
		);
	}
}
export default App;

That’s it! Start the application with yarn start and you should see our component being rendered:

MyComponent In Create React App

MyComponent In Create React App

Multiple Components

So far, we’ve only got one component. Adding multiple components is a little trickier as we can only export 1 as default. That means we have several options. To keep this short, I’m going to show an example of adding 2 more components and the various ways they can be exported and included in an app.

Two More Components

Let’s create two news files in \src. The first called TestComponent.js:

import React from 'react';

class TestComponent extends React.Component {

    render() {
    return (
      <div>
        FROM INSIDE TEST COMPONENT
      </div>
    )
   }
};

export default TestComponent;

A second called SampleComponent.js with:

import React from 'react';

class SampleComponent extends React.Component {

    render() {
    return (
      <div>
        FROM INSIDE SAMPLE COMPONENT
      </div>
    )
   }
};

export default SampleComponent;

Finally, rename src\index.js' tosrc\MyComponent.js’. We’ll be creating a new index.js next.

Exporting multiple components

Mozilla’s article on explaining the different types of import and export is about the best I’ve come across. If you’re not comfortable with the different types, definitely go and read that before the rest of this post.

Create src\index.js with the following:

import SampleComponent from './SampleComponent';
import  MyComponent from './MyComponent';
import TestComponent from './TestComponent';

export default TestComponent;
export {MyComponent, SampleComponent};

Importing Multiple Components

Update App.js to:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import TestComponent, {MyComponent, SampleComponent}  from 'myappincome';

class App extends Component {
	render() {
		return (
		<div className="App">
			<div className="App-header">
				<img src={logo} className="App-logo" alt="logo" />
				<h2>Welcome to React</h2>
			</div>
			<p className="App-intro">
				To get started, edit <code>src/App.js</code> and save to reload.
			</p>
			<MyComponent />
      <br />
      <SampleComponent />
      <br />
      <TestComponent />
		</div>
		);
	}
}
export default App;

Refresh the app and it doesn’t work! That’s because there’s a drawback to packaging up your components in an npm package.

Drawback

Unfortunately, any changes we make to our components in myappincome don’t show up in our app automatically. Just like when a new version of an app is released on npm.

Thankfully, it can be easily worked around by deleting the myappincome folder with rm -rf node_modules\myappincome and then running npm install again after every change.

It’s not ideal, but at least it works.

MultipleComponents in Create React App

MultipleComponents in Create React App

Conclusions

It’s now much easier to share components between all our projects and we haven’t had to install a local npm server like Sinopia.

What’s more, if at some point in the future we decide to publish our package on npm, we can.

As always, I’m not sure this is the best way to do this. It works, but if you know of a better way, please get in touch either in the comments below, or on twitter https://twitter.com/myappincome.

No comments yet, your thoughts are welcome.

Leave a Reply

Your email address will not be published. Required fields are marked *