An Opinionated Web Application Solution: Part 1
Starting series by examining several foundational choices that inform many of my other opinions.

TL;DR: The core constituent tools of this (front-end) web application solution include: React, TypeScript, webpack, Jest, Redux, and Immutable.
Having extensively explored and written on web application technologies, I have formed an opinion on what the best overall (front-end) web application solution is today. Thought to share it and the underlying rationale.
note: This series is not a tutorial on any particular constituent library, but rather a higher level discussion about the rationale of using them in the context of an overall web application solution.
My approach to writing this article was to first build an example (scaffold) project that both illustrates this opinion and forms the outline for this series.
The project’s software requirement are Node.js (used v8.9.4 but the latest v8.X.X LTS should be fine too) and Yarn. By the way, I considered switching back to the Node.js built-in npm command from using the Yarn library as the project’s package manager; the problem was that I had already gotten used to Yarn. The following commands are available from the project’s root folder.
- yarn install: Use first to install project’s dependencies
- yarn start: Start development mode; live linting, build, and browser reloading (only files in bundle)
- yarn build: Lint and build production files in dist folder (only files in bundle)
- yarn lint: Run linter (check all files)
- yarn tsc: Run compiler (check all files)
- yarn test: Run tests
- yarn coverage: Run tests and coverage report
- yarn analyze: Runs bundle analyzer
React
While the React library is not the first technology that one encounters in the example project, it is the linchpin choice that informs many other of my opinions.
I often find people confusing React with its companion libraries, e.g, webpack, or the underlying programming language, e.g, ES2015. Rather, React itself is a relatively simple library designed to declaratively map the DOM to JavaScript structures.
Will not spend much time explaining my rationale for using React; rather it can be summarized as:
I was drawn to React for its simplicity, JavaScript forward approach, and declarative style. I stayed with it because of its stability and community.
— me
TypeScript
With the ability to transpile source code to browser friendly JavaScript ES5 being common today, there are a number of programming languages one can use to build web applications.
Up until recently, I took a conservative approach that I would start with JavaScript ES2015, the idiomatic language for React projects, and minimally sprinkle in extra language goodies as I needed them. The rationale is that I did not want to find myself writing in a language with little community support.
More recently I sprinkled (more like a dash) in static typing with Flow; a seemingly obvious static typing choice as it is supported by Facebook (also supports React). But why static typing in the first place?
CODE FASTER.
Tired of having to run your code to find bugs? Flow identifies problems as you code. Stop wasting your time guessing and checking.CODE SMARTER.
It’s hard to build smart tools for dynamic languages like JavaScript. Flow understands your code and makes its knowledge available, enabling other smart tools to be built on top of Flow.CODE CONFIDENTLY.
Making major changes to large codebases can be scary. Flow helps you refactor safely, so you can focus on the changes you want to make, and stop worrying about what you might break.CODE BIGGER.
Working in a codebase with lots of developers can make it difficult to keep your master branch working. Flow can help prevent bad rebases. Flow can help protect your carefully designed library from your coworkers. And Flow can help you understand the code you wrote six months ago.
— Facebook Open Source — Flow: A Static Type Checker for JavaScript
I, however, bumped into a couple of pain points with Flow:
- In general, using static typing is a big change from writing dynamically typed JavaScript. I found it challenging to work with.
- Being a relatively new and less used library, I found relatively few articles on it.
- As many third-party libraries do not ship with Flow type definitions, you have to rely on a community managed repository of them. These individual type definitions are not distributed as npm packages; you need to independently download and manage the version of these files.
- Often the errors reported by Flow are cryptic:
[flow] exact type: object type (This type is incompatible with the expected return type of union: type application of polymorphic type: type `React$StatelessFunctionalComponent` | class type: type application of polymorphic type: class type: React$Component Member 1: type application of polymorphic type: type `React$StatelessFunctionalComponent` Error: inconsistent use of library definitions object type This type is incompatible with object type Member 2: class type: type application of polymorphic type: class type: React$Component Error: inconsistent use of library definitions object type This type is incompatible with class type: type application of polymorphic type: class type: React$Component)
Prompted by these pain points, I very recently (last month or so) explored using the TypeScript programming language.
- It is a strict superset of JavaScript; it does not include any conflicting language syntax.
- It adds static typing as its core feature; feels more natural than how Flow syntax is bolted on.
- It has broad community support across the larger JavaScript community, e.g., it is idiomatic to Angular. As such, I found many articles on TypeScript. Microsoft in partnership with Google backs TypeScript.
- For those third-party libraries that do not ship with TypeScript type definitions, most have community managed versions distributed as npm packages.
- Finally, I found the errors reported by TypeScript to be more helpful.
TS2322: Type '{ counter: number; increment: () => void; }' is not assignable to type 'IntrinsicAttributes & CounterProps'.Type '{ counter: number; increment: () => void; }' is not assignable to type 'CounterProps'.Property 'decrement' is missing in type '{ counter: number; increment: () => void; }'.
Bottom line, making the switch to TypeScript was a big leap. But having worked through the details over the last several weeks, I am convinced that is is the right choice.
webpack
The webpack library is the idiomatic build tool for React projects; as such no further rationale for webpack is needed. webpack configuration preferences, on the other hand, is highly complex and the basis of many of the following sections.
As a reminder, webpack and similar build tools are principally designed to allow you, the developer, to create projects with a large number of small manageable files (JavaScript/TypeScript, CSS, media, etc) and assemble them into a small number of larger files suitable for web distribution.
One general opinion is to use webpack scaffolding tools, like create-react-app, when learning React and for hobby projects. Spend the time to learn and configure webpack yourself for production projects. The rationale:
- Because of the complexity of the problem they solve, build tools (including webpack) are highly configurable and thus complicated. Not a good place for beginners.
- Much of webpack’s complexity derives from the thriving ecosystem of supporting third-party libraries. Inevitably, you will find libraries you want to use but create-react-app does not support.
Some will say that you can use create-react-app and later use its eject feature when you need the ability to directly configure webpack. Others use react-app-rewired to tweak create-react-app’s webpack configuration. In either case, I personally found it easier to simply learn and configure webpack directly.
Next Steps
In the next article in the series, An Opinionated Web Application Solution: Part 2, we will explore several webpack configuration preferences.
✉️ Subscribe to CodeBurst’s once-weekly Email Blast, 🐦 Follow CodeBurst on Twitter, view 🗺️ The 2018 Web Developer Roadmap, and 🕸️ Learn Full Stack Web Development.