Making The Case For Frontend Monorepos

... or, an evolutionary approach to building web frontends

Harrison Harnisch

Build Stuff @ Buffer

What is a monorepo?

contains more than one logical project

most likely unrelated, loosely connected or can be connected by other means

What Is A Frontend Monorepo?

contains code, tooling, configuration and utilities required to render a frontend application

loosely connected or can be connected by other means

Multirepo !== Monorepo

Two Different Approaches To Frontend Monorepos

Integrated

vs.

Modular

.
├── App
│   ├── index.html
│   ├── style.css
│   └── index.js
├── Utils
├── Tools
└── package.json

Integrated

"Don't Overthink It" Approach

Easy To Get Started

This is very desirable, especially when trying to launch a product

Gets Tangled With Changes

This is OK since we'll probably end up rewriting it a few times

.
├── packages
│   ├── components
│   │   └── package.json
│   ├── sidebar
│   │   └── package.json
│   ├── ...
│   │   └── package.json
│   └── utils
│       └── package.json
└── package.json

Modular

"Package Driven Development"

A workflow centralized around building loosely coupled packages

Bounded Complexity

Packages work like packing cubes

Packages Are Easier To Rewrite Than Applications

More Opportunities To Work In Parallel

Managing Lots Of Dependent Packages Is Hard

But There Are Tools To Help!

Why Break Things Into Packages?

Lets talk about Unix philosophy

Write programs that do one thing and do it well

Write programs to work together

UNIX Philosophy 

1978

The UNIX Dev Envoronment Was State Of The Art

But it wasn't easy enough to share work

System Package Manager

1988

1994

IRIX - inst

Debian - dpkg

Application Package Manager

1995

2000

 2004

2009

Perl - CPAN

Python - PyPi

Ruby - RubyGems

JS - npm

Source: Google Ngram

Unix Philosophy 1980-2006

System Package Manager

App Package Manager

Source: Google Ngram

Package Manager 1980-2006

In many ways Unix Philosophy drove the desire for package managers

Packages are more useful when you share them

Similarly, the modular approach is most effective if you can share work

Monorepos In Practice

Integrated→Modular

Idea

MVP

Get something in customers hands

Iterate

(Buffer was in this phase for over 6 years)

New Ideas

Migrate MVP

Build New Products

+

Integrated→Modular

Migrate MVP

Phase 1: Build In Existing Package

.
├── packages
│   ├── ...
│   │   └── package.json
│   └── frontend
│       ├── **sidebar.js**
│       ├── index.js
│       └── package.json
└── package.json

Phase 2: Local Package

.
├── packages
│   ├── ...
│   │   └── package.json
│   ├── **sidebar**
│   │   ├── **index.js**
│   │   ├── **reducer.js**
│   │   └── **package.json**
│   └── frontend
│       ├── index.js
│       └── package.json
└── package.json

Phase 3 (optional): Move Package To External Respsitory

It's OK for features to stay in phase 1 or 2

Migration can be done at your own pace

Idea

MVP

Iterate

New Product Idea(s)

Migrate MVP

+

Build New Products

Integrated

Modular

Dependency Management

Tooling!

Lerna

Yarn - Workspaces

Package Communication

Optimizing for loose coupleing

Packages alone will not stop code from getting tangled

Mediator Pattern

Redux

Recap

There are excellent tools to help manage dependencies

Packages alone will not keep code from getting tangled

Integrated and Modular approaches are both useful

Thank You!