The Copy Paste Guide for Creating NPM packages in ES6 with Babel and Webpack
ES6 is lovely, right?
I believe “Yes” it is! However, ES6 is not quite ready yet. Present JavaScript environments (NODE and Browser ) cannot run all the ES6 proposed features. Browser vendors are slowly shipping the features to their JS engines. Hence, as of today, only ES5 is guaranteed to work seamlessly in every JS environment.
So, how can we write ES6 ?
Luckily, we have transpilers. They allow us to transpile ( a term for compiling from a language to the same language but a different version ) ES6 code to ES5. In this post, we’ll see how to write a cross platform ( UMD ) module in ES6 and compile to ES5 using webpack
and babel
.
Let’s Start
In a nutshell, our project includes:
- Webpack is a code bundling tool and will use for building our module.
- Babel-loader for transpiling ES6 code to ES5
- Babel plugins and presets:
- babel-preset-es2015
- babel-preset-stage-0
- babel-plugin-add-module-exports
- Ava for unit testing our module
- NPM scripts for the build, test and pre-publish tasks.
Let’s start by creating a new directory for our project. In the terminal, navigate to the directory and run npm init
. Follow the instructions to generate a valid package.json
file.
Time to install the dependencies for the module. Run the following command to install the packages from npm:
Create the following files and folder structure:
- index.js ( This will be our main ES6 source file )
- webpack.config.js ( The configurations required for webpack to build our module )
- .babelrc ( babel configuration file )
dist
directory ( Final compiled package goes here )
Let’s start with the webpack configuration. Open webpack.config.js
in your favorite editor. Copy and paste the below code:
This is a simple configuration file required by webpack. The exported configuration file will be processed by webpack. Let’s look at each item in the exported object:
entry
is the main file from where webpack will look for all other dependencies.- We set target=‘node’, so webpack knows how to mock/load the default node packages like “fs”, “url” ..etc
- Output section contains information about our final package and configurations related to it. We set our
libraryTarget
to UMD so that webpack will generate the final module in UMD format ( universal module definition — for commonJS, requireJS, and browser ) - Module is the section where we can configure different loaders for our code. Since we write the code in ES6, we need webpack to use
babel-loader
to transform the file. Module can have different other options for configuring the module, however, we just need only the loader configuration for now.
Babel requires plugins to complete its job properly. For that, update the babel configurations in .babelrc
file.
Here we specify the moduleId to the final name of the module. We need to add the presets option to ["es2015", "stage-0"]
in order to transform the ES6 code. Find more about es-2015
and stage-0
features here
Babel 6 does not generate a default export inside the compiled file. Instead, the default export is exported as a property called default
. Because of this, if we try require('myModule')
, it doesn’t work. Babel 6 export should be required using require('myModule').default
.
That’s why we use a plugin called add-module-exports
. Its duty is to add the default export in the final babel generated output. You can find more about it here.
Note: Make sure the moduleId
in .babelrc is matching with your module’s name.
Set up the tests
I find ava
would be the best option for unit testing our module. Let’s create a tests
directory and add a new file build.spec.js
. A basic test case is give below:
Now make the tests pass by implementing the real code in the module.
More about ava
here.
Set up the NPM scripts to do the tasks
We need 5 npm tasks to make our life easier. All of them are self-explanatory; Just have look at the code in package.json
.
- npm start: To run in development mode. This task will watch for any source file changes and output the build.
- npm run build: Build the final module in production mode ( minified and with source maps ).
- npm test: Run the
ava
tests. - npm run test-w: Run tests in continuous watch mode.
- npm prepublish: Before publishing the package, this task run the
build
andtest
to make sure everything works fine.
Final scripts will look like this:
For developing in TDD fashion, run npm start
and npm run test-w
together.
Make the dist/build.js
as the main file for the module
Finally, we need to tell npm about where to load the module from. Edit the package.json
and change the “main” property to dist/build.js
Summary
Developers already adopted ES6 even before it’s available. Thanks to all these tools and the people behind them.
Today we learnt the minimal set-up to start writing code in ES6. You can find the repo for the seed project here. Fork, and create your next npm package in ES6.
I hope you enjoyed reading the article. Feedbacks are welcome!