Environmental requirements
- yarn v1.x
- Node. Js > = v10.12.0
- lerna 3.x
What is Monorepo?
Monorepo is a method of managing the source code of multiple projects in the same repository. The opposite of Monorepo is Multirepo, whose idea is to divide warehouses into modules. There are many popular open source projects using monorepo to manage code, such as Babel and Vue3.0.
The pros and cons of Monorepo
Advantages:
- Code reuse is easier;
- Streamlined dependency management, removing repeated dependencies of multiple packages;
- Convenient large-scale refactoring, can simultaneously refactor multiple packages and unified release, avoid different package management problems;
- It’s easier to work across teams. When you work across teams, you can work together by simply submitting code instead of publishing to a package manager.
- Unified management of Lint, Test, build, and Release;
- Unified place to deal with issues;
- This facilitates the unified generation of ChangeLog.
Disadvantages:
- Loss of version information. Monorepo, which releases a single version, will lose the version information of each project, although it is possible to release a separate version.
- Lack of package-specific access control (Git), where developers must be given access to the entire repository if they want to access a project, which may be a security issue.
- More hardware consumption: When you only need to develop a project, you have to download the entire repository code, which takes up more network and local storage space.
How to implement Monorepo?
The mainstream solution is to use Yarn Workspaces + LERna.
yarn workspaces
Yarn workspaces can integrate node_modules of multiple packages into one. You only need to run Yarn install to install all package dependencies.
Here’s an example:
root/
workspace-a/
package.json
workspace-b/
package.json
node_modules/
package.json
Copy the code
Workspaces are declared in the root package.json file:
{
"private": true."workspaces": ["workspace-a"."workspace-b"]}Copy the code
Note that adding private: true prevents the workspace root directory from being published to NPM. Workspaces are an array containing the paths of all “workspaces”. Wildcards such as “workspaces”: [“packages/*”] are also supported.
Package. json for workspace-a and workspace B are as follows:
workspace-a/package.json:
{
"name": "workspace-a"."version": "1.0.0"."dependencies": {
"cross-env": "5.0.5"}}Copy the code
workspace-b/package.json:
{
"name": "workspace-b"."version": "1.0.0"."dependencies": {
"cross-env": "5.0.5"."workspace-a": "1.0.0"}}Copy the code
Finally, run yarn install in the root directory to install all dependencies. After the installation, a directory structure similar to the following is displayed:
/package.json
/yarn.lock
/node_modules
/node_modules/cross-env
/node_modules/workspace-a -> /workspace-a
/workspace-a/package.json
/workspace-b/package.json
Copy the code
Workspace -b relies on workspace-a and will refer directly to files within the current project, rather than from NPM. There will be no node_modules/, but node_modules in the root directory.
lerna
A tool for managing JavaScript projects with multiple packages. A tool for managing JS projects with multiple packages.
Above is lerNA’s official introduction. Lerna is used to manage multiple packages, optimize the workflow of maintaining multiple packages, and solve the problem of multiple packages being interdependent and published. It is currently used by many well-known open source projects, such as Babel, create-React-app, mint-UI, and React-Router.
The structure of a LERNA project is roughly as follows:
lerna-repo/
packages/
package-1/
package.json
package-2/
package.json
package.json
lerna.json
Copy the code
The packages/ directory holds all packages. Lerna. json is its configuration file, described later.
How does Lerna work
Lerna management package has two modes: fixed and Independent.
Fixed/Locked Mode This is the default mode. All packages in Fixed mode share a version number. This version number is stored in the version field of lerna.json. So when you run lerna Publish, the modified packages are automatically updated with the version in package.json and published to NPM, while the unmodified packages are not updated. Another issue worth noting is that when the lerna.json version changes the major version number, all packages are updated and released.
Note: If you have a major version number of 0, all changes will be considered breaking, which means a big change that is not backward compatible, which will result in all package versions being updated.
Independent mode Lerna init — Independent is used to initialize a project in Independent mode. You can also manually change the version in lerna.
Independent mode allows each package to update its own version number, so when you run Lerna Publish, you need to select the version of each package that has changed.
Lerna Common commands
lerna init
Create a new lerNA repository or update an existing repository to a new version of LERNA, where the independent/-i option is used to generate independent mode projects.
lerna bootstrap
This command does several things:
- NPM install installs dependencies for all packages.
- Create soft links for packages that depend on each other.
- In all bootstrap packages (not included
command.bootstrap.ignore
Package ignored in)npm run prepublish
(If an argument is passed--ignore-prepublish
This step will be skipped). - In all bootstrap packages (not included
command.bootstrap.ignore
Package ignored in)npm run prepare
.
lerna publish
Publish all modified packages, prompt to select a new version, and update all changes to Git and NPM.
lerna run [script]
Execute specific NPM scripts in all packages.
lerna ls
Lists all public packages in the current repository. Packages that are private: true are not listed.
lerna.json
The content of lerna.json is roughly as follows
{
"version": 1.1.3 ""."npmClient": "npm"."command": {
"publish": {
"ignoreChanges": ["ignored-file"."*.md"]."message": "chore(release): publish"."registry": "https://npm.pkg.github.com"
},
"bootstrap": {
"ignore": "component-*"."npmClientArgs": ["--no-package-lock"]}},"packages": ["packages/*"]}Copy the code
version
: The version of the current repository.npmClient
: NPM client. The default value is NPM and the optional value is yarn.command.publish.ignoreChanges
: is an array. Changes to files in this array do not trigger version updates.command.publish.message
: Custom Git commit information when a new version is released.command.publish.registry
: Sets the private repository, which is published to by defaultnpmjs.org
.command.bootstrap.ignore
: Directories set here will not participatelerna bootstrap
.command.bootstrap.npmClientArgs
: performlerna bootstrap
Will pass all the values of the array as argumentsnpm install
.command.bootstrap.scope
: limiting thelerna bootstrap
In which packages it works.packages
: specifies the path of all packages.
The project practice
Set up
Open Yarn Workspaces:
yarn config set workspaces-experimental true
Copy the code
Create a project:
mkdir lerna-demo && cd lerna-demo
yarn init
Copy the code
Install lerNA globally:
npm install --global lerna
Copy the code
Lerna initialization:
lerna init
Copy the code
The following files are generated in the current directory:
lerna-demo/
packages/
package.json
lerna.json
Copy the code
Configure lerna.json in the root directory to use the YARN client and use workspaces:
/ / lerna. Json {" packages ": [" packages / *"], "version" : "0.0.0",+ "npmClient": "yarn",
+ "useWorkspaces": true
}
Copy the code
Package. json set private to true to prevent the root directory from being published to NPM, and also set workspaces:
// package.json
{
"name": "lerna-demo",
+ "private": true,
+ "workspaces": [
+ "packages/*"
+]
}
Copy the code
The new package
New packages need to be created under packages/ :
cd packages
mkdir wdm-lerna-demo-core && cd wdm-lerna-demo-core
Copy the code
Use yarn to initialize:
yarn init
Copy the code
The initial version of the new package should be 0.0.0, since it is updated with LERNA, and will be added on top of that when released.
Similarly, create the wdm-lerna-demo-ui package, and the final directory structure is roughly as follows:
lerna-demo/
packages/
wdm-lerna-demo-core/
package.json
wdm-lerna-demo-ui/
package.json
package.json
lerna.json
Copy the code
Installing common dependencies
If it is all inclusive dependencies, it can be installed like this:
lerna add lodash
Copy the code
Add the dependencies to the dependencies directory in the dependencies directory. Add the dependencies to the dependencies directory in the dependencies directory.
yarn add eslint --dev -W
Copy the code
The -w option explicitly indicates that the yarn operation is performed in the root directory of the workspace, avoiding misoperation of yarn in the root directory.
Install local package dependencies
In this example we set the UI to depend on core:
lerna add wdm-lerna-demo-core --scope=wdm-lerna-demo-ui
Copy the code
Wdm-lerna-demo-ui adds new dependencies:
// package.json
{
"name": "wdm-lerna-demo-ui"."version": "1.0.0"."main": "index.js"."license": "MIT"."dependencies": {
"wdm-lerna-demo-core": "^ 1.0.0"}}Copy the code
Then you can use core in your UI:
import myCore from 'wdm-lerna-demo-core'
Copy the code
This is done via a soft link to the wdm-lerna-demo-core/ directory, rather than using a package downloaded from NPM. So, changes in core can be reflected in the UI in real time.
Remove reliance on
If you want to remove a common package that all packages depend on, do this:
lerna exec -- yarn remove lodash
# lerna exec -- yarn remove lodash -- netword-timeout =1000000 # Use this command if a message is displayed indicating that there is a network problem
Copy the code
Lerna exec —
[..args] indicates that the command is executed in all packages.
Published to the NPM
First check to see if you are logged in to NPM:
# Print out the user name to indicate that you are logged in
npm whoami
Copy the code
If you have not logged in, run the following command as prompted:
npm login
Copy the code
After login, you can publish:
lerna publish
Copy the code
Here lerna Publish does a few things:
- Gives you a choice of how to update the version, whether it’s major, minor or beta.
- Update the version to the changed package
package.json
的version
. - If some packages depend on the newly updated package, it will be updated automatically
dependencies
Version number of. - Commit your changes to Git and generate a Git commit and tag with the version number.
- Publish the changed and public package to NPM.
So far, a LERNA project has been set up. See Lerna-demo for the source code.