This article has participated in the activity of “New person creation Ceremony”, and started the road of digging gold creation together.

Build monorePO using LerNA

What is monorepo?

Monorepo manages packages or projects in a Git repository

In what situations might you want to use this code management approach in real development?

  • Your team is a full-stack development oriented team that manages front-end and back-end projects in a repository
  • If you want to use microservices, either backend microservices or front-end microservices (single-SPA), you can manage multiple related projects in a repository.
  • In open source projects, project modules are managed and distributed separately, such as create-react-app

Lerna

Monorepo is a code management concept, and there are many tools to help you implement it. Here is Lerna

So what is Lerna?

The official explanation:

Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.

Lerna provides some commands to operate on multiple packages, as well as some support for project release workflows.

The lerNA V3 that we’re using here.

Initialize the project

To start with a new project or an existing project, lerna can be used to create the Monorepo development pattern

Lerna provides two ways to manage projects, one is Fixed/Locked mode (default) and the other is Independent mode

The difference is that Fixed/Locked mode version control is complete in a Repository, while Independent mode version control is Independent in each package

Here we introduce the form of Independent mode

Execute the following command to initialize lerNA

npx lerna init --independent
Copy the code

A lerna.json file is generated, which is the lerna configuration file, as follows

{
  "packages": [
    "packages/*"]."version": "independent"
}
Copy the code

There are two configurations, packages, which specify the directory in which you want to manage packages. The default configuration is the project folder in the first level directory under Packages

If you want to nest multiple layers, you can change to

{
  "packages": [
    "packages/**"]}Copy the code

If you need to add other directories, such as monorepo, you can change it to

{
  "packages": [
    "servers/*"."frontend/*"]}Copy the code

The exact directory structure depends.

If you are used to using YARN for package management, you can also define the package management tool as YARN

{
  "version": 1.1.3 ""."npmClient": "npm"."packages": ["packages/*"]}Copy the code

For a detailed lerna.json configuration, see the Readme document on Lerna Github

Perform package script

We can use the lerna run directive to run the commands associated with each package containing the associated package script.

For example, we have two front-end packages, each with a start in package.json

{
	"srcipts": {
		"start": "react-scripts start",}}Copy the code

We can just run it

lerna run --parallel start
Copy the code

The parallel parameter prints the output of all child processes for the process that needs to be in the project. It’s a little convoluted, but if you want to run all the time you just add this parameter.

Package depends on

The installation package

You can install dependencies in package.json for all packages using the following command

npx lerna bootstrap
Copy the code

The common package

We can install common packages in the root package.json directory. For example, if you are a front-end microservice project and use React as the main stack, you can install React, React-DOM, etc. in the root directory. Packages are available directly

More commonly, project-specific configurations, such as ESLint, prettier, tsconfig, etc., can also be installed directly in the root directory

The benefits of extracting public packages are:

  • All packages use the same version of the dependency package
  • Do some package upgrades and make it easier to upgrade when doing package checks like Github
  • Dependency packages can take less time to install
  • Requires less storage space

Package to package references in a project

If we need cross-references in Packages

We use lerna add to install third-party or local packages for a specified package. This directive is essentially similar to YARN add or NPM install. Here are some examples from the documentation

# Adds the module-1 package to the packages in the 'prefix-' prefixed folders lerna add module-1 packages/prefix-* # Install module-1 to module-2 lerna add module-1 --scope=module-2 # Install module-1 to module-2 in devDependencies lerna  add module-1 --scope=module-2 --dev # Install module-1 to module-2 in peerDependencies lerna add module-1 --scope=module-2 --peer # Install module-1 in all modules except module-1 lerna add module-1 # Install babel-core in all  modules lerna add babel-coreCopy the code

Version control

Lerna version control relies on the tag on the corresponding Git branch to determine the change record and version control accordingly

Lerna does not support Git flow. If git flow is followed, it is an anti-pattern, that is, a counter example.

Related issue: github.com/lerna/lerna…

Since we are using independent Mode, we need to manage the version of each package. If the project uses some CI Workflow, we also need to put version control into the CI process.

For lerna version control, use the lerna version command.

We have done several things in detail:

  1. Defines which packages have been updated since the last Git Branch release tag
  2. Updated version number
  3. Modify the packagepackage.jsonThe inside of theversion, NPM Lifecycle Scripts run in the root directory and within each update package. Commit these changes and type a Release tag
  4. Push to a remote Git Repository

Therefore, Lerna has completed the work of making release Tag and updating Changelog for us.

Finally, according to git flow, we just need to merge the release branch back to the development branch, see if hotfix release code is needed, and then merge the master/main branch to complete a release

If you need prerelease, beta, do the same for version control. Lerna Version provides parameters to do this

  • --conventional-prerelease: Current release is the prerelease version.
  • --conventional-graduate: Change the prerelease version of a package to a stable version of a package.

Management to release

Finally, if we also need to publish packages to NPM or another Registry, we need to use the lerna publish command.

Note that if you do not need to publish all packages, you can set package.json private to true in packages that do not need to publish

There are two options for the publish command

$git > publish from-package; $git > publish from-package; $git > publish from-packageCopy the code

When publish, there is an important parameter called canary. This parameter means that before publishing to NPM, create a new version of the current version, add 1 to minor, and add alpha, for example 1.0.0 will become 1.1.0-alpha). If you need to specify a suffix, you can define it using the –preid argument, for example –preid beta

conclusion

So far, we have introduced lerna how to create a simple Monorepo project, and perform script running, package installation and dependencies, version control and distribution.

I’ll leave the rest to you.