14

I started to build a component library that I want to publish on NPM (and reuse in other apps) by creating a React app using create-react-app. Unfortunately the create-react-app default configuration doesn't seem to support building such component libraries (see these issues). So it seems I have to eject.

Do you have some instructions what to configure after ejecting to make this a component library I can reuse in other apps (I guess some Webpack stuff)?

Yangshun Tay
  • 49,270
  • 33
  • 114
  • 141
medihack
  • 16,045
  • 21
  • 90
  • 134
  • 1
    CRA by default hides all the tooling from you as you focus on just the React part. You should be able to simply move your code into a tooled project and use it. IMO this will be easier over ejecting. It should be an hour or two for setting up the tooling using existing projects, or (more fun) do it yourself. Its not much with the newer versions of babel, webpack etc. – hazardous Apr 03 '17 at 10:41
  • You should be able to clone these very lean components (for their tooling code) and put in your own components' code there - https://github.com/wangzuo/react-progress-label, or https://github.com/aaronshaf/react-toggle. – hazardous Apr 03 '17 at 11:01
  • Added more details in my answer - http://stackoverflow.com/a/43183468/2790937. – hazardous Apr 03 '17 at 11:52
  • Thanks for your answers. One final question ... what makes `create-react-app` so special? What features does it have that are not relevant for developing a component? I also need the Webpack stuff, the testing stuff and so on for building a component. So what are those unneeded extras? – medihack Apr 03 '17 at 22:51
  • Hi @Zardoz, I have updated my answer to have the information you requested. Depending on your use case, you won't need the server hosting code spit out by eject, and your webpack setup will need changes as mentioned in my answer, to suit a component library. This is not taken care by CRA so you'll need to do it :). – hazardous Apr 04 '17 at 05:55
  • It is partially possible without ejecting, see my answer here: http://stackoverflow.com/questions/39684689/using-react-create-app-to-create-library/43916281#43916281 – madox2 May 11 '17 at 13:04

3 Answers3

12

Re-framing my comments into an answer.

Don't eject! CRA hides a lot of stuff under the hood and ejecting throws it up. It's relatively easier to just clone your src into another project with the tooling setup done.

And it's not very difficult to setup one yourself! Here's the things you will need to do:

  1. Basic babel and webpack configuration so your code compiles.

  2. Make sure React and React-DOM are added as external dependencies in your package.json file and added as alias in your webpack.config.js. (A thorough discussion is here.) This is important to ensure you ship the smallest bundles only. Also, React doesn't play well with multiple copies.

  3. Optionally, do the same for any other heavier libraries, e.g. Material-UI, Bootstrap, Lodash etc.

  4. In webpack's configuration, decide how you want your library exports should be? You should be good with UMD.

  5. Add main (and optionally module) entries in your package.json to let npm imports know where the components should be imported from.

  6. Publish it.

  7. Done!

Or, you can simply clone one of these super thin component projects and put in your components there -

There are more complete starter-kits as well, but IMO it's important to first know the details yourself before you abstract them away. Once you are familiar with the process, you should try leveraging the kits too as they go much beyond the basics, like test integration, react-storybook support and great npm publishing support.

UPDATES:

The purpose of CRA is to allow quick experimentation and on-boarding to React development, without going through the (somewhat complicated to a beginner) tooling setup. The intended use case of CRA, as denoted by the "App" in the name, is the whole app, not a component. Although developing anything built on language features like ES6 takes some tooling, an app typically takes more setup than a component. E.g. you also need a server component which hosts the generated code. CRA does all this and more for you.

And if you are working on an app, you will eject when you want to take control of the server side of it. It adds value in that case as you will get the basic hosting code auto-generated by CRA during eject.

To address test needs, CRA also has Jest integration, which is a test runner having React specific features like snapshot testing. Again, setting it up manually with your build pipeline is a handful and CRA once again hides all of this complexity from you, so you can simply focus on writing the tests.

Community
  • 1
  • 1
hazardous
  • 10,627
  • 2
  • 40
  • 52
2

This is super simple - you don't actually need webpack if you want to publish a package. Don't install it just for that if you don't want to.

If you use ES6:

You can use a simple script to create a dist folder that babel will create the files after transpiling:

"scripts": {
    // other scripts
    // .. might want to change "rm -rf" below if you're on a PC
    "build:production": "rm -rf es && cross-env NODE_ENV=production node_modules/.bin/babel ./src -d es"
  },

What this does is:

  1. Remove the es folder, which is a build folder.
  2. Runs babel for your files (in case they are located in src folder, change it to wherever your files reside) and create the es folder with the transpiled files.

In order to use the script above you need to install the following dependencies:

babel-cli / babel-core / babel-preset-es2015 / cross-env

Make sure you have a .babelrc file so that babel will work:

{
  "presets": [
    ["es2015", { "modules": false }]
  ]
}

Now all you have to do (after running npm run build:production) is to run:

npm publish

And your library is published in npm. This is also the command you run if you want to update, just don't forget to update the version number in your package.json.

In case you have files you dont want published to npm, just have a file in your root called .npmignore (similar to .gitignore) and list everything you want excluded.

If you don't use ES6:

In this case you don't need to transpile anything, just go straight to the npm publish section above and run it on the root folder you want published.

Omri Aharon
  • 16,959
  • 5
  • 40
  • 58
  • this actually makes sense..you could even push it further and use lerna..have your components set up with babel only and maybe one module with create-react-app for demo purposes..or just use styled components – Julius Koronci Aug 27 '17 at 23:17
1

create-react-app is meant for quick setting up and development of apps, not really for development of libraries. For one thing, create-react-app creates an index.html file when building, which is usually not needed by libraries. Libraries require a different set of configuration (much less).

I faced this problem myself and have written a React component boilerplate for writing and publishing React components: https://github.com/yangshun/react-component-starter, after referencing how popular ES6 libraries were written, such as Redux.

Pros:

  • Similar to create-react-app, batteries are included
  • It has got all the important areas covered: development, linting, testing, and distributing
  • Minimal configuration
  • Babel for transpilation to ES5 and CommonJS format
  • ESLint included and configured
  • Jest tests examples
  • Webpack configuration that compiles to UMD
  • React Storybook for quick development of the components
  • Support for stylesheet distribution alongside your component

Cons:

  • Highly opinionated in terms of choice of tooling; they follow the choices set by create-react-app.
  • Have to manually update each package dependencies in future (you'll face this issue if you did eject anyways)

There is minimal configuration included and setup is easy. The various webpack, Babel and ESLint configurations should be quite understandable.

Hope this will be helpful to you. Feel free to give suggestions and comments on how it can be improved.

Yangshun Tay
  • 49,270
  • 33
  • 114
  • 141
  • 2
    Thanks for your suggestion. Unfortunately, I am more looking for a way to convert an existing create-react-app (with Jest tests and so on). I guess that there are many people out there having this problem as creat-react-app is quite a common boilerplate for starting a React project these days and then later on decide it would be a worthy component library. – medihack Apr 02 '17 at 11:08
  • By component library do you mean one that is `npm install`-able by other developers? If so, `create-react-app` is unlikely to be suitable because it's meant for building apps, not libraries. – Yangshun Tay Apr 02 '17 at 11:11