Summary of the process of developing a new npm package in Monorepo
This week, I need to develop an npm package in my work to supplement other existing pacakge. The entire repository adopts the form of monorepo to record the pitfalls and new technologies learned during the whole process
Use of Lerna
The venom warehouse adopts the monorepo method
Monorepo is a different way of organizing code from multirepo. First, let’s explain what monorepo and multirepo are. Both are ways to manage and organize code. As the name suggests, monorepo is to put all related projects in one repository (such as React, Angular, Babel, Google…), while multirepo is divided into multiple repositories by module.
In general, monorepo is to manage multiple projects in the same repository, and lerna is a framework or way to implement monorepo.
This is its GitHub address: https://github.com/lerna/lerna
First of all, we can initialize the configuration and file directory of lerna in a folder through the lerna init command
1 | lerna-repo/ |
Lerna.json is the configuration item of lerna (in the readme of git), package.json is the configuration item of the entire repository, and the following packages are folders, each folder is a mulitrepo practice repository, which is the most common form of repository we usually have, but there is no own .git
Two modes: Fixed and Independent
In Fixed mode, the versions of all repositories in the entire lerna repository are the version field in package.json in the root directory, that is to say, they are all the same, that is to say, all packages should be upgraded together, even if you only change one of them.
In Independent mode, the version field of package.json in the root directory becomes independent, and each repository’s own version is in package.json in its own directory
Public dependence
Most of the devDependencies can be extracted into the root directory dependencies of the lerna repository through the lerna link convert command
This can reduce the space occupied by repeated dependencies
Make sure that each pacakge uses the same version (if each package uses a different version at the beginning, it seems to be the maximum version used after extraction)
Reduce dependency installation time
Common commands
Lerna init: Initialize lerna configuration
Lerna bootstrap: Install all dependencies
Lerna publishes a new version
Lerna exec: execute command (–scope can specify in which pacakge to execute)
Lerna create: Create a new package
Lerna link: Symbolically link together all Lerna packages that depend on each other in the current Lerna repository (this has not been used yet, I use npm link for local debugging)
For others, you can refer to the github repository.
Npm
Executing npm link in the root directory of the package you want to be used by other packages will create a mapping in the global directory, i.e. from global/a - > a
Calling npm link a in the package that will use a (this a is specified in the name field in the package.json of the package a) will establish the mapping of b/node_modules/a - > global/a - > a.
If you modify a at this time, it will be updated directly in b.
NPM
Usually, applications can only handle messages from within. If you want to intercept messages sent from the outside, you need a technology called hook (Hook). Imagine that you can’t control the process of npm test, but what if you really want to automatically handle something before test? Every time you manually execute something before test, is it annoying, annoying, annoying? Even if you don’t get bored, you will forget!
At this time, we will use our Hook. The following instructions are all Hooks, which can be defined in the scripts property of package.json and will be executed at a specified time in the lifecycle, which is the above-mentioned “intercepting and processing external messages”, which is very convenient for developers (maybe you want to do something bad?)
prepublish: Execute before publishing the package. (Also executed when npm install is executed in the package directory)
postpublish: execute after the package is published
preinstall: execute before the package is installed
postinstall: execute after the package is installed
preuninstall: execute before the package is uninstalled
postuninstall: execute after the package is uninstalled
preversion: Execute before modifying the version of the package
postversion: executed after modifying the version of the package
pretest, posttest: Executed when test is executed within the package, where pretest precedes posttest
prestop, poststop: Executed when stop is executed within the package, where prestop precedes poststop
prestart, poststart: Executed when start is executed within the package, where prestart precedes poststart
prerestart, postrestart: Executed when the restart script is executed in the package, where prerestart precedes postrestart. Note: If the specified restart script is not displayed in the scripts, stop is automatically called before start
The above Hooks are predefined by npm, that is to say, when you execute npm install, if you define preinstall and postinstall in the scripts, they will be automatically executed before/after npm install, no need for you to worry! awesome, is there any?
Also, any custom script (executed via npm run-script < script name >) can also be prefixed with pre and post to make hooks for it. For example: premyscript, myscript, postmyscript
That is, the pretest script will also run before npm test
Verdccio set up local repository (verification hook)
In order to test the effect of postinstall, but do not want to directly upload the unfinished package directly, you can create your own private repository locally. Here I useVerdccio
It is very simple to use, you can directly see the link above
There are currently three pitfalls:
- First, you must create a new user, otherwise you cannot publish (there may be other ways)
- If you want to install from npm after publishing the package, but the package your package depends on does not, an error will be reported. You can modify the configuration item at this time. The mac is in~/.config/verdaccio/config.yaml
1 | uplinks: |
Configure upstream links
- If you want to delete an existing repository, it is also very simple, because all will be stored in the local~/.local/share/verdaccio/storage.
Node get repository address
There is a requirement to obtain the repository address of git through node. At first, I wanted to read .git/config.
It was later discovered that the command line can be executed with child_process:
1 | const gitRemoteUrl = childProcess.execSync( |
How to specify what files are packaged
Since the script executed in my postinstall is independent and is not used in the index.js and its dependencies pointed to by the main of pacakge.json, after packaging and publishing, my script is not in the packaged directory. At this time You need to specify in the files of package.json to put my script in.