A Simple Guide To Setting Up A React Boilerplate With Testing

--

We all face this challenge every time, when we try to start a project from scratch — determining how to set it up properly so that everything works. In my current workplace, we use mostly AngularJS, but when I decided to go with React for one of our widget developments, we all had a few questions that popped into our minds, like what to include and what to leave out, what should the building environment be, how to test the code etc.

The answer to all these are not the same for every project you may encounter in life. But thanks to React and other tools that have been released over the past few years, it has become way easier for us to set up a React boilerplate in no time!

I know what you are thinking — why would I try to make something on my own when there is create-react-app cli or even comprehensive starter kits? I will give you few points to think about:

  1. When we rely on something without understanding properly (since these cli options actually take care of everything you need and maybe more), there comes a time when your project gets bigger and for example even a simple change in the build process will make your life a nightmare
  2. Most of the time, the generated scaffolds are bloated and there are lots of things you don’t need in the first place — if you are like me, you just love to add a module or library on demand, not because it might get used at some point
  3. These scaffolds use a lot of configurations to make things work, you might end up in a situation where you want to do something customized in your way, but then again it is so complicated to do so that you give up

Last but not least, the way we will be setting up our scaffold should not take more than 30 mins but will have everything we need, and maybe will need, until the project gets way too big. Even in that situation, you will see how simple it is to plug in some library or make whatever tweaks you want and get things working. I always love to set things up this way, where I have full control and I know every bit of the settings that were involved to get the project up and running. If you are more of a person who loves to use readymade scaffolds, then just go ahead and grab the scaffolded project we will be creating here. I promise, the scaffold itself is super simple and smaller than the ones I have mentioned, that you can literally get the gist even if you just look at the code.

I hope I have convinced you enough, so let’s get started without any further delay.

Whenever I start a project, the first thing I decide on is the structure. How you define your module boundaries is very important, since this is the practice you will keep up throughout the project development time. A good or a bad structure starts proving its points as soon as your project starts to grow. So, without any further ado, let’s look at how we are planning to organize our project today.

|-- src
|-- components
|-- main (the component that's responsible for view switching based on route)
|-- main.jsx
|-- another.component
|-- component.jsx
|-- _component.scss
|-- _components.scss (all the .scss partials defined in different components are referenced here)
|-- views
|-- home.jsx (or can be a directory of a view)
|-- another.view
|-- another.view.jsx
|-- _another.view.scss
|-- _views.scss (all the .scss partials defined in different views are referenced here)
|-- index.scss (refers _components.scss, _views.scss and any other .scss partials)
|-- index.jsx (the entry point where the app renders the main component and which eventually renders the views
based on selected route)

This is the initial structure I have in mind while I am creating the boilerplate for my project — we can modify it to fit our needs. The goal is to give a clear picture of the thought process behind this.

There will be other obvious and necessary files outside the src directory, but we will get into them one-by-one since all of them will have an important role!

Setting Up the Project

package.json

The first thing we need is package.json inside our project directory. And for managing our node modules, I prefer to use yarn because it’s faster, but you can use npm too, if you wish. You can follow instructions to set yarn up.

If you have set up yarn already, then let’s say our project is a simple-boilerplate and let’s do the following-

mkdir simple-boilerplate && cd simple-boilerplate && yarn init

This will prompt you with several simple questions like project name, version etc. Just complete all the steps and at the end we will have a package.json with all the information we just provided to create the simple-boilerplate directory.

Next, let us install the dependencies:

yarn add jquery react react-dom @fortawesome/fontawesome-free-webfonts bootstrap popper.js
  1. If in our components we ever need to manipulate a dom node directly(which we will so frequently), we will find jquery very handy in such situations
  2. I hope you know why we installed react
  3. react-dom is for rendering react components into the dom tree
  4. Including fontawesome for free icon fonts
  5. bootstrap for out of the box elements and styling to utilize; popper.js is just a bootstrap dependency that we had to include(it’s used by features like positioning a tooltip, popover or even a dropdown in viewport)

Done? Good job! We need to install some dependencies that will only be used for development. So yeah, the dev dependencies:

yarn add babel-cli babel-loader babel-preset-env babel-preset-react css-loader file-loader node-sass sass-loader style-loader url-loader webpack webpack-cli webpack-dev-server — dev

We will use Babel for transpiling ES6 code into ES5, so we have installed Babel and the presets that it will need for React specific code. Webpack will be our building and bundling tool, so we use its necessary bits relevant to our project. Lastly, we also included webpack-dev-server to test out our app in localhost.

webpack.config.js

As mentioned before, we will be using webpack for bundling our modules and making our app production-ready. Webpack also simplifies the development by letting you use ES6 export and import to maintain your modules. To know more, check out their thorough documentation.

To get started, we need to create the config file for webpack inside the project directory:

touch webpack.config.js

Once created, copy and paste following lines of code:

This configuration tells webpack to do a few things for us:

  1. Use a Babel loader to transpile any .js or .jsx code into ES5 syntax.
  2. Use sass-loader, style-loader and css-loader to take care of compilation of SCSS into CSS and CSS imports.
  3. Use file-loader and url-loader to load icon fonts provided by font awesome.
  4. Finally, create a bare-bone configuration for tiny webpack-dev-server which will come super handy when we do the development and test it out in the browser.

main.jsx

We will now create the src folder and create the index.jsx, that we have already specified in webpack.config.js:

mkdir src && cd src && touch index.jsx

We will also need a component that controls the view switching based on its current route path. Let’s say it’s called the main component:

mkdir -p components/main && cd components/main && touch main.jsx

Now, add the following lines of code in main.jsx:

The usage of the Main component is straightforward. We just need to pass an array of view objects, which are simple Javascript objects with 2 properties — a relative path (for example: /home) and the class of a component that it should render when we hit that path.

To make it more understandable, let’s just create our first view component.

Let’s type this in terminal:

mkdir -p src/views/home

This will create a “views” directory under src and create a “home” directory inside “views”. Inside “home”, we create the home.jsx file with the following code in it:

At this point, we need our index.jsx to be defined in order to glue these 2 components together and give an idea of how they should be used.

The index.jsx file will look like this:

Let’s take a deep breath and pause for a second.

So, what is happening here? This is the entry point for webpack. The first thing we did was importing font awesome style files and the bootstrap javascript. The amazing part is webpack will find them from their path and bundle them into the distributable we are going to create. That will get bundled into a file called vendor.js. All the other code that we have written and imported will be bundled into a separate file called bundle.js.

We also import index.scss, which is the entry for all the .scss partials we define here and inside our app. We will have a deeper look at it shortly.

The next part imports a few important parts from React and React Dom and we’ll use them in later parts of the code to make home components visible when we hit the proper url.

Now, that index.jsx is in place, we need one more file to make our life meaningful! An index.html which will use all this amazingness we have created so far.

index.scss

Ah, wait, index.html is obviously the next important bit; but we have already talked about index.scss and so it needs a bit of introduction, too! For now, this file resides inside src and contains the following line of code:

@import “~bootstrap/scss/bootstrap”;

Yeah, you guessed it right! We are importing all the bootstrap styling to our app, which means by default we can use the elements straight out of it!

index.html

We have made quite a lot of progress, and within the next few lines we should be able to run our first react setup that we started from scratch. Be ready to be surprised! Our super lean, simple but mighty index.html has only the following lines of code:

You are surprised a bit? Yes, of course, you should be!

These bundle.js and vendor.js are the files which I explained a while ago!

Couple of things to notice here. First of all, this line is where the all the magic starts to happen-

<div id=”app”></div>

If you remember, in our index.jsx, we actually told ReactDom.render method to render our App component into a dom node that is identified by the id app! Here’s the code for your reference:

render(
<Router><App/></Router>,
document.getElementById(‘app’)
);

Secondly, there is an order to how we included the js source files and the div with id app. If, instead of the way it is now, you rewrite the code like this:

<script src=”vendor.js”></script>
<script src=”bundle.js”></script>
<div id=”app”></div>

Nothing would have worked! Why? The opposite order(i.e. loading the js files after the div) actually ensures that all the code we have written so far and all the vendor files(e.g. react, react-dom) are loaded only after there’s already a div defined with the id app. So, when we told ReactDom.render to actually render our component into a dom node with id app, it found the node by simply doing

document.getElementById(‘app’)

Running the Project

To get our project up and running we need to add the following in our package.json file:

These commands will allow us to compile and build our project and also serve it in localhost using the webpack-dev-server.

Back to index.html

Still remember those bundle.js and vendor.js references that we included in the index.html? If you run yarn build, a dist folder will be generated and it will have those two files! It will contain some other files too — mostly the font files from font awesome to make them available when you serve the project. Our index.html file needs only these two files to render every component and views that our app will have going forward!

Wait a second, did you really run the yarn build already? If you did, you have seen it has been breaking and not generating the files we mentioned just now. That brings us to the last piece of the puzzle!

.babelrc

The reason why build is failing is because we included Babel and told webpack to use it to transpile ES6 codes into ES5, but we never let Babel know HOW it should do it. Let’s create a file .babelrc in our project directory(outside src directory). This only includes the list of presets Babel should be utilizing during transpilation.

{
“presets”: [“env”, “react”]
}

Once we have that, Babel knows which presets it should use for the process. If we run yarn build again, it should work just fine!

Check in Browser

Awesome! We have done a great job by gluing all the broken pieces together, and now it’s time to see how our solution looks! Just hit yarn start in terminal and it should open up our web app in a browser! Good job! You deserve a pat on your back!

Testing

Well done! The scaffold is ready and now you can go ahead and keep building your React app!

But to make it production ready, we are still missing an important piece. We need to add support to test the code we have written so far and whatever we will be writing going forward.

Fortunately, in this phase where we don’t have state management libraries like mobx or redux or any http queries happening using fetch or axios, writing tests for the React components will be an easier problem to solve.

Installing the Dependencies & Setup

We will use jest as our testing framework. It’s like all of Karma, Mocha, Chai and Sinon in one place. If you have used them(I am assuming this is not the first time you are writing tests for your project), you will find jest super handy since it needs almost 0 configuration and has everything like assertion library, stubbing features and test runner. In addition, we will be using this utility library from AirBnB called enzyme. It’s very lightweight and mostly created for doing jquery-like dom queries on react elements, which is an essential part in most of the tests you will ever write for your react components.

yarn add enzyme enzyme-adapter-react-16 jest babel-jest — dev

For enzyme to work with our current React version, which is 16+, we need a file named setup.enzyme.js to exist inside our project directory:

Let’s also include the following lines of codes in package.json-

Finally, let’s include the test command in the scripts object of package.json-

Writing the First Test

Alright, looks like we have done everything we can, and now it’s time to write some tests to actually see if our testing setup is working properly. Let’s create a file home.test.js inside src/views/home:

Any file that ends with .test.js will be picked up by jest.

Let’s type “yarn test” in terminal and happily discover our test has been passed!

What’s Next

This scaffold doesn’t have any state management library included(e.g. Redux/Mobx). Using one is as simple as installing it using yarn and then writing the pieces of code that will do the magic. In my next post, I hope to discuss about using Mobx and Redux in a React project using this same scaffold- so I think that will make this scaffold complete with everything you might need for a bigger and scalable project. Let me know how soon I should be writing it, in the comments section below.

Final Notes

Wow! It has been a long time since we started, and great to see that you have made with me this far! Congratulations!

If you have followed along, you must have a working setup for a React project and you can take things further. You can find the whole project in github - https://github.com/dibosh/simple-react-template and use the boilerplate directly from there (don’t forget to hit the star if you found it useful).

Let me know what you think about this boilerplate in the comments section below and suggest any topics that you would like to see posts about.

The author: Munim Dibosh is a Full Stack Software Developer with 5+ years of experience in Software Development & Practices. He is also a designer in practice and loves to craft beautiful experiences. The thing he loves about being full stack engineer most is the ability to contribute on design and development equally and helping in making better product decisions.

He has profound experience in writing apps using React and related technologies. He can be contacted via email at abdulmunim.buet@gmail.com or you can check his website to know more about his projects and works — www.munimdibosh.me

Ready for your next career endeavor?
Join
Pramp.com to practice live coding interviews for free!

--

--