读了一遍NPM文档

只能说自己的基本功还不够扎实,有的时候想自己看一下源码,发现啥都看不懂,不得不抽点时间来补习一下了。

本文尚未完成

写这篇文章源于想看以下一个 JavaScript 库的源码,最近一个项目中引了XSS 过滤库,虽然不是第一次 XSS 过滤了,但最近项目复盘的时候突然想起假期在知乎上看到的一个问题——如何证明(或直观解释)为何正则表达式无法可靠地解析 XML?,虽然 XSS 过滤和解析 XML 看起来没啥关系,我想看看 XSS 库是如何对一个 HTML 文件进行标签的过滤的,究竟是是用的正则表达式?但是看到源码的package.json部分有很多字段不太理解,所以读了一 NPM 文档。

整个 NPM 文档说明的比较全面,感兴趣的朋友们可以自己去阅读一下,内容也不多。在这里我就主要介绍一下我认为关于 NPM 的一些通识知识,前端开发者应该知道的内容。既然都说了是看别人的源码中有问题才来看文档的,所以接下来我将总结几个问题,按照文档的内容来给出回答。

npm 中的一些小细节

scope 和 unscope 包1

npm 包其实也是分作用域的,同一个作用域下不允许相同的包名,但它的主要作用是用来划分权限,对该作用域没有相关权限的用户是不能进行一些操作的,比如有的公司自己有 npm 作用域,不在该作用域下的账户是无法访问到 npm 包的,有的时候npm install提示找不到包,可以查看是否安装的是 scope 包,并且确定有没有可读的权限。

unscope 包:unscope 包对所用 npm 用户都是可见的,在包名前面没有@*/的标识,用户可以任意安装这些包。

1
"antd": "^4.8.0"

scope 包:scope 包前面有@*/的标识,表示组织的域。此外 scope 包并不是所有不在作用域下的账户都不能访问,如下这个@ant-design/icons包对于所有人都是可见的,只是对该包的归属做一个标记,或者包名已经被别人注册,要使用相同的名字就要限制一下作用域。

1
"@ant-design/icons": "^4.0.0"

注意:有一种特殊的形式@types/*
由于TypeScript的不断发张,很多很早之前发布的包并没有使用TypeScript编写,导致包中不存在声明文件,如果引用这个包的项目使用TypeScript编写,则在编译的时候会失败。所以很多包会补写对应的声明文件,单独发布,这些声明文件就会用@types/*进行标识。

dependencies 和 devDependencies

这个比较好理解了,仔细看package.json文件就会发现这两个字段,dependencies 里边存放了当前包引用的依赖包的包名和版本号。devDependencies 存放的是开发这个包的过程中使用的依赖包的包名和依赖。二者的区别在于前者表示项目的运行时依赖,如包中引用到额函数库等,后者的内容表示开发过程中,使用这些包能方便开发,缺少不影响包的功能,比如一些 CLI,构建工具等等。

在开发过程中建议遵守这些约定,以免引起不必要的麻烦。

TIPS

在执行安装命令时使用--save-dev-D标记会自动将所安装的包的包名的版本号存入package.jsondevDependencies中。

使用npm i(nstall)的时候会默认带上--save-prod标记,这个标记会将所安装包的包名和版本存入package.jsondependencies中。

local 和 global 安装

global 安装:除了安装在某一个文件夹内,也可以安装在全局,在安装的时候加上-g这个标记即可,这种安装通常是将作为命令行工具使用。安装之后即可在全局使用命令,如@vue/cli这个包,是 Vue 的脚手架工具,全局安装之后可以执行vue --versionvue ui等指令。

local 安装:npm 安装不同于 maven,pip,npm 有全局和局部两种安装方式,使用安装命令安装时默认会将包安装到当前文件夹的node_modules目录,只有当前目录下层的包或文件才能使用安装的包。

在任一目录下使用require()会检查当前目录的node_modules目录有没有这个包,没有则继续检查上级目录,重复上述操作,直到顶级目录,如果到现在还没找到,则会查找全局是否有这个包,如果都没有找到就会报Uncaught Error: Cannot find module "xxx"

如果你想像安装在全局的那些包一样使用命令,可以在命令前加npx,如npx webpack,关于 NPX,稍后会详细的讲解。

^~*

如果现在你正在基于别人开发的包开发自己的产品,细心的你应该会注意到在package.json文件中devDependenciesdepenencies字段中每个包的版本号几乎都有^|~|*前缀,这些前缀代表了不用的含义,简单的总结起来就是他们三个表示了不同的版本粒度,控制允许安装包的版本范围。

1
2
3
4
5
{
"webpack": "~5.10.3" /* 同5.10和5.10.x,允许的版本范围大于1.10.3 */,
"webpack-cli": "^4.3.0" /* 同4.x和4,允许的版本范围大于4.3 */,
"webpack-merge": "*" /* 同x,允许任意版本 */
}

npm i安装的时候默认会查找安装 registry 中最新的版本,版本号用于限制最低支持的版本,当有~时,限制是最严格的,需要和版本号三个字段作比较。当有^时,只需要比较版本号中前两个字段。当为*时,对最低版本号不做限制。

高阶使用

更改 global 安装的位置

如果你不想将 npm 安装的全局包放在默认的位置,可以更改它。
核心步骤:

  1. 先在你想放的地方创建一个文件夹
  2. 使用 npm config set prefix $新建的文件夹路径设置新路径
  3. 添加新创建的文件夹到环境变量
作者

KylinLee

发布于

2020-11-27

更新于

2022-02-11

许可协议

CC BY-NC-SA 4.0

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×