Home>Article>Web Front-end> This article will help you understand the principles of npm

This article will help you understand the principles of npm

青灯夜游
青灯夜游 forward
2022-08-09 09:23:02 3032browse

npm is the package management tool in the JavaScript world and is the default package management tool for theNode.jsplatform. Through npm, you can install, share, distribute code, and manage project dependencies. This article will take you through the principles of npm, I hope it will be helpful to you!

This article will help you understand the principles of npm

The principle of npm

npm is said to be the world’s largest package manager? Is the reason really just user-friendliness?

1. npm init

is used to initialize a simple package.json file. The package.json file is used to define a package description file.

1. Default behavior ofnpm initexecution

Executionnpm init --yes, all use default values.

2. Customizenpm initBehavior

npm initThe principle of the command is: call the script and output an initialized package.json file.

Get user input using prompt() method.

2. Dependency package installation

The core function of npm: dependency management. Executenpm ito install dependency packages from dependencies and devDependencies in package.json to the node_modules folder in the current directory.

2.1. Package definition

npm ican install a package. Usually package is the name of the package we need to install. Under the default configuration, npm will find the corresponding package address of the package name from the default source (Registry), and download and install it. Can also be a http url/git url/folder path pointing to a valid package name.

The accurate definition of package meets one of the following conditions a) to g), it is a package:

This article will help you understand the principles of npm

The accurate definition of package

2.2. Install local packages/remote git warehouse packages

Shared dependency packages do not have to be published to the npm source to be used.

1), Scenario 1: Local module reference

In development, calls between modules cannot be avoided. During development, we put frequently called configuration modules in the root directory, and then if there are many levels directory, and later reference

const config = require(''../../../../..config)

Such path references are not conducive to code refactoring. At this time we need to consider separating this module for other modules to share. For example, config.js can be encapsulated into a package and placed in the node_modules directory.

There is no need to manually copy or create soft connections to the node_modules directory. npm has its own solution:

Solution:

1. Add a new config folder and add config. js into the folder, change the name to index.js, create package.json to define the config package

{ "name": "config", "main": "index.js", "version": "0.1.0" }

2. Add dependencies in the project's package.json, and then execute npm i.

{ "dependencies": { "config":"file: ./config" } }

Looking at the node_modules directory, we will find an additional soft link named config, pointing to the upper config/ folder. This is because npm recognizes the URL of the file: protocol and learns that this package needs to be obtained directly from the file system. It will automatically create a soft link to node_modules to complete the "installation" process.

2), Scenario 2: Private git shared package

There will be some code/public libraries in the team that need to be shared between different projects in the team, but they may contain sensitive content.

We can simply host the dependent packages in a private git repository, and then save the git url to dependencies. npm will directly call the system's git command to pull the contents of the package from the git warehouse into node_modules.

Git url format supported by npm:

://[[:]@][:][:][/][# | #semver:]

You can use # after the git path to specify a specific git branch/commit/tag, or #semver: to specify a specific semver range.

For example:

git+ssh://git@github.com:npm/npm.git#v1.0.27 git+ssh://git@github.com:npm/npm#semver:^5.0 git+https://isaacs@github.com/npm/npm.git git://github.com/npm/npm.git#v1.0.27

3), Scenario 3: Open source package problem repair

At this time we can manually enter the node_modules directory to modify the corresponding package content, maybe modify a line of code to fix it problem. But this approach is very unwise!

Plan:

Fork the original author's git library, fix the problem in your own repo, and then change the corresponding dependencies in dependencies to your own repaired version git url can solve the problem.

3. How npm install works

After npm i is executed, all dependent packages are seen in node_modules. Developers do not pay attention to the structural details of the node_modules folder, but focus on the referenced dependency packages in the business code.

Understanding the node_modules structure helps us better understand how npm works. npm2 to npm5 changes and improvements.

3.1 npm2

npm2 uses a simple recursive installation method when installing dependent packages. Each package has its own dependency package, and the dependencies of each package are installed in its own node_modules. The dependency relationships progress layer by layer to form the entire dependency tree. This dependency tree corresponds one-to-one with the file structure tree in the file system.

The most convenient way to depend on the tree is to executenpm lsin the root directory.

Advantages:

  • The hierarchical structure is obvious and easy for fool-like management.

shortcoming:

  • For complex projects, the directory structure may be too deep, and the deep file path is too long, triggering that the file path in the window file system cannot exceed 260 characters.

  • Some packages that are dependent on multiple packages are installed repeatedly in many places, causing a lot of redundancy.

3.2 npm3

The node_modules directory of npm3 has been changed to a flatter hierarchical structure. npm3 traverses the entire dependency tree during installation and calculates the most reasonable folder installation method. All packages that are repeatedly dependent can be reinstalled.

For npm, packages with the same name and different versions are two independent packages.

The dependency tree structure of npm3 no longer corresponds to the folder hierarchy one-to-one.

3.3 npm5

Follow npm3’s flat dependency package installation method. The biggest change is the addition of the package-lock.json file.

Package-lock.json function: lock the dependency installation structure, and find that the node_modules directory file hierarchy is in one-to-one correspondence with the json structure.

npm5 will generate the package-lock.json file by default after executing npm i and submit it to the git/svn code base.

To upgrade, do not use version 5.0.

Note: In npm 5.0, if the package-lock file already exists, if you manually add a dependency to the package.json file and then execute npm install, the new dependency will not be installed in node_modules , package-lock.json will not be updated accordingly.

4. Dependency package version management

Introduces the knowledge related to dependency package upgrade management.

4.1 Semantic version semver

An important feature of npm dependency management adopts the semantic version (semver) specification as a version management solution.

The semantic version number must contain three numbers, in the format: major.minor.patch. It means: major version number. minor version number. modified version number.

We need to use the semver convention in dependencies to specify the version number or range of the required dependency package.

Commonly used rules are as follows:

This article will help you understand the principles of npm

#semver semantic version

1. Any two rules are connected with a space to represent "AND" logic is the intersection of two rules.

For example, >=2.3.1 =2.3.1 and

  • Can match 2.3.1, 2.4.5, 2.8.0
  • But it does not match 1.0.0, 2.3.0, 2.8.1, 3.0.0

2. Any two rules are connected with || to express "OR" logic, which is two rules. Union of rules.

Such as ^2 >=2.3.1 || ^3 >3.2

  • Can match 2.3.1, 2,8.1, 3.3.1
  • But it does not match 1.0.0, 2.2.0, 3.1.0, 4.0.0

3. A more intuitive way to express the version number range

  • or x matches all major versions
  • 1 or 1.x matches all versions with a major version number of 1
  • 1.2 or 1.2.x matches all versions starting with version number 1.2

4. Append after MAJOR.MINOR.PATCH - followed by dot-separated tags, which are usually regarded as pre-release version tags This version is unstable and not recommended for production use.

  • 1.0.0-alpha
  • 1.0.0-beta.1
  • 1.0.0-rc.3

4.2 Dependency version upgrade

After installing a dependency package, a new version is released. How to use npm? What about version upgrade?

  • npm i or npm update, but different npm versions, different package.json and package-lock.json files, installation and upgrade performance are different.

Conclusion of using npm3:

  • If the local node_modules is already installed, executing install again will not update the package version, but executing update will update it; and if the local node_modules is empty, executing install/update will directly install the update package.
  • npm update will always update the package to the latest version number that matches the semver specified in package.json - in this example, the latest version that matches ^1.8.0 is 1.15.0
  • Once package.json is given, no matter whether npm install or update is executed later, the webpack version in package.json has stubbornly remained unchanged from the beginning ^1.8.0

Conclusion of using npm5:

  • Whenever install is executed, npm will give priority to installing webpack according to the version specified in package-lock; avoiding the situation b) in the npm 3 table;
  • Whenever the installation/update is completed, the package-lock file will always be updated with node_modules - (so the package-lock file can be regarded as the JSON representation of node_modules)
  • If you execute npm update after node_modules is installed, the version number in package.json will also be changed to ^1.15.0

4.3 Best Practices

My commonly used node is 8.11.x, npm is 5.6.0.

  • 使用npm >= 5.1 版本,保持package-lock.json文件默认开启配置。
  • 初始化,npm i 安装依赖包,默认保存^X.Y.Z,项目提交package.json和package-lock.json。
  • 不要手动修改package-lock.json

升级依赖包:

  • 升级小版本,执行npm update升级到新的小版本。
  • 升级大版本,执行npm install @ 升级到新的大版本。
  • 手动修改package.json中的版本号,然后npm i。
  • 本地验证升级新版本后没有问题,提交新的package.json和package-lock.json文件。

降级依赖包:

  • 正确:npm i @验证没有问题后,提交package.json和package-lock.json文件。
  • 错误:修改package.json中的版本号,执行npm i不会生效。因为package-lock.json锁定了版本。

删除依赖包:

  • A计划:npm uninstall 。提交package.json和package-lock.json。
  • B计划:在package.json中删除对应的包,然后执行npm i,提交package.json和package-lock.json。

五、npm的sctipts

5.1 基本使用

npm scripts是npm的一个重要的特性。在package.json中scripts字段定义一个脚本。

比如:

{ "scripts": { "echo": "echo HELLO WORLD" } }

我们可以通过npm run echo 命令执行这段脚本,就像shell中执行echo HELLO WOLRD,终端是可以看到输出的。

总结如下:

  • npm run 命令执行时,会把./node_modules/.bin目录添加到执行环境的PATH变量中。全局的没有安装的包,在node_modules中安装了,通过npm run 可以调用该命令。
  • 执行npm 脚本时要传入参数,需要在命令后加 -- 表明,比如 npm run test -- --grep="pattern" 可以将--grep="pattern"参数传给test命令。
  • npm 还提供了pre和post两种钩子的机制,可以定义某个脚本前后的执行脚本。
  • 运行时变量:npm run 的脚本执行环境内,可以通过环境变量的方式获取更多的运行相关的信息。可以通过process.env对象访问获得:
  • npm_lifecycle_event:正在运行的脚本名称
  • npm_package_:获取当前package.json中某一个字段的匹配值:如包名npm_package_name
  • npm_package__:package中的嵌套字段。

5.2 node_modules/.bin目录

保存了依赖目录中所安装的可供调用的命令行包。本质是一个可执行文件到指定文件源的映射。

例如 webpack 就属于一个命令行包。如果我们在安装 webpack 时添加 --global 参数,就可以在终端直接输入 webpack 进行调用。

上一节所说,npm run 命令在执行时会把 ./node_modules/.bin 加入到 PATH 中,使我们可直接调用所有提供了命令行调用接口的依赖包。所以这里就引出了一个最佳实践:

•将项目依赖的命令行工具安装到项目依赖文件夹中,然后通过 npm scripts 调用;而非全局安装

于是 npm 从5.2 开始自带了一个新的工具 npx.

5.3 npx

npx 的使用很简单,就是执行 npx 即可,这里的 默认就是 ./node_modules 目录中安装的可执行脚本名。例如上面本地安装好的 webpack 包,我们可以直接使用 npx webpack 执行即可。

5.4 用法

1、传入参数

"scripts": { "serve": "vue-cli-service serve", "serve1": "vue-cli-service --serve1", "serve2": "vue-cli-service -serve2", "serve3": "vue-cli-service serve --mode=dev --mobile -config build/example.js" }

除了第一个可执行的命令,以空格分割的任何字符串都是参数,并且都能通过process.argv属性访问。

比如执行npm run serve3命令,process.argv的具体内容为:

[ '/usr/local/Cellar/node/7.7.1_1/bin/node', '/Users/mac/Vue-projects/hao-cli/node_modules/.bin/vue-cli-service', 'serve', '--mode=dev', '--mobile', '-config', 'build/example.js' ]

2、多命令运行 在启动时可能需要同时执行多个任务,多个任务的执行顺序决定了项目的表现。

1)串行执行

串行执行,要求前一个任务执行成功之后才能执行下一个任务。使用 && 服务来连接。

npm run scipt1 && npm run script2

串行执行命令,只要一个命令执行失败,整个脚本会中止的。

2)并行执行

并行执行,就是多个命令同时平行执行,使用 & 符号来连接。

npm run script1 & npm run script2

3、env 环境变量 在执行npm run脚本时,npm会设置一些特殊的env环境变量。其中package.json中的所有字段,都会被设置为以npm_package_ 开头的环境变量。

4、指令钩子 在执行npm scripts命令(无论是自定义还是内置)时,都经历了pre和post两个钩子,在这两个钩子中可以定义某个命令执行前后的命令。比如在执行npm run serve命令时,会依次执行npm run preserve、npm run serve、npm run postserve,所以可以在这两个钩子中自定义一些动作:

"scripts": { "preserve": "xxxxx", "serve": "cross-env NODE_ENV=production webpack", "postserve": "xxxxxx" }

5、常用脚本示例

// 删除目录 "clean": "rimraf dist/*", // 本地搭建一个http服务 "server": "http-server -p 9090 dist/", // 打开浏览器 "open:dev": "opener http://localhost:9090", // 实时刷新 "livereload": "live-reload --port 9091 dist/", // 构建 HTML 文件 "build:html": "jade index.jade > dist/index.html", // 只要 CSS 文件有变动,就重新执行构建 "watch:css": "watch 'npm run build:css' assets/styles/", // 只要 HTML 文件有变动,就重新执行构建 "watch:html": "watch 'npm run build:html' assets/html", // 部署到 Amazon S3 "deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/", // 构建 favicon "build:favicon": "node scripts/favicon.js",

六.npm配置

6.1 npm config

  • 通过npm config ls -l 可查看npm 的所有配置,包括默认配置。
  • 通过npm config set ,常见配置:
  • proxy,https-proxy:指定npm使用的代理
  • registry:指定npm下载安装包时的源,默认是https://registry.npmjs.org。可以指定私有的registry源。
  • package-lock.json:指定是否默认生成package-lock.json,建议保持默认true。
  • save :true/false指定是否在npm i之后保存包为dependencies,npm5开始默认为true。
  • 通过npm config delete 删除指定的配置项。

6.2 npmrc文件

可以通过删除npm config命令修改配置,还可以通过npmrc文件直接修改配置。

npmrc文件优先级由高到低,包括:

  • 工程内配置文件:项目根目录下的.npmrc文件
  • 用户级配置文件:用户配置里
  • 全局配置文件
  • npm内置配置文件 我们可以在自己的团队中在根目录下创建一个.npmrc文件来共享需要在团队中共享的npm运行相关配置。

比如:我们在公司内网下需要代理才能访问默认源:https://registry.npmjs.org源;或者访问内网的registry,就可以在工作项目下新增.npmrc文件并提交代码库。

示例配置:

proxy = http://proxy.example.com/ https-proxy = http://proxy.example.com/ registry = http://registry.example.com/

这种在工程内配置文件的优先级最高,作用域在这个项目下,可以很好的隔离公司项目和学习研究的项目两种不同环境。

将这个功能与 ~/.npm-init.js 配置相结合,可以将特定配置的 .npmrc 跟 .gitignore, README 之类文件一起做到 npm init 脚手架中,进一步减少手动配置。

6.3 node版本约束

一个团队中共享了相同的代码,但是每个人开发机器不一致,使用的node版本也不一致,服务端可能与开发环境不一致。

  • 这就带来了不一致的因素----方案:声明式约束+脚本限制。
  • 声明:通过package.json的engines属性声明应用运行所需的版本要求。例如我呢项目中使用了async,await特性,得知node查阅兼容表格[1]得知最低支持版本是7.6.0.因此指定engines配置为:
{ "engines": {"node": ">=7.6.0"} }
  • 强约束(可选):需要添加强约束,需要自己写脚本钩子,读取并解析engines字段的semver range并与运行环境做比对校验并适当提醒。

总结

  • npm init初始化新项目
  • 统一项目配置:需要团队共享npm config配置项,固化到.npmrc文件中
  • 统一运行环境:统一package.json,统一package-lock.json文件。
  • 合理使用多样化的源安装依赖包
  • 使用npm版本:>= 5.2版本
  • 使用npm scripts和npx管理相应脚本
  • 安全漏洞检查:npm audit fix修复安全漏洞的依赖包(本质:自动更新到兼容的安全版本)

引用链接

[1] node查阅兼容表格: https://node.green/

更多node相关知识,请访问:nodejs 教程

The above is the detailed content of This article will help you understand the principles of npm. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:zzvips.com. If there is any infringement, please contact admin@php.cn delete