From Zero to Hero: building a React Application from scratch

A talk about choices and technical debt

Gian Marco Toso

@gianmarcotoso

gianmarcotoso

gianmarcotoso.com

polarityb.it

Software Engineer, The Pirate I Was Meant To Be

🎩 About Me 🎩

Born and raised in Turin, Italy

@gianmarcotoso

gianmarcotoso

gianmarcotoso.com

polarityb.it

MSc in Computer Engineering 

Self Employed Consultant and Software Engineer

JavaScript and PHP Developer

🍔 About My Stack 🍔

Docker

PHP/Laravel

"It was working on my machine!"

The monolith is here to stay

NodeJS/TypeScript

Seriously, it's awesome!

React + Redux

The Flux Capacitor!

Getting Started

Starting a new project requires decisions

Decisions are hard

Getting Started

Problems are not solved all at once

Divide et Impera

Setting the Foundation

Presentation

State Management

Tooling

Testing

"Secondary" Concerns

Environment and Configuration

Error Handling

Logging

Styling

Accessibility

Folder Structure

Asynchronous Call Handling

Offline Capabilities

Mobile Support

Real-time Capabilities

Performance Considerations

Source Language

😱

Enter: The Boilerplate

Most developers turn to boilerplate projects

There are *a lot* of boilerplate projects

Create React App

The most popular React Starter Kit, made by Facebook

Come with most choices already made, out of the box

A powerful tool (especially for beginners)

An excellent reference for everyone

Should I use a boilerplate?

Does it have most of what I'm looking for?

Can I justify all the choices that have been made?

Could I build it myself from scratch?

Are its dependencies up to date?

Let's do it

State Management

Bundling

Testing

State Management

A State Manager is required for most real world React applications

Using a State Manager instead of managing state within React is more future proof

A State Manager helps address many concerns, such as:

Error Handling

Logging

Asynchronous Call Handling

Performance Considerations

State Management

There are many State Managers available, but you'll probably end up choosing one of these:

Redux

MobX

+ MobX State Tree

+ Middlewares

Redux

Let's choose Redux as our state manager. Which middlewares could we use?

Async Data Flow

redux-thunk / redux-saga / redux-observable

Logging

redux-logger / redux-devtools / custom middleware

Persistence

redux-persist / localforage + custom middleware

Let's do it

Tooling

Testing

State Management

Tooling

A well configured toolchain will make our app lighter and more performant

Tooling addresses many concerns, such as:

Source Language

Folder Structure

Styling

Environment and Configuration

Performance Considerations

Transpiler

We'll want to use a transpiler to convert our code from the source language to plain JS.

Babel

TypeScript

+ Presets / Plugins

Babel

When using Babel, we need to choose a preset and add plugins for features which are not yet standard

Presets

@babel/preset-env + @babel/preset-react

Plugins

@babel/transform-runtime (async-await)

@babel/plugin-proposal-class-properties (class properties)

@babel/plugin-proposal-object-rest-spread (object spread)

@babel/plugin-syntax-dynamic-import (dynamic imports)

Bundler

And of course we want a bundler to put things together

Webpack

Parcel

+ Plugins / Configuration

Webpack

We'll need to setup loaders and plugins to build things the way we want to

Loaders

babel-loader (JavaScript)

ts-loader (TypeScript)

style-loader / css-loader / sass-loader (CSS, SCSS)

file-loader / url-loader (images and assets)

Plugins

SplitChunksPlugin (chunking)

UglifyPlugin (minification)

CSS Engine

We might want to use a more featured engine for CSS, but we could also go with plain CSS or CSS-in-JS

SASS / SCSS

PostCSS

Let's do it

Tooling

Testing

State Management

Testing

Testing our code makes it more predictable, and easier to reason about.

While testing doesn't cover any secondary concern directly, it encompasses most of them.

Test Runner

We need to be able to run our tests. A test runner allows us to do just that.

Jest

Mocha

+ Chai

Testing React

Since we test React components from the CLI, we need a library to help with that.

Enzyme

React Testing Library

Configuration and Environment

Instead of creating JS files to store configuration, it's good practice to use environment variables

The dotenv node package and Webpack's DefinePlugin can be used in concert to inject the configuration inside our compiled code

// env.js
module.exports = {
    serverURL: process.env.SERVER_URL 
    logToken: process.env.LOG_TOKEN
}
// webpack.config.js
plugins: [
    new webpack.DefinePlugin({
        config: JSON.stringify(require('./env.js'))
    }),
]

Folder Structure

Choosing a folder structure for a project can be hard, and there is no solution that fits all projects

+ src/
    + app/
        + auth/
            + components/
            + connectors/
            + services/
            + sources/
            + views/
            auth.routes.jsx
    + components/
        button.component.jsx
    + core/
        app.store.js
    + resources/
    + styles/
    + utils/
    index.js
package.json
webpack.config.js       

It's usually a good idea to separate by domain

 
 

Technical Debt

React is just a UI library, the rest is up to you.

Making all this choices is hard, and every library you add will contribute to the project's overall technical debt

When adding a library, always make sure that

you really need it

it's regularly maintained

issues get resolved

(ideally) it has more than one contributor

Thank you! :)

From Zero to Hero: building a React Application from scratch

By Gian Marco Toso

From Zero to Hero: building a React Application from scratch

Slides for my talk at the 2018 WebAppConf in Torino

  • 1,705