exile.watch engineering
  • exile.watch engineering blog
  • April 2024
    • Why doesn't Dependabot update package.json?
  • March 2024
    • The savior amidst the chaos of dependency updates - Dependabot
    • Why project's local setup instructions are not part of README?
    • Leveraging Lefthook to enforce commit guidelines at exile.watch
    • The package manager of exile.watch
    • Lerna - the hidden powerhouse of exile.watch
      • 1. Separate repository and monorepo tool
      • 2. A module bundler - the fun begins
      • 3. Module registry (a place where packages get to chill)
      • 4. Versioning, Publishing, and Configuring lerna.json for Commit Conventions
      • 5. Some automation magic using the (Lerna) CLI
      • 6. How does one test lerna packages at exile.watch: locally and in the real world
    • To open source or to not open source
    • exile.watch architecture
Powered by GitBook
On this page
  • Why React? Why Next.js? Why not Vue or Angular or x, y, z?
  • I have the framework, now what's the structure?
  • Where did the idea of modularity come from?
  • Lerna?
  • Sweet - I have the concept mapped in mind, but where do I begin?
  • With great modularity comes great responsibility
  • So... is this approach beneficial?
  • Pros
  • Cons

Was this helpful?

  1. March 2024

exile.watch architecture

10 min read

PreviousTo open source or to not open source

Last updated 1 year ago

Was this helpful?

... all managed by .

Wait, wait, wait... How many repositories and packages are there again?

For... one user-facing website? Surely there must be some micro-frontends because otherwise, this seems like a completely overengineered solution.

You read it correctly. This modularity is by design. But is this approach beneficial?

Let's dive in.


I’ve been sticking with React for a good while now (7 years and counting), and honestly, it just fits like a glove for what I need to do. Picking it was pretty much a no-brainer for me.

At the time, Next.js offered the server-side rendering capabilities with the least developer experience friction.


I have the framework, now what's the structure?

// simplified structure of exile.watch in 2021
.
├ components
│ ├ ComponentA
│ │ └ ComponentA.tsx
│ ├ ComponentB
│ │ └ ComponentB.tsx
│ └ index.ts
├ hooks
│ └ useHook.ts
├ pages
│ ├ encounters.tsx
│ └ index.tsx
├ tsconfig.json
└ package.json

The development of exile.watch was on full throttle.

I lost all interest in the game, and consequently, my motivation to continue with exile.watch diminished.


Where did the idea of modularity come from?

This is what sparked my comeback to exile.watch after a three-years hiatus, given the "dependency mess" I had left behind and the breakdown to smaller projects and packages.

I decided to use exile.watch as my own sandbox for learning.

Lerna is a fast, modern build system for managing and publishing multiple JavaScript/TypeScript packages from the same repository.


Sweet - I have the concept mapped in mind, but where do I begin?

So, I've got React, Next.js, Lerna... components, hooks, some dependencies... Some dependencies.

29 dependencies, 49 devDependencies. That's... A LOT.

{
    "dependencies": {
    "@reduxjs/toolkit": "^1.5.1",
    "@sentry/browser": "^6.4.1",
    "@sentry/integrations": "^6.4.1",
    "@sentry/node": "^6.4.1",
    "@sentry/react": "^6.4.1",
    "@sentry/tracing": "^6.4.1",
    "@sentry/webpack-plugin": "^1.15.1",
    "@svgr/webpack": "^5.5.0",
    "classnames": "^2.3.1",
    "cookie-parser": "^1.4.5",
    "downshift": "^6.1.3",
    "express": "^4.17.1",
    "framer-motion": "^4.1.17",
    "is-hotkey": "^0.2.0",
    "lodash": "^4.17.21",
    "next": "^10.2.2",
    "pako": "^2.0.3",
    "react": "17.0.2",
    "react-cookie": "^4.0.3",
    "react-dom": "17.0.2",
    "react-hook-form": "^7.6.5",
    "react-redux": "^7.2.4",
    "react-xml-parser": "^1.1.8",
    "sass": "^1.34.0",
    "slate": "^0.63.0",
    "slate-history": "^0.62.0",
    "slate-react": "^0.63.0",
    "xml2ts": "^0.6.1",
    "xmltojson": "^1.3.5"
  },
  "devDependencies": {
    "@babel/core": "^7.14.3",
    "@commitlint/cli": "^12.1.4",
    "@commitlint/config-conventional": "^12.1.4",
    "@mdx-js/react": "^1.6.22",
    "@storybook/addon-actions": "^6.2.9",
    "@storybook/addon-docs": "^6.2.9",
    "@storybook/addon-essentials": "^6.2.9",
    "@storybook/addon-links": "^6.2.9",
    "@storybook/preset-scss": "^1.0.3",
    "@storybook/react": "^6.2.9",
    "@storybook/theming": "^6.2.9",
    "@svgr/cli": "^5.5.0",
    "@types/is-hotkey": "^0.1.2",
    "@types/js-yaml": "^4.0.1",
    "@types/lodash": "^4.14.168",
    "@types/node": "^14.17.0",
    "@types/pako": "^1.0.1",
    "@types/react": "^17.0.6",
    "@types/react-redux": "^7.1.16",
    "@types/xmltojson": "^0.0.28",
    "@typescript-eslint/eslint-plugin": "^4.24.0",
    "@typescript-eslint/parser": "^4.24.0",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^8.2.2",
    "commitizen": "^4.2.4",
    "css-loader": "^5.2.5",
    "cz-conventional-changelog": "^3.3.0",
    "date-fns": "^2.21.3",
    "eslint": "^7.27.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-config-react-app": "^6.0.0",
    "eslint-plugin-flowtype": "^5.7.2",
    "eslint-plugin-import": "^2.23.3",
    "eslint-plugin-jsx-a11y": "^6.4.1",
    "eslint-plugin-prettier": "^3.4.0",
    "eslint-plugin-react": "^7.23.2",
    "eslint-plugin-react-hooks": "^4.2.0",
    "eslint-plugin-simple-import-sort": "^7.0.0",
    "fork-ts-checker-webpack-plugin": "^6.2.10",
    "fs": "^0.0.1-security",
    "js-yaml": "^4.1.0",
    "lint-staged": "^11.0.0",
    "prettier": "^2.3.0",
    "sass-loader": "^10",
    "style-loader": "^2.0.0",
    "ts-loader": "^9.2.2",
    "ts-node": "^9.1.1",
    "tsconfig-paths-webpack-plugin": "^3.5.1",
    "typescript": "^4.2.4"
  }
}

I have waaay more devDependencies than dependencies, so let's address this first.

And planning to swap out Storybook for @exile-watch/storybook-config, shedding another 7 packages in the process.

Seeing the pattern yet?

Same story with the dependencies.

With great modularity comes great responsibility

And here I am, two weeks after diving back into the project.

7 repositories, 10+ packages, 1 chrome extension and 1 user facing website.

But... how do you even keep track of all this?

For now, just know Dependabot is like that reliable buddy doing all the heavy lifting for you—keeping everything updated without you breaking a sweat.

So... is this approach beneficial?

Let's wrap this up with some pros and cons based on what I've been through.

Pros

  • Everything's modularized: Each Lerna monorepo, package, and consumer app knows its lane, focusing sharply on its defined scope

  • Jump-starting new projects is a breeze since everything’s pre-configured, letting other team members hit the ground running with feature development

  • Unified updates mean when something changes, it hits the whole org at once—keeping everyone on the same wavelength

  • Frequent rotations? Easy. Moving between projects is smooth since you’re always familiar with the setup

  • The development approach is opinionated, guiding the team with clear rules to follow

Cons

  • Thinking of kicking off a new project? This architecture might feel like swatting a fly with a sledgehammer—total overkill unless you’re in it for the learning curve.

    • Got a couple of frontend teams already? Great! This might be time to think about bringing things together with a centralized solution

  • Resource drain alert: Getting all this up and running eats up time and people—usually needing a dedicated person or a small squad focused on R&D and pushing engineering productivity to new heights

  • Update fatigue is real. Without Dependabot finely tuned, your team might get bogged down with constant updates, shifting focus from feature delivery to keeping up with the latest package versions


No. There are no micro-frontends. In fact, the .

Why ? Why ? Why not or or x, y, z?

Does React have ? Sure, as do other tools. However, I won't be delving into those here.

Given the project's needs, was a significant consideration. exile.watch was initiated in 2021, and while I don't recall if SEO was a strong selling point for React at that time, I do remember that Next.js was particularly effective at satisfying SEO crawlers.

I'm a big fan of the for its clean and concise approach to project structure. This is my goal whenever I start a new React/Next.js project, and that's exactly what I aimed for with exile.watch in 2021.

However, with the introduction of the in the ...

End of January 2024 enters the chat. Being let go from the company I developed an itch to learn Lerna.

During my time at the company, we extensively levereged Lerna. I was part of the team, and over time we created a stellar frontend architecture that I will always aim to achieve, as long as resources (people and time) will allow.

?

let you develop multiple packages in the same repository, which is fantastic for productivity. You can share code, establish clear ownership, and have fast unified CI.

To use monorepos well, you need a good monorepo tool, and Lerna is exactly that. Lerna is , widely used, and battle tested.

Given what are all about, it made sense to kick things off by tackling the build tools. This meant setting up my first Lerna monorepo to manage just that.

First up, creating to ditch 10 TypeScript-related packages.

Next, swapping out individual code quality tools for , which axed another 11 packages.

Initially, I didn't lean on any UI library, which meant my themes and icons were kinda all over the place. That sparked the creation of , our Lerna monorepo design system, housing and packages.

PS:

Simple answer: .

I wrote a separate post about Dependabot .

You can see it in action.

Still on the fence? Remember what I said about sticking to for simplicity’s sake

Author: About exile.watch: Github: Visit to experience it first hand

user-facing website doesn't even have ten pages
React
Next.js
Vue
Angular
flaws
SEO (Search Engine Optimization)
Bulletproof React repository
Expedition league
Path of Exile game
due to bankruptcy
Engineering Productivity
Lerna
Monorepos
fast
devDependencies
@exile-watch/typescript-config
@exile-watch/biome-config
@exile-watch/writ
@exile-watch/writ-react
@exile-watch/writ-icons
Here is the current list of dependencies for comparison
Dependabot group updates
here
here
Bulletproof React
Sebastian Krzyżanowski
https://docs.exile.watch/
https://github.com/exile-watch
https://exile.watch/
Seven repositories, over ten packages, one Chrome extension, and one user-facing website
one person
exile.watch.logo
Comparison chart of React, Vue.js and Angular
List of group pull requests opened by Dependabot