当前位置: 首页 > article >正文

npm知识

npm 是什么

npm 为你和你的团队打开了连接整个 JavaScript 天才世界的一扇大门。它是世界上最大的软件注册表,每星期大约有 30 亿次的下载量,包含超过 600000 个包(package)(即,代码模块)。来自各大洲的开源软件开发者使用 npm 互相分享和借鉴。包的结构使您能够轻松跟踪依赖项和版本。

npm 由三个独立的部分组成:

  • 网站 —— 是开发者查找包(package)、设置参数以及管理 npm 使用体验的主要途径。
  • 注册表(registry) —— 是一个巨大的数据库,保存了每个包(package)的信息。
  • 命令行工具 (CLI) —— 通过命令行或终端运行。开发者通过 CLI 与 npm 打交道。

公共 npm 注册表

公共 npm 注册表是一个 JavaScript 包数据库,每个包都由软件和元数据组成。开源开发人员和公司的开发人员使用 npm 注册表向整个社区或其组织成员贡献包,并下载包以在他们自己的项目中使用。

要开始使用注册表,请注册一个 npm 帐户并查看“入门”和 CLI 文档。

包和模块

npm 注册表包含包,其中许多也是 Node 模块,或者包含 Node 模块。请继续阅读以了解它们有何不同以及它们如何相互作用。

包是由 package.json 文件描述的文件或目录。包必须包含 package.json 文件才能发布到 npm 注册表。包可以不受限制,也可以限定为用户或组织,范围限定的包可以是私有或公共的。

包的格式

  • a) 包含由 package.json 文件描述的程序的文件夹。
  • b) 一个包含(a)的 gzip 压缩包。
  • c) 解析为(b)的 URL。
  • d) 在注册表中发布(c)的 <name>@<version>
  • e) 指向(d)的 <name>@<tag>
  • f) 具有满足(e)的最新标记的 <name>
  • g) 一个 git url,克隆后会导致(a)。

模块

模块是 node_modules 目录中可由 Node.js require() 函数加载的任何文件或目录。

要通过 Node.js require() 函数加载,模块必须是以下之一:

  • 一个文件夹,其中包含一个 package.json 文件,其中包含 “main” 字段。
  • 一个 JavaScript 文件。

**注意:**由于模块不需要具有 package.json 文件,因此并非所有模块都是包。只有具有 package.json 文件的模块也是包。

scope

所有 npm 包都有一个名称。一些包名称也有范围(作用域)。作用域遵循包名称的通常规则(URL安全字符,没有前导点或下划线)。在包名称中使用时,作用域前面有一个 @ 符号,后面有一个斜线,例如:

@somescope/somepackagename

作用域 (Scope) 是一种将相关包组合在一起的方法,也会影响 npm 处理包的方式。

每个 npm 用户/组织都有自己的范围,只有你才能在你的范围中添加包。这意味着您不必担心有人会抢在您之前使用您的软件包名称。因此,这也是向组织发送官方软件包的好方法。

范围包可以从 npm@2 开始发布和安装,并且受主 npm 注册表支持。无范围包可以依赖于 scoped 包,反之亦然。npm 客户端向后兼容无范围注册表,因此它可以用于同时处理有范围和无范围注册表。

安装范围包

作用域包安装到常规安装文件夹的子文件夹中,例如,如果普通包安装在 node_modules/packagename 中,则作用域包将安装在 node_modules/@myorg/packagename 中。范围文件夹 (@myorg) 只是范围的名称,前面有一个 @ 符号,可以包含任意数量的范围包。

通过在 npm install 中按名称引用 @ 符号来安装范围包:

npm install @myorg/mypackage

或者用 package.json

"dependencies": {
    "@myorg/mypackage": "^1.3.0"
}

请注意,如果省略 @ 符号,则在任何一种情况下,npm 都将尝试从 GitHub 安装。

导入范围包

由于范围包安装在 scope 文件夹中,因此在代码中需要它们时,您必须包含范围的名称,例如:

require("@myorg/mypackage");

Node 处理范围文件夹的方式并没有什么特别之处。这只需要名为 @myorg 的文件夹中的 mypackage 模块。

发布范围包

范围包可以从 npm 2.0 或更高版本中发布,并且可以发布到支持它们的任何注册表,包括主 npm 注册表。

将公共范围的包发布到主 npm 注册表

发布到范围时,您有两个选项:

  • 发布到您的用户范围(示例:@username/模块
  • 发布到组织范围(示例:@org/module

如果要将公共模块发布到组织范围,则必须首先使用要发布到的范围名称创建组织,或者将其添加到具有适当权限的现有组织。例如,如果要发布到 @org,则需要在尝试发布之前在 npmjs.com 上创建 org 组织。

默认情况下,范围包不是公共的。您需要使用初始 npm publish 命令指定 --access public。这将发布包并将访问权限设置为 public,就像您在发布后运行 npm access public 一样。在发布现有范围包的新版本时,您无需执行此操作。

将私有范围的包发布到 npm 注册表

要将私有范围的包发布到 npm 注册表,您必须拥有 npm 私有模块帐户。

然后,您可以使用 npm publishnpm publish --access restricted 发布模块,它将出现在 npm 注册表中,但访问权限受限。然后,如果需要,您可以使用 npm access 或在 npmjs.com 网站上更改访问权限。

将范围与注册表相关联

范围可以与单独的注册表相关联。这样,您就可以无缝地混合使用来自主 npm 注册表和一个或多个私有注册表的包,例如 GitHub Packages 或开源 Verdaccio 项目。

您可以在登录时将范围与注册表相关联,例如

npm login --registry=http://reg.example.com --scope=@myco

范围与 registry 具有多对一的关系:一个 registry 可以托管多个 scope,但一个 scope 只指向一个 registry。

您还可以使用 npm config 将范围与注册表关联:

npm config set @myco:registry=http://reg.example.com

一旦范围与注册表关联,具有该范围的包的任何 npm install 都将改为从该注册表请求包。包含范围的包名称的任何 npm publish 都将发布到该注册表。

npm install 原理

  1. 首先得有 package.json 包管理文件才可以执行 npm install

  2. npm install -> 看是否有 package-lock.json 文件

  3. 没有 package-lock.json 文件,则构建依赖关系,然后从 registry 仓库下载安装包(压缩文件),将压缩包添加到本地的缓存文件中再将下载的压缩包解压到 node_modules 中,同时生成 package-lock.json 文件,完成安装

  4. package-lock.json 文件,则先检查下载的包和 package-lock.json 文件中的包版本是否符合 semver 版本规范,不一定非要完全一样,像 2.2.1 和 2.2.2 是一样的

  5. 不一致,则重新构建依赖关系,然后就是和第 3 步一样,去仓库下载,加压,添加缓存,解压到 node_modules 中,生成新的 package-lock.json

  6. 一致,则会去本地缓存文件中去查找缓存文件,找到缓存文件,将压缩包解压到 node_modules 中,完成安装

在这里插入图片描述

在这里插入图片描述

package.json 文件

‌package.json 文件是项目的清单,用于存储与项目有关的元数据以及依赖项包列表。它向‌ npm 提供信息,使其能够识别项目并处理所有项目的依赖项。通过 package.json 文件,其他人可以轻松安装和管理与项目相关的软件包。‌

package.json 文件必须是实际的 JSON,而不仅仅是 JavaScript 对象文本。

name

如果您计划发布包,则 package.json 中最重要的内容是 nameversion 字段,因为它们是必需的。名称和版本共同构成一个标识符,该标识符假定为完全唯一。对包的更改应随版本更改一起进行。如果您不打算发布包,则 name (名称) 和 version (版本) 字段是可选的。

一些规则:

  • 名称必须小于或等于 214 个字符。这包括 scoped 包的范围。
  • 作用域包的名称可以以点或下划线开头。如果没有范围,则不允许这样做。
  • 包的名称中不能包含大写字母。
  • 名称最终成为 URL、命令行上的参数和文件夹名称的一部分。因此,名称不能包含任何非 URL 安全字符。

一些提示:

  • 不要使用与核心 Node 模块相同的名称。
  • 不要在名称中添加 “js” 或 “node” 。假设它是 js,因为你正在编写一个 package.json 文件,你可以使用 engines 字段指定引擎。
  • 该名称可能会作为参数传递给 require(),因此它应该简短,但也具有合理的描述性。
  • 在你开发依赖之前,你可能要检查 npm 注册表,看看是否已经有这个名字。
  • 名称可以选择以范围为前缀,例如 @myorg/mypackage

version

如果您计划发布包,则 package.json 中最重要的内容是 nameversion 字段,因为它们是必需的。名称和版本共同构成一个标识符,该标识符假定为完全唯一。对包的更改应随版本更改一起进行。如果您不打算发布包,则 name (名称) 和 version (版本) 字段是可选的。

版本必须可由 node-semver 解析,它作为依赖项与 npm 捆绑在一起。(npm install semver 自己使用它)

description

在其中添加描述。它是一个字符串。这有助于人们发现你的包,因为它在 npm search 中列出。

keywords

在其中放置关键字。它是一个字符串数组。这有助于人们发现你的包,因为它在 npm search中列出。

author

顾名思义就是作者,表示该项目包的作者。它有两种形式,一种是字符串格式:

{
    "author": "CUGGZ <xxxxx@xx.com> (https://juejin.cn/user/3544481220801815)"
}

另一种是对象形式:

{
    "author": {
        "name" : "CUGGZ",
        "email" : "xxxxx@xx.com",
        "url" : "https://juejin.cn/user/3544481220801815"
	}
}

main

该字段用来指定加载的入口文件,在 browser 和 Node 环境中都可以使用。如果我们将项目发布为 npm 包,那么当使用 require 导入 npm 包时,返回的就是 main 字段所列出的文件的 module.exports 属性。如果不指定该字段,默认是项目根目录下的 index.js。如果没找到,就会报错。

该字段的值是一个字符串:

{
    "main": "./src/index.js"
}

browser

如果您的模块打算在客户端使用,则应使用 browser 字段而不是 main 字段。这有助于提示用户它可能依赖于 Node.js 模块中不可用的原语。(例如:window

{
    "browser": "./src/index.js"
}

repository

表示代码的存放仓库地址,通常有两种书写形式。第一种是字符串形式:

{
"repository": "https://github.com/facebook/react.git"
}

除此之外,还可以显式地设置版本控制系统,这时就是对象的形式:

{
    "repository": {
        "type": "git",
        "url": "https://github.com/facebook/react.git"
	}
}

homepage

项目主页的 URL。

例如:

"homepage": "https://github.com/my-project"

scripts

scripts 属性是一个对象,其中包含在包生命周期中的不同时间运行的脚本命令。key 是生命周期事件,value 是要在该点运行的命令。

{
    "scripts": {
        "serve": "webpack server --mode=development",
        "dev": "webpack --mode=development",
        "build": "webpack --mode=production"
    }
}

可以配置任何 cmd 支持的命令,运行方式是 npm run 脚本名称,不仅如此,npm 还对某些常用的脚本名称进行了简化,下面的脚本名称是不需要使用 run 的:

  • start
  • stop
  • test

一些细节:

  • 脚本中可以省略 npx,因为会将 node_module 中的 bin 目录添加到环境变量中,执行完成后会删除。
  • start 脚本有默认值:node server.js。

dependencies

该字段中声明的是项目的生产环境中所必须的依赖包。当使用 npm 或 yarn 安装 npm 包时,该 npm 包会被自动插入到此配置项中:

npm install <PACKAGENAME>
yarn add <PACKAGENAME>

当在安装依赖时使用 --save 或 -S 参数,也会将新安装的 npm 包写入 dependencies 属性。

npm install --save <PACKAGENAME>

使用版本号

该字段的值是一个对象,该对象的各个成员,分别由模块名和对应的版本要求组成,表示依赖的模块及其版本范围:

{
    "dependencies": {
        "react": "^17.0.2",
        "react-dom": "^17.0.2",
        "react-scripts": "~4.0.3",
    }
}

使用 URL

您可以指定一个 URL 来代替版本范围。

使用 git URL

Git URL 的形式如下:

<protocol>://[<user>[:<password>]@]<hostname>[:<port>][:][/]<path>[#<commit-ish> | #semver:<semver>]

<protocol>gitgit+sshgit+httpgit+httpsgit+file 之一。

如果提供了 #<commit-ish>,它将用于克隆该提交。如果 commit-ish 的格式为 #semver:<semver>,则 <semver> 可以是任何有效的 semver 范围或确切版本,并且 npm 将在远程存储库中查找与该范围匹配的任何标签或引用,就像注册表依赖项一样。如果未指定 #<commit-ish>#semver:<semver>,则使用默认分支。

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

使用 GitHub URL

就像 git URL 一样,可以包含 commit-ish 后缀。例如:

{
    "name": "foo",
    "version": "0.0.0",
    "dependencies": {
        "express": "expressjs/express",
        "mocha": "mochajs/mocha#4727d357ea",
        "module": "user/repo#feature\/branch"
    }
}

使用本地路径

从版本 2.0.0 开始,您可以提供包含包的本地目录的路径。可以使用 npm install -Snpm install --save 使用以下任何形式保存本地路径:

../foo/bar
~/foo/bar
./foo/bar
/foo/bar

在这种情况下,它们将被规范化为相对路径并添加到您的package.json中。例如:

{
    "name": "baz",
    "dependencies": {
        "bar": "file:../foo/bar"
    }
}

此功能有助于本地离线开发和创建需要安装 npm 的测试,这些测试您不想访问外部服务器,但在将包发布到公共注册表时不应使用。

在这种情况下,运行 npm install 时,通过本地路径链接的包将不会安装自己的依赖项。您必须从本地路径本身内部运行 npm install

devDependencies

devDependencies 中声明的是开发阶段需要的依赖包,如 Webpack、Eslint、Babel 等,用于辅助开发。它们不同于 dependencies,因为它们只需安装在开发设备上,而无需在生产环境中运行代码。当打包上线时并不需要这些包,所以可以把这些依赖添加到 devDependencies 中,这些依赖依然会在本地指定 npm install 时被安装和管理,但是不会被安装到生产环境中。

当使用 npm 安装软件包时,指定以下参数后,新安装的 npm 包会被自动插入到此列表中:

npm install --save-dev <PACKAGENAME>
npm install -D <PACKAGENAME>
{
    "devDependencies": {
        "webpack": "^5.96.1",
        "webpack-cli": "^5.1.4",
        "webpack-dev-server": "^5.1.0"
    }
}

private

private 字段可以防止我们意外地将私有库发布到 npm 服务器。只需要将该字段设置为 true

{
    "private": true
}

语义化版本

版本规范:主版本号.次版本号.修订号

  • 主版本号(major):当你做了不兼容的 API 修改。

  • 次版本号(minor):当你做了向下兼容的功能性新增。

  • 修订号(patch,补丁版本号):当你做了向下兼容的问题修正。

版本号范围

>

大于某个版本,例如:>1.2.1,则说明依赖要大于 1.2.1 版本。

>=

大于等于某个版本,例如:>=1.2.1,则说明依赖要大于等于 1.2.1 版本。

<

小于某个版本,例如:<1.2.1,则说明依赖要小于 1.2.1 版本。

<=

小于等于某个版本,例如:<=1.2.1,则说明依赖要小于等于 1.2.1 版本。

比较器可以用空格连接起来形成一个比较器集,它由它包含的所有比较器的交集来满足。例如,范围 >=1.2.7 <1.3.0 将匹配版本 1.2.71.2.81.2.99,但不包括版本 1.2.61.3.01.1.0

一个范围由一个或多个比较器集组成,由 || 连接。一个版本匹配一个范围,当且仅当至少一个 || 分隔的比较器集中的每个比较器都满足该版本。范围 1.2.7 || >=1.2.9 <2.0.0 将与版本 1.2.7、1.2.9 和 1.4.6 匹配,但与版本 1.2.8 或 2.0.0 不匹配。

-

指定介于两个版本之间的范围,例如:1.2.3 - 2.3.4 ,相当于 >=1.2.3 <=2.3.4

如果提供部分版本作为包含范围内的第一个版本,则缺失的部分将替换为零。例如:1.2 - 2.3.4,相当于 >=1.2.0 <=2.3.4

如果提供部分版本作为包含范围内的第二个版本,则接受以提供的第二个版本开头的所有版本,但不接受大于提供的第二个版本。例如:1.2.3 - 2.3,相当于 >=1.2.3 <2.4.0-01.2.3 - 2,相当于 >=1.2.3 <3.0.0-0

X/x/*

Xx* 中的任何一个都可以用来 “代替” [major, minor, patch] 中的某个数值。

  • *

    相当于 >=0.0.0,任何非预发行版本都满足。

  • 1.x

    相当于 >=1.0.0 <2.0.0-0,匹配主版本号。

  • 1.2.x

    相当于 >=1.2.0 <1.3.0-0,匹配主版本号和次要版本号。

部分版本范围被视为 X 范围,因此特殊字符实际上是可选的。

  • ""

    空字符串,相当于 *>=0.0.0

  • 1

    相当于 1.x.x>=1.0.0 <2.0.0-0

  • 1.2

    相当于 1.2.x>=1.2.0 <1.3.0-0

~

如果指定了次要版本,则允许补丁级更改。如果没有指定次要版本,则允许次要级别的更改。

  • ~1.2.3

    相当于 >=1.2.3 <1.(2+1).0>=1.2.3 <1.3.0-0

  • ~1.2

    相当于 >=1.2.0 <1.(2+1).0>=1.2.0 <1.3.0-0(与 1.2.x 相同)。

  • ~1

    相当于 >=1.0.0 <(1+1).0.0>=1.0.0 <2.0.0-0(与 1.x 相同)。

  • ~0.2.3

    相当于 >=0.2.3 <0.(2+1).0>=0.2.3 <0.3.0-0

  • ~0.2

    相当于 >=0.2.0 <0.(2+1).0>=0.2.0 <0.3.0-0(与 0.2.x 相同)。

  • ~0

    相当于 >=0.0.0 <(0+1).0.0>=0.0.0 <1.0.0-0(同 0.x)。

^

允许对版本 1.0.0 及更高版本进行补丁更新和次要更新,对版本 0.X >=0.1.0 进行补丁更新,而对版本 0.0.X 没有更新。

  • ^1.2.3

    相当于 >=1.2.3 <2.0.0-0

  • ^0.2.3

    相当于 >=0.2.3 <0.3.0-0

  • ^0.0.3

    相当于 >=0.0.3 <0.0.4-0

解析插入符号范围时,缺少的 patch 值会降级为数字 0,但即使在主要版本和次要版本均为 0 时,该值也会允许灵活性。

  • ^1.2.x

    相当于 >=1.2.0 <2.0.0-0

  • ^0.0.x

    相当于 >=0.0.0 <0.1.0-0

  • ^0.0

    相当于 >=0.0.0 <0.1.0-0

缺少的 minorpatch 值会将糖化为零,但也允许在这些值内灵活使用,即使主要版本为零也是如此。

  • ^1.x

    相当于 >=1.0.0 <2.0.0-0

  • ^0.x

    相当于 >=0.0.0 <1.0.0-0
    ^

允许对版本 1.0.0 及更高版本进行补丁更新和次要更新,对版本 0.X >=0.1.0 进行补丁更新,而对版本 0.0.X 没有更新。

  • ^1.2.3

    相当于 >=1.2.3 <2.0.0-0

  • ^0.2.3

    相当于 >=0.2.3 <0.3.0-0

  • ^0.0.3

    相当于 >=0.0.3 <0.0.4-0

解析插入符号范围时,缺少的 patch 值会降级为数字 0,但即使在主要版本和次要版本均为 0 时,该值也会允许灵活性。

  • ^1.2.x

    相当于 >=1.2.0 <2.0.0-0

  • ^0.0.x

    相当于 >=0.0.0 <0.1.0-0

  • ^0.0

    相当于 >=0.0.0 <0.1.0-0

缺少的 minorpatch 值会将糖化为零,但也允许在这些值内灵活使用,即使主要版本为零也是如此。

  • ^1.x

    相当于 >=1.0.0 <2.0.0-0

  • ^0.x

    相当于 >=0.0.0 <1.0.0-0


http://www.kler.cn/a/531345.html

相关文章:

  • 读书笔记--分布式架构的异步化和缓存技术原理及应用场景
  • 3.5.7 基于横盘结构的分析体系——缠论(背驰/背离)
  • PHP实现混合加密方式,提高加密的安全性(代码解密)
  • L1-006 连续因子*
  • pytorch实现简单的情感分析算法
  • Ubuntu 下 nginx-1.24.0 源码分析 main函数 — ngx_cdecl 宏
  • Smart contract -- 钱包合约
  • 代码随想录算法训练营Day51 | 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
  • 【Docker项目实战】使用Docker部署MinIO对象存储(详细教程)
  • 17.3.5 添加水印
  • Linux环境下的Java项目部署技巧:项目部署
  • 评估分类模型性能:ROC曲线和AUC值
  • 麦芯 (MachCore) 应用开发教程 6:一台设备中多台电脑主从机的设置
  • PentesterLab 24周学习计划
  • 【游戏设计原理】97 - 空间感知
  • 【翻译】OpenAI Deep Research (2025年2月2日OpenAI发布)
  • Spring中@Conditional注解详解:条件装配的终极指南
  • 8、面向对象:类、封装、构造方法
  • pandas中的关系型连接操作
  • 1.5 Go切片使用
  • 浅谈量化感知训练(QAT)
  • 机器学习--学习计划
  • Intel 与 Yocto 项目的深度融合:全面解析与平台对比
  • 变形金刚多元宇宙
  • 【汽车电子软件架构】AutoSAR从放弃到入门专栏导读
  • 【探索篇】探索部署离线AI在Android的实际体验