Creating a React library using Rollup & Gulp
Before I’ll start with how to create your own React library, I’d like to say I hate writing my own bundler config, task manager etc. I don’t mind using Create React App or any other well written boiler plate.
That been said, Let start with writing our own Rollup and gulp configs.
I guess that you are familiar with yarn / npm.
Init the project
Start by creating a new folder to hold our library. Inside that folder, init your project by using yarn int
Adding our devDependencies
Babel is a JavaScript compiler mainly used to convert ECMAScript 2015+ code into a backwards compatible version of Javascript. In our case it is also used to convert React’s JSX components to JavaScript
yarn add -D "@babel/core" "@babel/plugin-external-helpers" "@babel/preset-env" "@babel/preset-react" "@svgr/rollup" "babel-eslint"
ESLint is a linter tool for JavaScript
yarn add -D eslint eslint-plugin-react
Gulp is a task manager automation tool
yarn add -D gulp gulp-shell gulp-watch
Rollup is a module bundler and compiler for JavaScript
yarn add -D rollup rollup-plugin-babel rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-postcss rollup-plugin-ur
I save the best ones for last, our React dependencies
yarn add -D prop-types react react-dom
Now copy and paste those three packages, to your peerDependencies. We’d like to keep them extended from our bundle / compiled version.
Creating our ESLint config
Create a file name “.eslint” and add the following json.
{
"parser": "babel-eslint",
"plugins": ["react"],
"extends": ["eslint:recommended", "plugin:react/recommended"]
}
Here we set our linter to use babel as its parser to support extended JavaScript options as well as React
Create a file name “.eslintignore” and add the following lines.
gulpfile.js
node_modules
rollup.config.js
Here we just add some file we want the linter to ignore
Setting Babel configurations
Create a file name “.babelrc” and add the following json.
{
"presets": [
[
"@babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"modules": false
}
],
"@babel/react"
]
}
Here we set the way we’d like Babel to parse our JavaScript and React JSX.
Setting our Rollup bundler
Create a file name “rollup.config.js” and add the following configuration code.
import babel from 'rollup-plugin-babel'
import commonjs from 'rollup-plugin-commonjs'
import postcss from 'rollup-plugin-postcss'
import resolve from 'rollup-plugin-node-resolve'
import url from 'rollup-plugin-url'
import svgr from '@svgr/rollup'export default {
plugins: [
external(),
postcss({
modules: true
}),
url(),
svgr(),
babel({
exclude: 'node_modules/**',
}),
resolve(),
commonjs()
]
}
You might notice that our rollup.config.js file is missing the entry and output files configuration. This is because we are going to set them, using our Gulp file.
The Gulp file default task, is to run our Rollup bundler, through every component in our library and parse it to ES5 Javascript with CJS module specifiers. This is to enable us to import our component using non ESM supporting systems such as node.js
Setting Gulp tasks
Create a file name “gulpfile.js” and add the following code.
const gulp = require('gulp');
const shell = require('gulp-shell');
const watch = require('gulp-watch');const globs = ['src/**/*.js', '!src/**/*.test.js'];
const shellCmd = ["rollup <%= file.path %> --file <%= file.path.replace('src','lib') %> -f cjs -c -m"];gulp.task('build', () => {
return gulp
.src(globs, { read: false })
.pipe(shell(shellCmd));
});gulp.task('watch', ['build'], () => {
return gulp.src(globs)
.pipe(watch(globs))
.pipe(shell(shellCmd));
});gulp.task('default', ['build']);
We have two main tasks
- ‘build’ to run over all the components and parse them.
- ‘watch’ to parse only changed files.
Now you could add a demo app, to test your library. For this is I use the ‘create-react-app’ (As said before, I don’t like to write my own configs 😄)
Link your project
In the library: yarn link
In the app: yarn link 'your library package name'
Notice that link doesn’t add the library to your app’s package.json. so remember to do that yourself relative to your app (Thanks ShayCes).
Last thing to do, publish your library to NPM npm publish
Finally, I’d like to thank my two awesome friends, Shay Cojocaru and Yury Michurin for looking at my code and telling me, where I messed up (And I did)
You can check my demo project on Github.
I hope this was helpful to you.