current position:Home>Especially how to publish vuejs, which can be applied to the project after learning

Especially how to publish vuejs, which can be applied to the project after learning

2021-08-23 10:03:41 Tong ouba

Preface : Looking at the source code for the first time , Thank you, brother Chuan, for providing the right theme , Give careful guidance . I feel that learning the source code is really helpful , I tasted the sweetness for the first time , You can draw lessons from ( Plagiarism ) The idea of source code solves practical problems , That's good . I'm really a rookie , I can't write , Just take notes of your study .

1. Preparatory work and main spirit

1. Source code address :https://github1s.com/vuejs/vue-next/blob/HEAD/scripts/release.js

2. The main content of the source code :vuejs How is it published

3. Think about what you can apply after learning :

1. For example, after learning the source code , Optimize the release process of your project  
———— It's kind of like Faye :
 There are many problems in the front-end version distribution process of our company git command  , these git Command I can run in script mode , Learn from... In the source code run Method :
const run = (bin, args, opts = {}) =>
  execa(bin, args, { stdio: 'inherit', ...opts })
 It has been written so far (CV) A tool script , Optimized the process of issuing pre release versions of our company's front-end projects , See part VI .

4. Read the source code, pay special attention to :

 First understand the overall situation ~  The main line is main function    First understand about   Then check again if you don't understand 

2. from main The function starts to see

take main Sort out the main code in the function , The overall process is shown in the figure below :

Let's take a brief look at vuejs Release the overall process

2.1 Process related to version number verification :40 - 77 That's ok

40 That's ok : Get version number

44 -49 That's ok : If the version number does not exist, ask whether you want to upgrade the large version 、 Small version 、 Patch version Or custom

52-59 That's ok : If the user selects customization, the customized version will be obtained

65-67 That's ok : Check whether the version number is legal

69-73 That's ok : Ask if you are sure to release the version

55-77: If you choose no main End of function execution , return

2.2 Tests before release :80-86 That's ok

2.3 Update dependent version number :88-90 That's ok

2.4 function build command :93-101 That's ok

2.5 Run the log command :104 That's ok

2.6 Submission code :106-113 That's ok

2.7 Run the issue command :115-119 That's ok

2.8 The new version push To git:121-125 That's ok

2.9 Prompt to skip updated packages :131-139 That's ok

3. Some definition details of variables and functions

3.1 Test before release :

80-86 That's ok :

// without skipTests  Skip the test   And there's no  isDryRun( hurry in vain ?) Then run the test 
step('\nRunning tests...')
    if (!skipTests && !isDryRun) {
    // Use jest ,  Clear cache 
    await run(bin('jest'), ['--clearCache'])
    //yarn test 
    await run('yarn', ['test', '--bail'])
    } else {
    console.log(`(skipped)`)
 }

3.2 Build all packages

93—101 That's ok :

// It's actually running yarn build  command  
await run('yarn', ['build', '--release'])

3.3 Run the log command

104 That's ok : function yarn Of log command

await run(`yarn`, ['changelog'])
//changelog It's defined in package.json  Of  npm scripts  in :
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
 // It's used here conventional-changelog, See part V : Dependencies used 

3.4 Submission code

106-113 That's ok :git Version management related

// Determine if the document has changed , If there is any change, submit to git
const { stdout } = await run('git', ['diff'], { stdio: 'pipe' })
  if (stdout) {
    step('\nCommitting changes...')
    await runIfNotDry('git', ['add', '-A'])
    await runIfNotDry('git', ['commit', '-m', `release: v${targetVersion}`])
  } else {
    console.log('No changes to commit.')
  }

3.5 Run the issue command

115-119 That's ok : Release

// publish packages
  step('\nPublishing packages...')
  for (const pkg of packages) {
    await publishPackage(pkg, targetVersion, runIfNotDry)
  }
//publishPackage In the definition of 175-230 That's ok :
async function publishPackage(pkgName, version, runIfNotDry) {
  //  If a package is to be skipped, it returns directly 
  if (skippedPackages.includes(pkgName)) {
    return
  }
  // Get path and content 
  const pkgRoot = getPkgRoot(pkgName)
  const pkgPath = path.resolve(pkgRoot, 'package.json')
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
  // If it is private, return 
  if (pkg.private) {
    return
  }

  // For now, all 3.x packages except "vue" can be published as
  // `latest`, whereas "vue" will be published under the "next" tag.
  //  Define the published tags  ( hit tag)
  let releaseTag = null
  if (args.tag) {
    releaseTag = args.tag
  } else if (version.includes('alpha')) {
    releaseTag = 'alpha'
  } else if (version.includes('beta')) {
    releaseTag = 'beta'
  } else if (version.includes('rc')) {
    releaseTag = 'rc'
  } else if (pkgName === 'vue') {
    // TODO remove when 3.x becomes default
    releaseTag = 'next'
  }

  // TODO use inferred release channel after official 3.0 release
  // const releaseTag = semver.prerelease(version)[0] || null
  //  Execute release :  function yarn To issue orders for 
  step(`Publishing ${pkgName}...`)
  try {
    await runIfNotDry(
      'yarn',
      [
        'publish',
        '--new-version',
        version,
        ...(releaseTag ? ['--tag', releaseTag] : []),
        '--access',
        'public'
      ],
      {
        cwd: pkgRoot,
        stdio: 'pipe'
      }
    )
    console.log(chalk.green(`Successfully published ${pkgName}@${version}`))
  } catch (e) {
    if (e.stderr.match(/previously published/)) {
      console.log(chalk.red(`Skipping already published: ${pkgName}`))
    } else {
      throw e
    }
  }
}

3.6 Update dependency details

88-90: Update all dependencies

updateVersions(targetVersion)
//updateVersions  Is an updated version of the defined function , It's called in  updatePackage function 
function updateVersions(version) {
  // 1. update root package.json
  updatePackage(path.resolve(__dirname, '..'), version)
  // 2. update all packages
  packages.forEach(p => updatePackage(getPkgRoot(p), version))
}
//packages Is defined in section 16 That's ok ;
//updatePackag stay 157 That's ok : It probably means finding the path package.json File and then read the contents of the file , Turn to object , An updated version , Write back to the file .
function updatePackage(pkgRoot, version) {
  const pkgPath = path.resolve(pkgRoot, 'package.json')
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
  pkg.version = version
  updateDeps(pkg, 'dependencies', version)
  updateDeps(pkg, 'peerDependencies', version)
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
}
// What we use here updateDeps stay  159-173 Line definition :
function updateDeps(pkg, depType, version) {
  const deps = pkg[depType]
  if (!deps) return
  Object.keys(deps).forEach(dep => {
    // Check dependencies , If there is vue Then prompt and replace the version .
    if (
      dep === 'vue' ||
      (dep.startsWith('@vue') && packages.includes(dep.replace(/^@vue\//, '')))
    ) {
      console.log(
        chalk.yellow(`${pkg.name} -> ${depType} -> ${dep}@${version}`)
      )
      deps[dep] = version
    }
  })
}

4. Overall process summary and review

take main Sort out the main code in the function , The overall process is shown in the figure below :

Let's take a brief look at vuejs Release the overall process

5. Dependencies used

5.1 minimist

const args = require('minimist')(process.argv.slice(2))

minimist Lightweight command line parameter parsing engine

https://blog.csdn.net/fangxuan1509/article/details/107469465

https://www.npmjs.com/package/minimist

5.2 chalk

const chalk = require('chalk')

chalk Is a color plug-in

https://blog.csdn.net/sqrtsix/article/details/76615630

https://www.npmjs.com/package/chalk

5.3 semver

const semver = require('semver')

Semver It's a special analysis Semantic Version( Semantic version ) Tools for ,“semver” It's actually the abbreviation of these two words .Npm This tool is used to handle version related work .

Semantic version literacy https://segmentfault.com/a/1190000014405355

https://www.npmjs.cn/misc/semver/

5.4 enquirer

const { prompt } = require('enquirer')

The command line prompts ?

https://www.npmjs.com/package/enquirer

5.5 execa

const execa = require('execa')

execa Can call shell And local and external programs javascript encapsulation . Will start the child process to execute . Support for multiple operating systems , Include windows. If the parent process exits , Then all the generated child processes are killed .

http://abloz.com/tech/2018/08/21/nodejs-execa/

https://www.npmjs.com/package/execa

5.6 yarn Related commands

https://yarn.bootcss.com/docs/getting-started/

5.7 conventional-changelog

Automatically generate on the basis of contractual submission changelog

https://blog.csdn.net/weixin_34326179/article/details/91382865

https://www.npmjs.com/package/conventional-changelog

6. application : Optimize hair “ Pre release version ” The process of

6.1 Problem description

“ Pre release version ” It is a verified version before we send the official version , At present, our company's front-end projects are issued “ Pre release version ” You should go through the process shown in the figure below , There are many operations git The order of , Inspired by reading the source code , I want to write a tool script , Turn these commands into automatic execution , The required information only needs to be entered or selected by the developer .

Which produces tag It needs to be based on tag Naming conventions to generate . The following figure 12 Is a fixed value ,20 Represents the year ,30 It represents the week of the year ,01 Represents the number of editions issued .

6.2 Solution

So I need to do these things in the script I need to write :

(1) To get the current year , The current week : These two values are expressed in JS The basic code is ok,

(2) You need to interact with developers to get the number of releases and service names : have access to release.js Used in rely on :enquirer;

(3) Need to run git command :release.js Used in rely on :execa, And defined run() Method .

(4) If you want to highlight the prompt in the console, use dependency :chalk , Of course, this is optional

6.3 Concrete realization

6.3.1 First, create a new project under the project root directory scripts Folder , Then build release.js file

6.3.2 Installation dependency

npm install chalk --save-dev 
npm install execa --save-dev 
npm install enquirer --save-dev 

6.3.3 Write code

const chalk = require('chalk')
const execa = require('execa')
const {
  prompt
} = require('enquirer')

const step = msg => console.log(chalk.cyan(msg))

const run = (bin, args, opts = {}) =>
  execa(bin, args, {
    stdio: 'inherit',
    ...opts
  })


async function main() {
  console.log(' Welcome to the release assistant script ')
  step('\n Verify that the code is submitted ...')
  const { yes } = await prompt({
    type: 'confirm',
    name: 'yes',
    message: ` Make sure that the code has been submitted and the code push To develop Did you branch ?`
  })

  if (!yes) {
    return
  }
  //  Switch to  develop  Branch , Pull the latest code 
  await run('git', ['checkout', 'develop'])
  await run('git', ['pull', 'origin', 'develop'])
  //  Switch to  release  Branch , Pull the latest code 
  await run('git', ['checkout', 'release'])
  await run('git', ['pull', 'origin', 'release'])
  //  Local  release  Branch merging  develop  Branch code 
  await run('git', ['merge', 'develop'])
  //  After the merger , Push to remote  release  Branch 
  await run('git', ['push', 'origin', 'release'])
  
  //  The following logic is spelling tag Number , hit tag use 
 
  //  Gets the last two digits of the current year 
  const yearLastTwoBit = getLastTwoBitYear()
  console.log(yearLastTwoBit)

  //  Get what week of the year it is 
  const currentWeek = theWeek()
  console.log(currentWeek)

  //  The version number of this time 
  const targetVersion = (
    await prompt({
      type: 'input',
      name: 'version',
      message: ' This is the first time this week ?( Please enter a number )',
    })
  ).version
  console.log(targetVersion)

  //  Front end service name 
  const serviceName = (
    await prompt({
      type: 'input',
      name: 'serviceName',
      message: ' Please enter the name of this front-end service ?( for example  fe_beg)',
    })
  ).serviceName
  console.log(serviceName)

  //  Splicing tag name  
  const tagName = `Cloud_R-12.${yearLastTwoBit}.${currentWeek}.${targetVersion > 10 ? targetVersion : `0${targetVersion}`}-${serviceName}`

  //  Splice notes 
  const comment = `${serviceName} service ${currentWeek} Zhou / Iteration number ${targetVersion} Sub version release `
  
  //  Local call  Tag, Generate version 
  await run('git', ['tag', tagName, '-m', comment])

  //  push  Tag  To the remote code base , Trigger a build 
  await run('git', ['push', '--tags'])

  console.log(' Wait a moment , The pre release environment version release can be completed , Detailed view Jenkins')

  //  Switch back to develop Branch 
  await run('git', ['checkout', 'develop'])
}

//  Gets the last two digits of the current year 
function getLastTwoBitYear() {
  const date = new Date()
  const currentYear = date.getFullYear().toString()
  return currentYear.substr(currentYear.length - 2, 2)
}

function theWeek() {
  var totalDays = 0;
  now = new Date();
  var days = new Array(12);
  days[0] = 31;
  days[2] = 31;
  days[3] = 30;
  days[4] = 31;
  days[5] = 30;
  days[6] = 31;
  days[7] = 31;
  days[8] = 30;
  days[9] = 31;
  days[10] = 30;
  days[11] = 31;
  // Determine if it's a leap year , in the light of 2 Calculate the number of days of the month 
  if (Math.round(now.getYear() / 4) == now.getYear() / 4) {
    days[1] = 29
  } else {
    days[1] = 28
  }
  if (now.getMonth() == 0) {
    totalDays = totalDays + now.getDate();
  } else {
    var curMonth = now.getMonth();
    for (var count = 1; count <= curMonth; count++) {
      totalDays = totalDays + days[count - 1];
    }
    totalDays = totalDays + now.getDate();
  }
  // Get the first few weeks 
  var week = Math.round(totalDays / 7);
  return week;
}
main().catch(err => {
  console.log(err)
})

6.3.4 And then in package.json Add one npm script:

"release": "node scripts/release.js",

6.3.5 test

Run the command :

npm run release  

The following figure shows the script running effect :

The gadget script runs fairly smoothly , Just run 1 subcommand , confirm 1 Time , Input 2 Time , Avoid a lot of input git command . And after sending “ pre-release ” after , It's easy for us to forget to switch back to develop Branch , The gadget script finally cuts the code to develop Branch , Can reduce unnecessary trouble .

Of course, that is , I didn't consider many exceptions case , Not very robust , To be optimized .

This article is from WeChat official account. - Front end canteen (webcanteen)

The source and reprint of the original text are detailed in the text , If there is any infringement , Please contact the [email protected] Delete .

Original publication time : 2021-08-06

Participation of this paper Tencent cloud media sharing plan , You are welcome to join us , share .

copyright notice
author[Tong ouba],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210823100333060z.html

Random recommended