Everyone knows that node is currently bundled with NPM. NPM is the dependency manager for Node, although it is not the only option. We also have PNPM/YARN/CNPM/NI.

However, all dependency managers are addressing a pain point in NPM. The dependency declaration file package.json itself is essentially unchanged for NPM.

For example, you can run a command using NPM run serve or run a command using YARN serve.

You can see that yarn can omit the run argument here.

However, they only parse package.json. For example, in the following file, when running NPM run serve, you are actually running the command corresponding to the serve key under scripts in the JSON file.

{
  "name": "h5"."version": "1.0.7"."private": true."scripts": {
    "serve": "vue-cli-service serve"
  },
  "dependencies": {
    "axios": "^ 0.19.2"."vuex": "^ 3.4.0"
  },
  "devDependencies": {
    "node-sass": "^ 4.12.0"}}Copy the code

Commands are only used for ease of understanding. For example:

npm run server
# similar to running the following command from the command line
vue-cli-service serve
Copy the code

The difference between running a command through NPM run and directly

Again, use the configuration above to describe:

{
  "scripts": {
    "serve": "vue-cli-service serve"}}Copy the code

When NPM runs vue-cli-service serve, it checks whether there is an executable file with the same name under the current node_modules/. Bin. If there is an executable file, it runs it.

Here we can open the directory to see:

If you run vue-cli-service serve directly from the command line, you will not find the executable program from node_modules.

Run the executable

So what is an executable file? There are many vue-cli-service with the same name in the figure above. Which one is running?

Let’s start with how did these files come from?

For example, @vue/cli-service has the following package.json file. Note the bin field. When we run NPM i@vue /cli-service, NPM creates several executables named vue-cli-service in node_modules/.bin/.

{
  "name": "@vue/cli-service"."version": "4.4.6."."description": "local service for vue-cli projects"."main": "lib/Service.js"."typings": "types/index.d.ts"."bin": {
    "vue-cli-service": "bin/vue-cli-service.js"}}Copy the code

The definition of executable varies from system to system. On Windows, executables are determined by group policies and environment variables.

Use set Pathext to view the environment variable pathext, which defines the suffix that can be used as an executable file.

# Look at the executable file suffix
set pathext
Copy the code

As you can see from the above configuration, the common exe is also included. This executable file on Windows can be run by typing the file name on the command line or double-clicking it.

Check out this short video for a sneak peek.

On Unix systems, this is done by setting the file properties to be executable and declaring the interpreter on the first line of the file.

If we run in CMD, Windows usually calls the vue-cli-service. CMD file, which is a batch script for Windows:

@ECHO off
SETLOCAL
CALL :find_dp0

SET _maybeQuote="
IF EXIST "%dp0%\node.exe" (
  SET "_prog=%dp0%\node.exe"
) ELSE (
  SET _maybeQuote=
  SET "_prog=node"
  SET PATHEXT=%PATHEXT:; .JS; =; %
)

%_maybeQuote%%_prog%%_maybeQuote%  "%dp0%\.. \_@vue_cli-service@4.4.6@@vue\cli-service\bin\vue-cli-service.js" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b
Copy the code

So when we run vue-cli-service serve, it is equivalent to running node_modules/. Bin /vue-cli-service. CMD serve.

The script then uses Node to run the vue-cli-service.js js file. Thanks to a series of system-specific apis available in Node, you can do a lot of things in this JS file, such as reading and analyzing files in the directory where the command was run. Generate files and so on from templates.

Unix is the default executable file, you must enter the full filename
vue-cli-service

The default executable in # Windows CMD automatically looks up the file according to Pathext when we don't add the suffix
vue-cli-service.cmd

# Windows PowerShell executable file, can be cross-platform
vue-cli-service.ps1
Copy the code

It should be mentioned that in Windows, CMD scripts are used a lot and have good compatibility. PowerShell is more powerful, but the way it runs commands is very different from CMD commands, which can lead to confusion about which commands should be run in which interpreter.

Example: The command running mode is incompatible

Example: Windows by default, this script is disabled on many operating systems. As a result, the NPM command runs incorrectly

So try CMD if you encounter powerShell related errors.

Inject relevant runtime information

This section is illustrated by debugging the NPM source code.

NPM_CONFIG_REGISTRY is an environment variable from process.env. This is the image address that can be configured when NPM is installed.

Then we look at the environment variable, which is not defined in the current system.

Let’s start debugging scripts NPM run s2 in mockm package.json

{
  "scripts": {
    "s2": "node run.js remote --config=D:/git2/mockm/server/example/full.mm.config.js",}}Copy the code
npm run s2
Copy the code

To save space, break directly at key points:

Here is the source for [email protected] and you can see that NPM uses npm-lifecycle to run a child process that calls our run.js file.

When run.js is run through spawn, some process-related information is set, which is natively supported by Node.

For example, the NPM_CONFIG_REGISTRY environment variable I just mentioned.

Let’s continue to the next breakpoint, the run.js file:

You can see that the child process successfully retrieved the information given by the parent process.

conclusion

  • runnpm run xxxNPM looks for the program to be executed in node_modules/. Bin in the current directory, and runs it if it finds it.
  • If not, look for the global node_modules/.bin.npm i -g xxxIs to install to the global directory;
  • If the global directory is still not found, look for other executables with the same name in the PATH environment variable.

extension

  • [email protected] source
  • Mockm front-end interface tuning tool
  • NPM Scripts Usage Guide
  • NPM Scripts official documentation