marp | theme | size | auto-scaling | title |
---|---|---|---|---|
true |
gaia |
58140 |
code |
Monorepos |
- Lerna
- What does a monorepo look like?
- Lerna Commands
- Lerna with NPM
- Lerna with Yarn
- Yarn Workspaces
- Lerna with Yarn Workspaces
- GitHub Packages
-
Splitting up large codebases into separate independently versioned packages is useful for code sharing.
-
Tracking changes and testing accross repositories becomes difficult very quickly.
-
Organize your codebases into multi-package repositories also known as monorepos.
-
Lerna helps you optimize to manage multi-package repositories !
./my-monorepo
│
│ README.md
│ package.json
│
-───packages
│
-────package-1
│ │ README.md
│ │ package.json
│ │ ...
-────package-2
│ │ README.md
│ │ package.json
│ │ ...
-────package-3
│ README.md
│ package.json
│ ...
- lerna init
- lerna bootstrap
- lerna run
- lerna exec
- lerna add
- lerna version
- lerna publish
- lerna clean
- lerna info
Install Lerna for access to the CLI. Creates a new Lerna repo or upgrades an existing repo to the current version of Lerna
$ lerna init
-
Lerna will be added as a
devDependency
inpackage.json
. -
Creates a
lerna.json
config file to store the version number. -
By default Lerna projects operate on a single line version. The version is kept in the
lerna.json
file at the root of your project under theversion
key. -
Independent mode allows you to increment package versions independently of each other. Each time you publish, you will get a prompt for each package that has changed to specify if it's a patch, minor or major change.
# Independent mode $ lerna init --independent
Bootstraps the packages in the current repo.
$ lerna bootstrap
-
Installs all of the dependencies and links any cross-dependencies. It will symlink together all packages that are dependencies of each other.
-
Runs the
prepublish
andprepare
scripts in all bootstrapped packages. -
The
prepublish
script is deprecated and has been replaced with theprepare
script. The NPM CLI runs theprepublish
script for bothnpm publish
andnpm install
. -
Use
prepublishOnly
script to only run a script beforenpm publish
. -
Use the
--hoist
flag to install dependencies at the repo root. Binaries from these dependencies are linked into the dependent packagenode_modules/.bin
directory.$ lerna bootstrap [glob]
Run a script in each package that contains that script.
$ lerna run <script> -- [..args]
-
For example, running the unit tests for each package.
$ lerna run test
-
Stream the output from the child processes immediately, prefixed with the package name.
$ lerna run test --stream
-
Can also be run in parallel.
$ lerna run test --stream --parallel
Run a command in each package.
$ lerna exec -- <command> [...args]
-
For example, for cleaning each package folder.
$ lerna exec -- rm -rf ./coverage ./dist ./node_modules junit.xml
-
Scoped packages are supported.
$ lerna exec --scope @geersch/logging -- rm -rf ./node_modules
-
Can also be run in parallel.
$ lerna exec --parallel -- rm -rf ./node_modules
Add a package as a dependency to packages in the current repo.
$ lerna add <package>[@version] [--dev] [--exact] [--peer]
For example:
$ lerna add lodash
$ lerna add lodash --scope @geersch/logging
-
Adding a development dependency.
$ lerna add debug --dev $ lerna add debug --dev --scope @geersch/logging
-
Adding a peer dependency.
$ lerna add lodash --peer $ lerna add lodash --peer --scope @geersch/logging
Identifies the packages that have been updated and will prompt for a new version.
$ lerna version
By default it commits the changes, tags the commit and pushes to the remote.
-
Use
--no-git-tag-version
if you don't want it to create a commit.$ lerna version --no-git-tag-version
-
You can also pass a semver level and the
--yes
flag to skip the selection prompt$ lerna version [major | minor | patch | premajor | preminor | prepatch | ...] --yes
-
If you use the
--conventional-commits
flag, then it will use the Conventional Commits specification to determine the version bump and generateCHANGELOG.md
files.$ lerna version --conventional-commits
Identifies the packages have been updated and publishes them.
$ lerna publish
Calls lerna version
and publishes the packages updated since the last release.
-
Use
from-git
to publish packages tagged in the current commit.$ lerna publish from-git
-
Use
from-package
to inspect eachpackage.json
file and publish if the package version is not present in the registry. Handy if a previouslerna publish
failed to publish all the packages.$ lerna publish from-package
Remove the node_modules
directory from all packages.
$ lerna clean
-
I prefer
lerna exec
to clean each package folder.Just put the following
purge
script in thepackage.json
file at the root of your project.{ "purge": "lerna exec --parallel -- rm -rf ./node_modules ./coverage ./dist junit.xml" }
-
Or use
lerna run
and provide a script per package.$ lerna run clean $ lerna run --scope @geersch/logging clean
Prints local environment information that can be useful for submitting bug reports.
$ lerna info
Environment info:
System:
OS: macOS 10.15.6
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Binaries:
Node: 12.16.1 - ~/.nvm/versions/node/v12.16.1/bin/node
Yarn: 1.22.5 - ~/.nvm/versions/node/v12.16.1/bin/yarn
npm: 6.14.8 - ~/.nvm/versions/node/v12.16.1/bin/npm
Utilities:
Git: 2.24.3 - /usr/bin/git
npmPackages:
lerna: ^3.22.1 => 3.22.1
git clone https://github.com/geersch/lerna.git
git checkout master
By default Lerna uses NPM as the client to run commands with.
$ mkdir lerna
$ cd lerna
$ npx lerna init
$ npm install
{
"packages": [
"packages/*"
],
"version": "independent",
"command": {
"publish": {
"registry": "https://npm.pkg.github.com"
}
}
}
{
"name": "root",
"version": "1.0.0",
"description": "A monorepo example using Lerna.",
"private": true,
"scripts": {
"postinstall": "lerna bootstrap",
},
"devDependencies": { ... }
}
After installing the packages (npm install
) the postinstall
script will run lerna bootstrap
which bootstraps the packages in the current Lerna repo. It will symlink together all Lerna packages
that are dependencies of each other
{
"name": "root",
"version": "1.0.0",
"description": "A monorepo example using Lerna.",
"private": true,
"scripts": {
"postinstall": "lerna bootstrap --hoist",
},
"devDependencies": { ... }
}
- Multiple packages often have duplicate dependencies in their
package.json
files. - Lerna can reduce duplicate packages by hoisting the dependencies up to the root (topmost Lerna-project level
node_modules
directory). - Use
lerna bootstrap --hoist
in thepostinstall
script to bootstrap the package after installing them vianpm install
.
git clone https://github.com/geersch/lerna.git
git checkout lerna-with-yarn
Use Yarn as the NPM client.
-
Install Yarn.
$ npm install -g yarn
-
Specify Yarn as the NPM client in
lerna.json
.{ "npmClient": "yarn", "packages": ["packages/*"], "version": "independent", }
-
Run
yarn import
to generate ayarn.lock
from an NPMpackage-lock.json
file. -
Remove the
node_modules
folder andpackage-lock.json
files in the root and package folders. -
Run
lerna bootstrap
in thepostinstall
script to bootstrap the packages.{ "postinstall": "lerna bootstrap" }
-
Run
yarn
from the root to install the packages and bootstrap the packages.
git clone https://github.com/geersch/lerna.git
git checkout yarn-workspaces
Use Yarn Workspaces for handling the dependencies.
-
Install Yarn.
$ npm install -g yarn
-
Run
yarn import
to generate ayarn.lock
from an NPMpackage-lock.json
file. -
Remove the
node_modules
folder andpackage-lock.json
files in the root and package folders. -
Yarn Workspaces needs to be defined in the root
package.json
.{ "workspaces": ["packages/*"] }
-
Remove the
Lerna
package and thelerna.json
configuration.$ yarn remove lerna $ rm -rf lerna.json
-
Remove the scripts that use Lerna in the root
package.json
file. -
Run
yarn
from the root to install the packages. -
Use
yarn workspaces run
to run scripts in each workspace.
git clone https://github.com/geersch/lerna.git
git checkout lerna-with-yarn-workspaces
Use Yarn Workspaces for handling the dependencies and use Lerna to run commands for the packages and to publish them.
-
Install Yarn.
$ npm install -g yarn
-
Specify Yarn as the NPM client in
lerna.json
and setuseWorkspaces
totrue
to let Yarn manage the dependencies.{ "npmClient": "yarn", "useWorkspaces": true, "packages": ["packages/*"], "version": "independent", }
-
Yarn Workspaces needs to be defined in the root
package.json
.{ "workspaces": ["packages/*"] }
-
Run
yarn import
to generate ayarn.lock
from an NPMpackage-lock.json
file. -
Remove the
node_modules
folder andpackage-lock.json
files in the root and package folders. -
Don't run
lerna bootstrap
. Remove thepostinstall
script. -
Run
yarn
from the root to install the packages.
Let's publish the packages.
-
Step 1: Set the
name
andpublishConfig
options in your package'spackage.json
.{ "name": "@geersch/calculator", "publishConfig": { "registry": "https://npm.pkg.github.com/" } }
-
Step 2: Authenticate
$ yarn login --registry=https://npm.pkg.github.com/
-
Step 3: Publish
$ yarn publish