A basic monorepo managed with Lerna and Yarn workspaces. Inspired by this Medium post by David Barral, and theoretically extensible to other projects. This repo is a work in progress, but the eventual goal is to create a scalable, framework-agnostic template for monorepos.
For those unfamiliar with Lerna, modular components are referred to as packages.
At the moment, the project is comprised of:
- client - React, Webpack
- server - Express, Winston server
- tools - Shared tooling/configurations
- hub - A
package.json
listing the other packages as dependencies - scripts Shell and npm scripts (and sym-links) for CI/CD
All shared tooling and configurations are contained in packages/tools
.
At the moment, this includes settings for:
- Babel v7 (Stage 2, React)
- ESLint v5 (Airbnb and Prettier)
- Jest v23
- Prettier v1
npm i -g lerna
Yarn - follow the installation instructions for your OS here. Make sure yarn workspaces are enabled!
yarn config set workspaces-experimental true
Have Lerna install dependencies and link the various packages to one another.
lerna bootstrap
After the packages have finished installing, you can selectively run different parts of the project.
Runs all package.json scripts with the name dev
From the project root directory:
yarn run dev
From anywhere in the project:
lerna run dev --parallel --no-bail
From the project root directory:
yarn run client:dev
From anywhere in the project:
lerna run client:dev --no-bail
lerna add <dependency_name> --scope <package_name>
To make webpack a shared dependency, add webpack to packages/tools
:
lerna add webpack --scope tools
packages/tools/package.json
would now look something like this:
// packages/tools/package.json
"name": "tools",
"version": "1.0.0",
"dependencies": {
"webpack": "^4.24.0",
}
Write "tools": "1.0.0"
as a dependency wherever a project needs it:
// packages/client/package.json
"dependencies": {
"tools": "1.0.0"
}
Run lerna link
to link the packages together.
Shared configurations are defined in packages/tools/
// packages/tools/eslint.config.js
module.exports = {
"extends": ["airbnb", "prettier"],
"plugins": ["prettier"],
"rules": {
"prettier/prettier": ["error"],
}
}
They can then be imported into any other package like so:
// packages/client/eslint.config.js
module.exports = require('tools/eslint.config.js');
├── .editorconfig
├── .gitignore
├── lerna.json
├── package.json
├── packages
│ ├── client
│ │ ├── babel.config.js
│ │ ├── .browserslistrc
│ │ ├── dist
│ │ │ ├── index.html
│ │ ├── eslint.config.js
│ │ ├── jest.config.js
│ │ ├── package.json
│ │ ├── prettier.config.js
│ │ ├── src
│ │ │ └── index.jsx
│ │ ├── task -> ../../scripts/task
│ │ └── webpack.config.js
│ ├── hub
│ │ ├── package.json
│ │ └── task -> ../../scripts/task
│ ├── server
│ │ ├── babel.config.js
│ │ ├── eslint.config.js
│ │ ├── jest.config.js
│ │ ├── package.json
│ │ ├── prettier.config.js
│ │ ├── src
│ │ │ ├── index.js
│ │ │ └── server.js
│ │ └── task -> ../../scripts/task
│ └── tools
│ ├── babel.config.js
│ ├── eslint.config.js
│ ├── jest.config.js
│ ├── package.json
│ ├── prettier.config.js
│ └── task -> ../../scripts/task
├── README.md
├── scripts
│ ├── publish
│ └── task
└── yarn.lock
- Charles Hufnagel - chufnagel
This project is licensed under the GPLv3 - see the LICENSE.md file for more details.
- Credit to David Barral for the original Medium post!