Setting up React with Babel, Mocha, Chai, Enzyme and Webpack
I’m not a big fan of black magic, especially when I set up my development environment. Every module I have installed, I want to know exactly what problem does it solve. And every feature I have used, I want to know how to customize it to suit my needs. You could use create-react-app, but I like to manage all the things by my own hands because I always have so many things which I want to tweak my way.
Now let’s set up a React environment with Tests, ES6 and bundle enabled (With HMR).
We’ll go through every step and explain why we need that module.
1.First of all, what we want?
- We want to write React via ES6, so we need to
babel
as our transpiler - We want to test our app via
Mocha
, and usingChai
to make the assertion - We will use
Enzyme
to test our React Component. - We want to use ES6 to write our test cases as well.
- We want to bundle our project via
Webpack
. - We will use the Hot Module Replacement (HMR) feature from Webpack to speed up our process.
2.Create the folder structure
1 | root |
About the sub-folders:
src
: Whole the source codes sit here.dist
: All the transpilered codes (ES5 version) sit here.tests
: Folder for test cases.
3.Install React
- Firstly, initialize a new NPM configuration there via
npm init —yes
,yes
means default answer to all questions, speed up the procedure.- It will generate a
package.json
at the root of your project folder.
- It will generate a
- Secondly, Install React dependencies by
npm install --save react react-dom
--save
meansreact
andreact-dom
are our dependencies. Our application needs them to run. And they’ll appear in thedependencies
section of yourpackage.json
4.Add ES6 support
Now we will add babel
via the following command:
npm install —save-dev babel-cli babel-preset-env babel-preset-react
babel-cli
is a built-in CLI which can be used to compile files from the command line.babel-preset-env
is a presets for determining the Babel plugins and polyfills you need based on your supported environments.babel-preset-react
: A preset for react related thing such asjsx
andflow.js
.
- Create a
.babelrc
file at the root of your folder, you can include it in thepackage.json
as well if you prefer fewer files at your root.--save-dev
means we need these libs when we develop, but not for the production. And they’ll appear in thedevDependencies
section of yourpackage.json
1 | { |
5.Add Webpack support
- Install webpack by using
npm install --save-dev webpack webpack-dev-server babel-loader babel-core
, we are ready to bundle our project.babel-loader
is a loader that webpack will use to deal with.js
files.webpack-dev-server
is a local server for running your web app
- Add a
scripts
section in yourpackage.json
:
1 | "scripts": { |
Then you can use npm run build
to bundle your project via webpack or use npm start
start your dev server.
- Add a configuration file named
webpack.config.js
at the root:
1 | var path = require("path"); |
All the settings here are self-explained via their names. the app.js
is the entry file of our project, we will add it later. Beware the structure here, should be very easy to understand:
- Our app starts at
entry
- we want the final bundle file to be in the place mentioned by the
output
. - We have some
rules
to deal with different files,.jsx
is our current focus. - And we want to enable
source-map
as a developing tool. - Finally, we want a
devServer
which use the configuration we want.
6.Check if React works.
Create 3 files:
app.js
in thesrc
folder: This is the entry of our project.
1 | import React from "react"; |
HelloComponent.js
in thesrc
folder: This is our hello world ES6 component.
1 | import React from "react"; |
index.html
in thedist
folder.
1 |
|
Run command npm start
, and open http://localhost:9876
, you will see your hello world.
Webpack dev server will build and display your app.
7.Add testing libraries
npm install --save-dev mocha chai enzyme babel-register react-test-renderer
babel-register
is a plugin forMocha
to use on the fly to transpile your ES6 test filesreact-test-renderer
is a plugin forReact 15.5.+
, since there is a breaking changing here, you need this plugin forenzyme
to run.
Create a test_Hello.js
in the tests
folder:
1 | import chai from "chai"; |
It will test if there is an h1
tag in our <Hello/>
module, it should pass.
1 | <First/> |
8.Add Hot Module Replacement support
HMR could speed up your workflow dramatically. Since it will update the changed modules on the fly without refreshing your page. Cool. It is provided by webpack
. But you need to add some code in order to enjoy it.
Firstly, add the following setting to our previous webpack.config.js
, the original settings remain the same:
1 | module.exports = { |
We are configuring entries and plugins for HMR. The whole config file is provided at the end of the article.
Secondly, add a hot loader plugin for babel via:
npm install --save react-hot-loader
- Modify the
.babelrc
file to enable this plugin:
1 | { |
- Modify your
src/app.js
to this:
1 | import React from "react"; |
The logic is mostly the same, but we will determine if the HMR setting is on, if it is on, will use module.hot.accept
to render our app. Remember we have set hot:true
previously? It will expose the module.hot
API to our code, so we could detect it via if (module.hot)
.
Thirdly, now use npm start
to start your webpack-dev-server
, if you have followed my tutorial so far, remember to stop and restart the server since we have changed its settings.
After the server has started, go changing the HelloComponent.js
file, try changing the Hello world
to Hello HMR
, look at your browser, the content will change without refresh the page. That means the states of your components will be maintained, cool!
9. Story not end.
But if you try to run the test case via npm test
, it will throw you an error:
1 | /Users/albertgao/codes/github/React.TODO/tests/test_app.js:1 |
Wait, what? Shouldn’t settle out the testing part before? Why it can’t recognize the import
keyword? The reason is we have set "presets": [["env",{"modules":false}], "react"]
to enable the HMR feature. But it will cause we can’t run our tests since we use the import
feature. How to we make tests work via ES6 while the HMR could work also? A little tricky here:
First, change your .babelrc
file to this:
1 | { |
The env
here will enable us to use the Node.js environment variables to check whether we are under the test
mode.
Then, change the test
command in your package.json
to use it:
1 | "scripts": { |
Re-run the test via npm test
, it should work again.
10. The whole webpack.config.js
1 | var path = require("path"); |
11. Happy ending.
Now everything should work as expected, and you are good to go.
Thanks for reading!
Follow me (albertgao) on twitter, if you want to hear more about my interesting ideas.