Custom Boilerplate

Recently, I took on a mini-project to create my own boilerplate that I intend to use for my future front-end projects. Check out the repo for this project here!

Motivation

Thus far when making web applications, I used Create React App to instantiate my project. For those who are not familiar, this is a super simple tool to initialize a react application in a single command. Their website boasts that you can get started immediately!

get-started-immediately

Create React App was incredibly useful for me when I first started web development. I highly recommend it if you are new to React or web development. Without it, I would have struggled to set up all the necessary configuration while just starting to learn React. It’s also a big time saver which can be useful if you’re like me - making numerous small applications as I’m learning how to program.

This solution worked for me until my last project. I felt like the things Create React App was doing “under the hood” were only complicating the process. As I started to peel apart the layers and read the documentation more deeply, I often found myself with more questions than answers.

pull-a-part-car

Some of the disadvantages I noticed include:

I found it difficult to confirm exactly what the provided scripts are executing.

When it came time to deploy my last project, I started to dive deeper into customizing scripts to set up a development environment, test the application, and build the application. As complexity grew, so did my need for customization. I began to have questions around what the react-scripts commands were doing behind the scenes. For example, when you run the provided command react-scripts build, what exactly does it do? Does it delete the previous build files for you? The documentation didn’t break down exactly what happens when running this command, so dove into the source code to answer my questions.

Customizing webpack and other configurations is difficult

As the complexity of your application increases, it’s possible you may need to customize your set up. Since the various configuration files are not exposed through Create React App, it becomes difficult to figure out how to customize these things for yourself. What configurations are already in place? How can I change existing properties or add new ones?

Bloat

If you’ve seen any tutorial on CRA, the second step usually provided after initializing your application is deleting all the unnecessary files created by default! CRA installs numerous packages that you may never need, thus increasing the size of your application and potentially creating unnecessary confusion.

Also, it takes a long time to run the command to create an application (9 seconds on average for me). Cloning an existing git repo is practically instantaneous!

Customization

There are a few additional steps I take to initialize a new project. I update the tsconfig to contain stricter settings. I initialize an eslint config file for linting. It would be nice if I could clone these config files from an existing source with my preferred defaults, rather than remembering which lines to change for each new project.

Setting Up A Custom Boilerplate

Before I started creating my own boilerplate, I looked for existing examples that I could utilize. I discovered most boilerplates included too many assumptions. Often certain libraries were already installed or the configurations went beyond what I considered sane defaults.

Objective

I decided my goal was to create a repo I could reuse for any Typescript-React project without making further assumptions about the application.

I felt the acceptable minimum required to start development ASAP included:

  • Installing the required types and packages for Typescript and React
  • Transpiling TypeScript to JavaScript
  • Transpiling JavaScript for the browser
  • Using a source-map to get proper reference points from the browser console to your application files
  • Including types in the configuration files to ease future customizations and throw proper errors before runtime
  • Setting up linting with some of my preferred defaults
  • Ability to create a development server with live reloading
  • Establishing scripts to begin development

Initial Set Up

First, I initialized the set up with some of the required files:

  • Created a package.json
  • Created a public folder with an index.html file containing a standard head and body
    • Added a div with an id=root in the body to leverage for attaching the React components
  • Created a src folder containing the React components and an index.tsx
    • Created a React component called App.tsx
    • Imported react-dom and the App component in the index file to attach the component to the root element
  • Initialized a tsconfig with my preferred defaults
  • Initialized a .gitignore to prevent adding my node_modules and the dist folder containing bundled files

ESLint

Next, I created an ESLint config with some generic defaults.

I had hoped to use TypeScript for consistency and assistance with auto-complete when writing the configuration. Unfortunately, after a diving down the rabbit-hole of GitHub issues, I discovered that ESLint doesn’t support TypeScript files for their configuration.

I extended the recommended linting, included plugins for react, react hooks (to enforce best practices) and typescript.

Webpack

I used Webpack to accomplish 4 primary goals:

  • Transpiling TypeScript to JavaScript
  • Transpiling JavaScript to an earlier version for browser compatibility
  • Running a development server with immediate reloading without refreshing
  • Bundling the application

Learning how to configure webpack was the main reason I took on this mini-project. To date, I hadn’t taken the time to break down and understand what each property was responsible for. My initial intention was to summarize everything you need to know here, but taking some time to read the amazing tutorials that webpack provides is worth it. They are concise and easy to read, while giving some context to understand why certain settings are necessary. It took some trial and error for me to figure out exactly what each property of the configuration is responsible for and how they work together.

Here are links to the guides I used and a few key takeaways that I learned along the way. Note that this is for Webpack 5.

  • Webpack 5 accepts configuration files written in TypeScript
  • Start with the Getting Started guide
  • Follow the Output Management guide to set up the output folder names
    • HTML files are not included in the bundling process by default. In order to include them, you need to configure the HtmlWebpackPlugin. This injects the script tag in the index.html file instead of needing to do this manually.
  • Follow the guide on how to work with TypeScript
    • They recommend transpiling your code with ts-loader as it preforms type checking. No need to use babel with this approach!
  • Follow the development guide to set up a development server
    • Some resources I read recommend installing extra source-map plugins, but that isn’t necessary. You can enable source maps by adding devtool: 'inline-source-map' in your webpack config and "sourceMap": true in your tsconfig.
    • Set up hot reloading by adding hot: true as a property of devServer
  • Read the Asset Management guide if you need to bundle other files that are not JavaScript or TypeScript (like CSS or images)

Conclusion

I highly recommend creating your own boilerplate. It took me about a day to familiarize myself with the documentation enough to put this together. It was immensely helpful for me to gain a deeper understanding of webpack.

Once I started understanding this process more deeply, I was able to dive into Create React App’s source code to answer some of my questions. I ended up discovering they are using much of the same process under the hood, which was incredibly useful to realize. Sometimes things are more simple than you would think!

Next on my to-do list: creating a repo with a full-stack version!

GitHub Repo