1. Introduction

Hi, I’m Wakawa. Recently, I organized an activity to read the source code together. If you are interested, you can join in with my wechat account RuoChuan12, or follow my official account Ruochuanjing and reply to “source code”. It has been three months, we exchange and learn together, common progress, many people said that a lot of harvest.

If you want to learn source code, Underscore, Lodash, Vuex, Sentry, Axios, Redux, KOA, VUUE-Devtools, Vuex4, Koa-Compose, vue 3.2 are highly recommended Release, VUE-this, CREate-Vue, toy Vite and more than 10 source code articles.

In this article only-allow-analysis, ask a star^_^

Recently, we organized source code reading activities, and we learned about 200 lines of source code together every week. It is a weekly issue and has been running for 14 issues. So we search for all kinds of worth learning, and the code line is not many source.

Reading this article, you will learn:

1. How to debug source code 2. Learn NPM hooks 3"preinstall": "npx only-allow pnpm"One line of code unified specification package manager 4. Learn only-allow principle 5. , etc.Copy the code

2. The scene

As we develop projects, we often need to install dependencies, although they are usually documented. But it’s not a mandatory constraint. People are prone to mistakes or omissions, and if the rule is to use NPM, someone on the team one day accidentally uses other dependencies installed by other package managers and uploads code, which can lead to online problems in serious cases. So we need tools (code) to enforce constraints.

Can you replace NPM/YARN/PNPM? Easy to use! Source code revealed! Automatically match the corresponding package manager according to the lock file and run the corresponding command.

In the source code, we have learned that Vue 3.2 has been released, so how does Rain Creek release vue.js?

Vue3 source code uses NPM’s preinstall hook constraint and can only install dependencies using PNPM. Let’s move on to the implementation.

Vue3 source code && NPM command hook

// vue-next/package.json
{
  "private": true."version": "3.2.22"."scripts": {
    "preinstall": "node ./scripts/preinstall.js",}}Copy the code
Executed in sequenceExecute this script before # install
preinstall
Execute the install script
install
Execute the script after # install
postinstall
Copy the code

Custom commands are also supported.

See the official documentation hooks for more.

Let’s look at the preinstall source code.

// vue-next/scripts/preinstall.js

if (!/pnpm/.test(process.env.npm_execpath || ' ')) {
  console.warn(
    `\u001b[33mThis repository requires using pnpm as the package manager ` +
      ` for scripts to work properly.\u001b[39m\n`
  )
  process.exit(1)}Copy the code

This code is also relatively simple, check if the script is not executed by PNPM error, exit the process.

For process objects, see Teacher Ruan Yifeng process Objects

The process.argv property returns an array of arguments for executing the script from the command line. Its first member is always Node, the second member is the script file name, and the remaining members are the arguments to the script file.

This code addresses the questions raised in the opening scene, but you can’t copy and paste this code for every project. Can we package it into NPM package for use? I didn’t think much about it at the time and didn’t wrap the NPM package. Until I looked through the element-Plus source code and found the only-allow package. One line of code unified specification package manager.

{
  "scripts": {
    "preinstall": "npx only-allow pnpm -y"}}Copy the code

When I saw the code, I thought: How did they know that? I didn’t think much about it. Until one day, the PNPM document Only allow PNPM document has this. All right, well, I’m sorry I didn’t read the file. At that time, I planned to analyze the source code of this only-allow package, opened a look surprised, only 36 lines, write it, so I wrote this article.

It is customary to prepare the environment before looking at the source code.

4. Environment preparation

4.1 Clone Code

# Recommend cloning my source library
git clone https://github.com/lxchuan12/only-allow-analysis.git
cd only-allow-analysis/only-allow
# npm i -g pnpm
pnpm i

git clone https://github.com/pnpm/only-allow.git
cd only-allow
# npm i -g pnpm
pnpm i
Copy the code

4.2 Debugging Source Code

Let’s look at the package.json file.

// only-allow/package.json
{
  "bin": "bin.js",}Copy the code

Ensure that the main entry file is only-allow/bin.js.

In the latest version of VSCode, auto attach supports intelligent debugging by default. If you find that auto attach is not supported, you can use the shortcut key CTRL + shift + p to check whether it is enabled.

Add the following command to only-allow/package.json

// only-allow/package.json
{
  "scripts": {
    "preinstall": "node bin.js pnpm"}},Copy the code

UsedPM = whichPMRuns()

Press the shortcut key CTRL + to open the terminal. To debug only-allow/bin. Js’, run the following yarn add release it -d command.

PNPM install will be displayed on the terminal after debugging.

As shown below:

For more details on debugging, see my article: Beginner orientation: Front-end programmers must learn basic skills – debugging JS code

Then we look at the main source flow by debugging.

5. Only – allow the source code

// only-allow/bin.js
#!/usr/bin/env node
const whichPMRuns = require('which-pm-runs')
const boxen = require('boxen')

const argv = process.argv.slice(2)
if (argv.length === 0) {
  console.log('Please specify the wanted package manager: only-allow <npm|pnpm|yarn>')
  process.exit(1)}// The first parameter is the package manager that the user passed in to use
// such as NPX only-allow PNPM
// Here the debug is node bin.js PNPM
const wantedPM = argv[0]
// if neither NPM PNPM yarn is configured, an error is reported
if(wantedPM ! = ='npm'&& wantedPM ! = ='pnpm'&& wantedPM ! = ='yarn') {
  console.log(`"${wantedPM}" is not a valid package manager. Available package managers are: npm, pnpm, or yarn.`)
  process.exit(1)}// The package manager used
const usedPM = whichPMRuns()
// An error occurs if the package managers you want to use are not equal.
// -npm prompts to use NPM install
// - PNPM prompts you to use PNPM install
// - yarn Prompts you to use YARN install
// Finally exit the process
if(usedPM && usedPM.name ! == wantedPM) {const boxenOpts = { borderColor: 'red'.borderStyle: 'double'.padding: 1 }
  switch (wantedPM) {
    case 'npm':
      console.log(boxen('Use "npm install" for installation in this project', boxenOpts))
      break
    case 'pnpm':
      console.log(boxen(`Use "pnpm install" for installation in this project. If you don't have pnpm, install it via "npm i -g pnpm". For more details, go to https://pnpm.js.org/`, boxenOpts))
      break
    case 'yarn':
      console.log(boxen(`Use "yarn" for installation in this project. If you don't have Yarn, install it via "npm i -g yarn". For more details, go to https://yarnpkg.com/`, boxenOpts))
      break
  }
  process.exit(1)}Copy the code

Following the breakpoint, we can see which-pm-runs.

6. Which package manager is currently running which-pm-runs

The package manager and version number are finally returned.

According to debugging, process.env.npM_config_user_Agent is a string like this.

"Yarn / 1.22.10 NPM /? The node/v14.16.0 Linux x64"

'use strict'

module.exports = function () {
  if(! process.env.npm_config_user_agent) {return undefined
  }
  return pmFromUserAgent(process.env.npm_config_user_agent)
}

function pmFromUserAgent (userAgent) {
  const pmSpec = userAgent.split(' ') [0]
  const separatorPos = pmSpec.lastIndexOf('/')
  return {
    name: pmSpec.substr(0, separatorPos),
    version: pmSpec.substr(separatorPos + 1)}}Copy the code

6.1 String.prototype.substr Intercepts a String

By the way. The pull Request I saw in vue-next source => chore: Remove Deprecated String.prototype.substr

String.prototype.substr is deprecated.

That is, substr is not recommended. Slice is recommended.

Ecma specification

7. To summarize

We show that the vuE3 source code can only use PNPM for the preinstall hook constraint by starting from a real scenario where the team needs to standardize the unified package manager. At the same time, by looking at the source code of Element-Plus and PNPM documentation, we learned about the package only-allow. You can do a unified package manager “preinstall”: “NPX only-allow PNPM”

We learned how it works. Only -allow to compare the expected package manager with the running package manager. If the match fails, an error message is displayed. Which -pm-runs gets the package manager and version number of the currently running script by getting the process.env.npM_config_user_Agent variable.

We use tools (code) rather than documentation and communication to constrain.

The writing of this article reminds me of what I thought when I participated in the excellent front end Technology Open Day in 2018

There was a quote from the speaker. Couldn’t agree more.

Technical (open source) projects are essentially the instrumentalization of ideas, routines, and norms.

At the same time to give us inspiration is also to read more official documents and norms.

Suggest readers clone my warehouse hands-on debugging source code learning.

Finally, you can continue to pay attention to me @Ruogawa. Welcome to join us in ruochuan12 to learn about 200 lines of source code every week and make progress together.


About && communication groups

Recently, I organized a reading activity for source code. If you are interested, you can join me in wechat ruochuan12 for long-term communication and learning.

Author: Often in the name of ruochuan mixed traces in rivers and lakes. Welcome to add my wechat account ruochuan12. Front road | know very little, only good study. Concern about the public number if chuan vision, every week to learn the source code, learn to see the source code, advanced advanced front end. Wakawa’s blog segmentfault wakawa’s view column, has opened a column on wakawa’s view, welcome to follow ~ dig gold column, welcome to follow ~ github blog, beg a star^_^~