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
babelas our transpiler - We want to test our app via
Mocha, and usingChaito make the assertion - We will use
Enzymeto 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,yesmeans default answer to all questions, speed up the procedure.- It will generate a
package.jsonat the root of your project folder.
- It will generate a
- Secondly, Install React dependencies by
npm install --save react react-dom--savemeansreactandreact-domare our dependencies. Our application needs them to run. And they’ll appear in thedependenciessection 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-reactbabel-cliis a built-in CLI which can be used to compile files from the command line.babel-preset-envis 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 asjsxandflow.js.
- Create a
.babelrcfile at the root of your folder, you can include it in thepackage.jsonas well if you prefer fewer files at your root.--save-devmeans we need these libs when we develop, but not for the production. And they’ll appear in thedevDependenciessection 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-loaderis a loader that webpack will use to deal with.jsfiles.webpack-dev-serveris a local server for running your web app
- Add a
scriptssection 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.jsat 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
rulesto deal with different files,.jsxis our current focus. - And we want to enable
source-mapas a developing tool. - Finally, we want a
devServerwhich use the configuration we want.
6.Check if React works.
Create 3 files:
app.jsin thesrcfolder: This is the entry of our project.
1 | import React from "react"; |
HelloComponent.jsin thesrcfolder: This is our hello world ES6 component.
1 | import React from "react"; |
index.htmlin thedistfolder.
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-registeris a plugin forMochato use on the fly to transpile your ES6 test filesreact-test-rendereris a plugin forReact 15.5.+, since there is a breaking changing here, you need this plugin forenzymeto 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
.babelrcfile to enable this plugin:
1 | { |
- Modify your
src/app.jsto 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.