Ultimate boilerplate for React + Express with Docker
So I created yet another boilerplate with React and Express.
Here is why.
Do We Need Yet Another Boilerplate?
The answer is yes!
Let’s face it — It’s a pain to set up a React project from scratch.
Whilst learning React, I encountered so many problems just to get a hello world app running on the browser. Trying to compile and bundle the front-end felt like forever. Webpack config looked cryptic and daunting. So many babel presets to choose from… Then here comes the back-end. How should I structure the app? Do I opt for client-side or server-side rendering? Which test runner to use? What is the best way to separate development and production workflow?
The abundance of choice is overwhelming.
Although there are tons of tutorials and boilerplates out there, many of them are outdated. Few of them explains the rationale behind the decisions. It was about time I put what I learnt into practice, so we can just focus on learning and playing around with React.
It Comes With Perks
It’s ES6 compatible across the stack. A testing environment is hooked up with Jest. And it’s Docker-ready. The repository contains detailed README on how to use it.
In this post, I’m going to talk about thoughts that went into in creating the boilerplate.
Application Structure
I put a particular emphasis on simplicity and flexibility, when thinking about the app structure.
- I like having a single directory
app
at the top level to contain all the source code, which is then divided intoclient
andserver
. - I want to have my test files close to what’s being tested, as I don’t like having to mentally go up and down the file tree to
import myModule from '../../../src/server/helper/myModule’
. Therefore, instead of having a separate directory for tests at the top level, I placed a__tests__
directory each forclient
andserver
. - By default, the app makes use of server-side rendering. Hence, the
index.html
file is located within theview
directory underserver
. It can be easily switched over to client-side rendering, should you wish so.
Stress-free Workflow
I’m a big fan of a stress-free development workflow with fast feedback.
- The dev mode comes with a watch functionality. Changes made either to the client and the server are immediately detected and the app is re-bundled / re-started automatically.
- The tests are run with Jest. It comes with useful features like parallel testing, intelligent test watching (re-runs only the tests affected by changes), and coverage report.
Ease of Deployment
So you created an app on your machine. But what’s next? This question is often overlooked. I wanted to create something that’s a ready to be deployed without an additional effort.
- I created a Webpack config optimised for production, in addition to the default config for development. The size of the file bundled file in the production mode is 1kB. Now that’s 0.0005% of what’s bundled in the dev mode. Minimising the bundle size becomes essential as the application grows.
2. The app runs in Docker, so it can be deployed straight to another machine or a cloud server, without having to worry about the dependency compatibility.
Code Style
I introduced standard as a code style as well as a linter, since I almost exclusively follow this style. It has robust rules in place to allow you to use no semicolons. It favours the use of single quotes over double. I love it! The code looks so much cleaner.
Implemetation does not require configuration, which is a bonus. Just run $ npm/yarn run standard
to check for any linting error. I configured so it also runs at the end of $ npm/yarn test
. If you don’t like the style, simply remove it from the script.
Latest Packages
Finally, nothing is more frustrated than finding a good boilerplate, only to find out that packages are outdated. So I did my best to ensure that the npm packages are up-to-date. For example, I used Webpack version 3 in combination with babel-preset-react and babel-preset-env, which replaces babel-preset-2015, 2016, 2017 and latest.
Wrap up
A boilerplate, by nature, is opinionated. That doesn’t mean I think there is no better way. I want to learn different opinions as to what you think is batter and why. So please share your thoughts! I appreciate your feedback as always.
I hope you enjoy using the boilerplate. If you like it, star it and share it with your peeps :)
Thanks, and happy coding!