关于Node-Modules的注意事项
Node-modules文件夹及其结构。
引言
这是一个关于node_modules文件夹及其结构的说明。
背景
这是一个关于node_modules文件夹及其结构的说明。特别是,当一个NODE项目引用同一包的不同版本时,我想回答以下问题。这些问题很简单,但如果处理不当,可能会导致恼人的版本地狱。
- 同一包的不同版本是如何放置在node_modules文件夹中的?
- 应用程序运行时,是否会调用同一包的所有版本,还是只调用该包的一个版本?
为了回答这些问题,我创建了三个NODE包。package-client
项目直接和间接地引用了两个版本的package-0
。
- 我们将发布两个版本的
package-0
,版本1.0.0
和版本1.0.1
。 package-1
引用package-0
版本1.0.0
。package-client
引用package-1
和package-0
版本1.0.1
。因此,package-client
同时引用了package-0
的版本1.0.0
和版本1.0.1
。
这个实验是在一个私有的NPM注册表上进行的。如果您不知道如何设置私有的NPM注册表,您可以查看我的另一篇说明。为了简化我的工作,所有包都作用域为"@example"。例如,package-0
的全名是@example/package-0
。我还为每个包添加了一个.npmrc文件,所以我每次发布或安装包时都不需要指定注册表URL(--registry)。
@example:registry=https://:4873/
如果您希望所有作用域为@example
的包都使用注册表https://:4873/,您也可以将该条目放在您home目录下的.npmrc文件中。我们可以通过curl其URL来确认注册表是否正在运行。
curl https://:4873/
"package-0"
@example/package-0的package.json如下所示
{
"name": "@example/package-0",
"version": "1.0.0",
"description": "The @example/package-0",
"main": "index.js",
"author": "Song Li",
"license": "ISC"
}
Index.js文件的唯一功能是导出一个表示版本号的string
。
module.exports = 'This is Version 1.0.0';
我们可以通过以下命令将包发布到注册表
npm publish
然后我们可以将package.json和index.js文件更新到版本1.0.1
,并发布它。
{
"name": "@example/package-0",
"version": "1.0.1",
......
}
module.exports = 'This is Version 1.0.1';
我们可以通过以下命令确认这两个版本都已发布到注册表
npm view @example/package-0 versions
"package-1"
@example/package-1引用了@example/package-0。
{
"name": "@example/package-1",
"version": "1.0.0",
"description": "The @example/package-1",
"main": "index.js",
"author": "Song Li",
"license": "ISC",
"dependencies": {
"@example/package-0": "1.0.0"
}
}
有三种方法可以引用包版本。
- ~version “大约等于版本” - 它会将您更新到所有未来的补丁版本,而不会增加次要版本。~1.2.3 将使用从 1.2.3 到 <1.3.0 的版本;
- ^version “与版本兼容” - 它会将您更新到所有未来的次要/补丁版本,而不会增加主要版本。^2.3.4 将使用从 2.3.4 到 <3.0.0 的版本;
- 绝对版本 - 在此说明中,我使用了绝对版本 "1.0.0"
index.js需要@example/package-0并重新导出其string
。由于@example/package-1引用了@example/package-0版本1.0.0
,理想情况下它应该导出字符串 "This is Version 1.0.0
"。
const msg = require('@example/package-0');
module.exports = msg;
然后我们可以发布该包并确认其在注册表中的可用性。
npm publish
npm view @example/package-1 versions
"package-client"
随着@example/package-0和@example/package-1都发布到注册表,我们可以看看package-client
。
{
"name": "package-client",
"version": "1.0.0",
"description": "The package-client ",
"main": "index.js",
"private": true,
"keywords": [],
"author": "Song Li",
"license": "ISC",
"dependencies": {
"@example/package-1": "1.0.0",
"@example/package-0": "1.0.1"
}
}
它引用了@example/package-1和@example/package-0,index.js打印出这两个包的string
。
const msg_0 = require('@example/package-0');
const msg_1 = require('@example/package-1');
console.log(`Message from package-0: ${msg_0}`);
console.log(`Message from package-1: ${msg_1}`);
然后我们可以安装引用的包并查看node_modules文件夹。
npm install
find . -name "package-0" -type d -prune -print | xargs du -chs
如果我们现在运行index.js,我们将看到以下结果
node index.js
结论
现在我们可以得出结论。
- 当NODE应用程序引用同一个包的多个版本时,所有版本都将安装在node_modules文件夹中。在这个例子中,
1.0.1
安装在顶层,1.0.0
安装在@example/package-1文件夹下; - 当程序中使用同一个包的多个版本时,如果程序实际使用了这些版本,那么所有版本都将被调用。
我们可以进一步查看package-lock.json文件,以更好地理解如何安装包的不同版本。
我们需要与团队共享package-lock.json文件,以便所有人在npm install
时都拥有相同的node_modules文件夹。如果我们想从注册表中清理实验包,可以使用以下命令
npm cache clean -f
npm unpublish @example/package-0 -f
npm unpublish @example/package-1 -f
关注点
- 这是一个关于node_modules文件夹及其结构的说明。
- 您不太可能遇到包的不同版本的问题。但是,如果您遇到问题,最好知道您可能在同一个程序中同时运行依赖包的不同版本。
- 希望您喜欢我的帖子,并希望这篇说明能对您有所帮助。
历史
- 2020年10月16日:第一次修订