Front-end Engineering Practice-Monorepo and Lerna Management

In front-end engineering practice, Monorepo (single warehouse) management and Lerna are two popular methods for organizing and versioning large projects or component libraries.
Introduction to Monorepo
Monorepo (single warehouse) refers to a development method that manages multiple related projects in a Git warehouse. The advantages of this method are:
Centralized management: All projects are in one warehouse, which facilitates code sharing, version synchronization and collaborative development. Modularity: Independent modules can be created for easy reuse and maintenance. Unified CI/CD: One-time configuration, full warehouse effectiveness, simplifying continuous integration and deployment processes. Better dependency management: It is easier to manage dependencies between projects.
Introduction to Lerna
Lerna is a command-line tool for managing multi-package projects in Monorepo. It provides version management and publishing functions, making it easy to manage multiple npm packages in a single warehouse.
The core concepts of Lerna are:
Packages: Independent npm packages in Monorepo.
Versions: Each package can have its own version, which can be fixed or shared.
Bootstrapping: Initialize all package dependencies to ensure that each package works properly.
Publishing: Publish packages to npm, either one by one or in batches.
Install Lerna
First, make sure Node.js and npm are installed. Then, install Lerna in the project root directory:
npm install --save-dev lerna
# 或
yarn add --dev lerna
Initialize the Lerna project
Run the following command in the project root directory to initialize Lerna:
npx lerna init
This will create a lerna.json configuration file and a packages directory to store the packages.
Creating and managing packages
Create a new package in the packages directory:
mkdir packages/my-package
cd packages/my-package
npm init -y
# OR
yarn init -y
Write code inside the package, such as index.js and package.json.
Using Lerna commands
Bootstrap: Initializes all package dependencies.
npx lerna bootstrap
Add:Add dependencies between packages.
npx lerna add @scope/my-package
Publish:Publish the package to npm.
npx lerna publish
List:View the packages in the project.
npx lerna ls
Lerna configuration
In lerna.json, you can configure Lerna's behavior, for example:
{
"version": "independent",
"packages": ["packages/*"],
"command": {
"publish": {
"ignore": ["**/node_modules/**"]
}
}
}
version: specifies the version strategy, which can be fixed (all packages share the same version number) or independent (each package has its own version number).packages: specifies the directory path containing the package.command.publish.ignore: files or directories to ignore when publishing.
Performance Optimization
Independent Version: Using the independent version strategy, you can publish each package separately to avoid unnecessary publishing.
Selective Publishing: Use the --since or --scope parameters to publish only changed packages.
Workspaces: Use with Yarn Workspaces to reduce installation time and disk space usage.
Advanced Features of Lerna
Asynchronous Operations and Locking
Lerna supports asynchronous operations, which is very useful when working with large projects. Setting the concurrency property in lerna.json can limit the number of concurrently executed tasks to prevent excessive resource consumption.
{
"concurrency": 4
}
Lerna also uses npm's package-lock.json or yarn.lock file to ensure dependency consistency every time it is installed. When lerna bootstrap is executed, it installs dependencies according to the locked versions in the file, ensuring that all developers use the same dependency versions when building locally.
Custom scripts
Lerna allows you to define custom scripts in lerna.json to perform specific tasks in your project. For example, create a pre-release script:
{
"scripts": {
"prepublishOnly": "tsc"
}
}
This will run the TypeScript compiler before publishing the package.
Workflow integration
Lerna can be integrated with common CI/CD tools (such as Jenkins, CircleCI, GitHub Actions, etc.) to achieve automated testing, building, and publishing. In .gitlab-ci.yml, .travis.yml, or other CI configuration files, configure the corresponding Lerna commands.
For example, in GitHub Actions:
name: CI
on:
push:
branches: [ main ]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: npm ci
- name: Bootstrap Lerna
run: npm run bootstrap
- name: Run Tests
run: npm test
- name: Publish
if: startsWith(github.ref, 'refs/tags')
run: npx lerna publish from-git --yes
Best Practices for Monorepo
Clear module division: Ensure that each package has clear boundaries and purposes to avoid excessive coupling.
Version strategy: Choose a fixed or independent version strategy based on project requirements.
Reasonable dependency management: Avoid circular dependencies and reasonably control public dependencies.
Documentation and instructions: Provide clear README and API documentation for each package to facilitate other developers.
Continuous integration: Integrate automated testing, code quality inspection, and build process.
Code review: Ensure code quality and follow team specifications.
Regular cleanup: Regularly evaluate and delete packages that are no longer used.
Other Monorepo management tools
In addition to Lerna, there are other tools that can be used for Monorepo management, each with its own characteristics and applicable scenarios:
Yarn Workspaces
Yarn's Workspaces feature is built directly into the package manager without the need for additional command line tools. It allows multiple dependencies to be managed in one repository and automatically resolves cross-package dependencies. Workspaces is suitable for projects that mainly use Yarn as a package manager.
Rush (Pika)
Rush is a monorepo management tool developed by Microsoft that focuses on speed and scalability. Rush uses a custom dependency resolution algorithm and supports multiple projects and multiple package types, including TypeScript, JavaScript, C++, etc. Rush also provides a wealth of command-line tools and configuration options.
Nx ( Nrwl.io)
Nx is an open source monorepo management tool that was originally designed for Angular projects, but now supports multiple frameworks and technologies, such as React, Vue, Node.js, etc. Nx provides a full set of workflow tools, including code generation, testing, performance analysis, and parallel builds. It also supports micro-frontend architecture.
Challenges of Monorepo
While Monorepo has many advantages, there are also some challenges:
Version conflicts: In large projects, managing different versions of packages can become complicated.
Build time: As the size of the project grows, the time to build and test can increase significantly.
Learning curve: New members may need more time to familiarize themselves with the structure and workflow of Monorepo.
Dependency management: Solving cross-package dependencies and avoiding circular dependencies may require extra attention.
Choose Monorepo or Polyrepo?
Choosing Monorepo or Polyrepo (multiple repositories) depends on project requirements, team size, and preference. Monorepo is suitable for large projects that need to share code and components frequently, while Polyrepo is suitable for small projects or components that need to be developed and released independently.
When making a decision, you should consider the following factors:
Code sharing: If there is a lot of shared code between projects, Monorepo may be a better choice.
Team collaboration: If the team needs to work closely together, Monorepo can simplify collaborative development.
Build time: If the project is large, Monorepo may result in long build times.
Project independence: If the projects are independent of each other, Polyrepo may be more suitable.





