This document outlines the design decisions made in this project.
We made two language decisions when starting this project:
-
We decided to use JavaScript rather than TypeScript
-
We decided to use CommonJS modules rather than ES Modules
The combination of the above allows us to work on and publish the packages in this monorepo without needing a build step. This means that the code we write is exactly the same as the code run inside our applications.
In terms of TypeScript, the key benefits are having type safety and type hinting in your editor. We can achieve both of these without writing TypeScript. Using JavaScript with JSDoc comments to document types, VSCode (used by the majority of our engineers) offers the same level of type hinting as it does with TypeScript. It's also possible to run the TypeScript type checker against JavaScript code to verify that everything is type safe (e.g. using tsc --checkJS
).
In order to be useful for TypeScript projects, we do still need to publish our modules with TypeScript type declaration files (.d.ts
).
If we wanted to support ES Modules (which is the future direction I think we'll all go in) then we'd need to choose between one of the following, neither of which seems preferable to just sticking with CommonJS for now.
-
We write our code in ES Modules but we cross-compile to CommonJS before publishing. This isn't ideal because it introduces a build step and steps away from "what you see is what's running in your app"
-
We write our code in ES Modules and publish them as ES Modules with no cross-compilation. This makes them incompatible with a large number of our apps (many of them use CommonJS exclusively) and would tie adopting Reliability Kit to an unrelated migration step
A note that for now there is a small downside to sticking with CommonJS. It will continue to work for the forseeable future in Node.js itself, but more modules on npm are switching to native ESM which is not very compatible with CommonJS. We may find ourselves forced to reconsider at some point if any of our key dependencies (e.g. Express or Jest) migrate to ESM-only and drop support for their old CommonJS versions.
This repository does not use Tool Kit. This is because, at the time of writing, Tool Kit did not have full support for managing and publishing packages in a monorepo. We copied many of the scripts and the CircleCI config from Tool Kit itself so that we can manage the monorepo in the same way. This may change in future.
When testing a monorepo, running tests and linting can happen in one of two ways:
-
Have tooling installed in the top level package and run these tools against the whole repo
-
Have tooling installed in each package and have commands in the top level package to run these
We have opted to have tooling installed at the top level. This speeds up build times, because Jest and ESLint have non-trivial start up times and multiplying this by the number of packages can lead to a lot of overhead. This also means that the tooling is consistent between all of the different packages and upgrading the tooling happens in one place. There is more information on how to run tests in the contributing guide.
We decided that npm workspaces and minimal tooling would be the best supported route forward. As we're opting for testing at the top level, we have minimal need for running the same scripts across all packages. If we do want to then it's possible by adding the --workspaces
flag to any npm command.
We opted for Conventional Commits as this allows us to programatically determine package version numbers and automate a lot of the release tasks related to managing a monorepo. As none of the team at the time were in the habit of writing commits this way, we adopted commitlint in order to enforce the rules. There is more information on how to commit in the contributing guide.
We opted to use GitHub issues and a project board to track work that needs to be done on Reliability Kit. This is for several reasons:
-
The project board can easily be public to match the repo. This allows people who aren't members of the Financial-Times GitHub org to contribute. The issues and progress tracking also lives alongside the code
-
By using GitHub we don't have to manage access separately – all our engineers have access by default and anyone with a GitHub account can comment without needing to take up a license seat
-
We can more easily manage issue and PR templates to suit our needs, as well as being able to add custom fields and views on our data