background
With iteration of the front-end business, the expansion of the code, will inevitably take some common components or the underlying abstract logic independent warehouse, in the form of NPM package used in our main project, which will inevitably involve the package release, in order not to let us release too mess and difficult to manage, we practice some of the more convenient way to help package management specification; (Note: This practice is based on the fact that there are a large number of team members and these NPM packages need to be released frequently in daily iterations. It may not be universal.)
Rely on that
By default, there are Node, Npm, Git base environment, and also need:
- Shelljs is used to execute commands. It is not necessary. Child_process has a similar function
- Standard-version Version management and CHANGELOG
Core problems and solutions
All packages are published to the latest field
Normal business development is divided into TEST,BETA,LIVE and other different environments. Our problem lies in how to make our release more isolated. The first thing that comes to mind is the TAG of NPM. Publish –tag XXX to publish under the corresponding tag; We’ll also use the NPM view reference command;
Version number conflict
Standard-version gives us auto-increments, but this means that everyone is developing on the release branch and crashes in the test environment. You bump the version first and release it in your branch, and I will release it later
For this problem, we need to make an isolation for each person in order to ensure that the release does not conflict. For example, we need to make a tag for each person’s name, so that you send yours and I send mine, or according to the requirements of the current task, we need to use the task order number to make isolation.
(Of course, you can change the version number to publish, which will lead to more non-standard version number management problems, not recommended, see detailsSemantic version)
Version region conflict when mentioning MR/PR
When MR/PR is mentioned, the version number of branches is different, which may cause conflicts.
Therefore, we decided that in a non-Live environment, we don’t need to change the version number, just for testing, we only need a version number when we are on Live; So the idea is to publish and then roll back package.json file changes;
The main process
It’s still a little confusing, but let’s go straight to the process:
The specific implementation
// publish.js
const shell = require('shelljs')
const { join } = require('path')
const XXX_REG = /xxx-\d+/i // Requirement branches are named according to certain rules for easy differentiation
const rootPath = process.cwd()
const pkg = require(`${join(rootPath, 'package.json')}`)
const packageName = pkg.name
const version = pkg.version // Use this as a larger version, such as 1.1.0
try {
const alpha = 'alpha'
const changefiles = shell.exec('git ls-files -m').stdout.trim() // Check the updated file
if (changefiles.length) {
throw new Error('Local contains uncommitted files')}// Get the current git branch and calculate the current name
const gitBranchName = shell.exec('git branch | grep "*"').stdout
const isTestFeature = XXX_REG.test(gitBranchName)
const featureName = isTestFeature && XXX_REG.exec(gitBranchName)[0].toLowerCase()
// Calculate the tag corresponding to the current requirement branch, such as XXX-123-alpha
const tag = `${featureName}-${alpha}`
// This command is used to see if there are any published products under the corresponding tag
const latestVersion = shell.exec(`npm view ${packageName} version --tag=${tag}`).stdout
// Calculate the new version, if there is old increment, if there is no release version 0
let newVersion = ' '
if (latestVersion.includes(tag)) {
const splitVersions = latestVersion.split(` -${tag}. `)
const latestMainVersion = splitVersions[0]
const latestNum = Number(splitVersions[1])
newVersion = `${latestMainVersion}-${tag}.${latestNum + 1}`
} else {
newVersion = `${version}-${tag}. 0 `
}
// Official release
if (isTestFeature && featureName) {
const versionCommand = `npm run release -- --release-as ${newVersion} --skip.changelog --skip.tag --skip.commit`
const publishCommand = `npm publish --registry https://company.com --tag ${tag}` // Publish to the Intranet
shell.exec(`${versionCommand} && ${publishCommand}`)
shell.exec('git checkout -- package.json') // Roll back package.json changes brought by standard-version}}catch (e) {
console.log(e)
process.exit(1)}Copy the code
// package.json
{
"name": "ureponame"."version": "1.1.0"."scripts": {
"release": "standard-version"."publish-local": "node build/publish"."prepublishOnly": "npm run build"},... }Copy the code
Usage and Instructions
Use a short JS script and git/ NPM command to help us publish. It is convenient to directly run NPM run publish-local.
The release of BETA and LIVE is not reflected above. In line with the principle of not releasing manually if possible, we have connected these logics into THE CI of Gitlab and released them automatically on the Master and Release branch. The logic implemented is similar but with a bit more CI logic, which we’ll talk about in the live section later;
The above is a small exploration to make NPM package more convenient. This demand is based on the team’s frequent change release and online, different situations between teams, if you have good ideas, please leave a message to exchange and learn ~