package.json 和 package-lock.json 解析()

package.json 前端每个项目的根目录上有一个 package.json 文件,定义了当前项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等)。当运行 npm install命令时,会根据文件中的配置自动下载所需的模块配置项目所需的运行和开发环境。

package.json文件是一个JSON对象,该对象的每一个成员就是当前项目的一项设置。比如name就是项目名称,version是版本号。

1. name 字段

2. version 字段

格式为 x.x.x,name 和 version 一起构成一个标识符,该标识符被认为是完全唯一的。每次发布时 version不能与已存在的一致。

3. description 字段用于编写描述信息的字符串。有助于模块在 npm库被搜索发现。

4. keywords 字段字符串组成的数组,有助于模块在 npm库被搜索发现。

5. homepage 字段

项目的主页地址。

6. bugs 字段 用于反馈项目问题的 issue 地址或者邮箱。

7. license字段当前项目的协议—— 模块使用权限和限制。

8. author字段 & contributors字段author和 contributors均表示当前项目的共享者。

contributors是对象数组,具有 name字段和可选的 url及 email字段。

author 可以是具有 name字段和可选的 url及 email字段的对象,或包括name, url 和 email 字符串:

"author": "edemao edemao@xx.com (https://edemao.top/)"
 
/** 或 */
"author": {
  "name" : "edemao",
  "email" : "edemao@xx.com",
  "url" : "https://edemao.top/"
}

9. files字段

是模块下文件名或者文件夹名构成的数组,如果是文件夹名,则文件夹下所有的文件也会被包含进来(除非文件被另一些配置排除了)。可以在模块根目录下创建一个.npmignore文件,写在这个文件里边的文件即便被写在files属性里边也会被排除在外,这个文件的写法与.gitignore类似。

10. main字段指定加载的入口文件,require导入的时候会加载这个文件。默认值是模块根目录下面的index.js。

12. bin字段用来指定每个内部命令对应的可执行文件的位置。node工具必然会用到该字段。

当我们编写一个cli工具的时候,需要指定工具的运行命令,比如webpack执行 bin/index.js文件中的代码:

"bin": {
  "webpack": "bin/index.js",
}

档模块以依赖的方式被安装,如果存在选项,会在生成对应的文件,并建立符号链接。由于node_modules/.bin/目录会在运行时加入系统的 PATH 变量,所以 npm run 就可以不带路径,直接通过命令来调用这些脚本文件。

bin
node_modules/.bin/
所有 node_modules/.bin/ 目录下的命令,都可以用 npm run [命令] 的格式运行。在命令行键入npm run,按tab键会显示所有可以使用的命令。

13. man 字段

用来指定当前模块的 man文档的位置。

14. directories 字段directories制定一些方法来描述模块的结构, 用于告诉用户每个目录在什么位置。

15. repository 字段指定一个源代码存放地址。

16. scripts字段指定了运行脚本命令的 npm 命令行缩写。使用 scripts字段可以快速的执行 shell 命令,可以理解为 alias。scripts可以直接使用node_modules中安装的模块,否则需要使用npx命令才能直接运行:

"scripts": {
  "build": "webpack"
}
 
// npm run build 相当于 npx webpack

17. config 字段

用于添加命令行的环境变量。在脚本就可以引用字段的值。

server.js
config
console.log(process.env.npm_package_config_port); // 8080

也可以通过进行修改:

npm config set
npm config set edemao:port 8000

18. dependencies字段 & devDependencies字段dependencies指定项目运行所依赖的模块,devDependencies指定项目开发所需要的模块。

值对象的每一项为一个键值对,前面是模块名称,后面是对应模块的版本范围。版本号遵循“major.minor.patch”的格式规定(主版本号.次版本号.修补版本号)。

修补版本中的更改表示不会破坏任何内容的错误修复。
次要版本的更改表示不会破坏任何内容的新功能。
主要版本的更改代表了一个破坏兼容性的大变化。 如果用户不适应主要版本更改,则内容将无法正常工作。
1. 固定版本:比如 5.3.1,安装时只安装指定版本。

2. 波浪号:比如 ~5.3.1, 表示安装 5.3.x 的最新版本(不低于5.3.1),但是不安装5.4.x,也就是说安装时不改变大版本号和次要版本号。

3. 插入号:比如 5.3.1, ,表示安装 5.x.x 的最新版本(不低于5.3.1),但是不安装 6.x.x,也就是说安装时不改变大版本号。需要注意的是,如果大版本号为 0,则插入号的行为与波浪号相同,这是因为此时处于开发阶段,即使是次要版本号变动,也可能带来程序的不兼容。

4. latest:安装最新版本。

依赖安装时,–save参数表示写入dependencies,–save-dev表示写入devDependencies。

19. peerDependencies 字段peerDependencies字段,就是用来供插件指定其所需要的主工具的版本。

比如,项目依赖 A 模块和 B 模块的 1.0.0 版本,而 A 模块本身又依赖 B 模块的 2.0.0 版本,用 peerDepedencies 指定 A 模块 使用 B 的时候,必须是 2.0.0 版本:

{
  "name": "A",
  "peerDependencies": {
    "B": "2.0.0"
  }
}

注意,从npm 3.0版开始,初始化的时候 peerDependencies不会默认带出。

20. bundledDependencies 字段指定发布的时候会被一起打包的模块。

21. optionalDependencies 字段可选的项目运行依赖,写法和dependencies一样,不同之处在于如果安装失败不会导致 npm install失败。

22. engines 字段指明模块运行的平台限制,比如 Node或者 npm的某个版本或者浏览器。

23. os 字段指定模块能运行的操作系统。

24. cpu 字段限制模块只能在某种架构的cpu下运行。

25. private 字段布尔值,可以防止一个私有模块被无意间发布,true则 npm拒绝发布它。

26. publishConfig 字段在模块发布时生效,用于设置发布用到的一些值的集合。如果你不想模块被默认标记 tag 为最新的,或者默认发布到公共仓库,可以在这里配置 tag 或仓库地址。如果只想让模块被发布到一个特定的 npm仓库,通常 publishConfig会配合 private来使用。

27. preferGlobal字段布尔值,表示当用户不将该模块安装为全局模块时(即不用–global参数),true 表示显示警告。

28. browser 字段指定供浏览器使用的模块版本。指定浏览器打包工具比如 Browserify该打包的文件。

package-lock.json

package-lock.json 目的是对整个依赖树进行版本固定的(锁死),会在 npm 更改 node_modules 目录树 或者 package.json 时自动生成的 ,它准确的描述了当前项目 npm 包的依赖树,并且在随后的安装中会根据 package-lock.json 来安装,保证是相同的一个依赖树,不考虑这个过程中是否有某个依赖有小版本的更新。项目中有 package-lock.json 文件,会根据 package-lock.json 里的内容来处理和安装依赖而不再根据 package.json,除非对 package.json 中依赖的版本进行了修改。

注意,使用cnpm install时候,并不会生成 package-lock.json 文件,也不会根据 package-lock.json 来安装依赖包,还是会使用 package.json 来安装。

package-lock.json 可能被意外更改的原因:

package.json 文件修改了;

挪动了包的位置:将部分包的位置从 dependencies 移动到 devDependencies 这种操作,虽然包未变,但是也会影响 package-lock.json,会将部分包的 dev 字段设置为 true;

registry 的影响:安装源 registry 不同,执行 npm i 时也会修改 package-lock.json使用 npm ci来 而不是 npm i 安装依赖,可以避免异常的修改 package-lock.json。

目前很多项目代码 lockfileVersion = 1,如果不小心更新node > 14,可能会导致 lockfileVersion = 2,而且会出现以下告警:

npm WARN read-shrinkwrap This version of npm is compatible with lockfileVersion@1, but package-lock.json was generated for lockfileVersion@2. I’ll try to do my best with it!
v1=> npm v5 和 v6。
v2: => npm v7&v8,向后兼容 v1 锁文件。
v3: => npm v7&v8 没有 向后兼容性

需要在确定升级到 npm 8 和 package-lock.json 2 之前,对 npm 版本进行降级:

/** 1. mac 或 linux 上需要先 运行: */rm /usr/local/bin/npm && ln -s ~/.npm-packages/bin/npm /usr/local/bin/npm/** 2. 全局安装旧 npm */npm install -g npm@6.14.15

————————

package.json 前端每个项目的根目录上有一个 package.json 文件,定义了当前项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等)。当运行 npm install命令时,会根据文件中的配置自动下载所需的模块配置项目所需的运行和开发环境。

package.json文件是一个JSON对象,该对象的每一个成员就是当前项目的一项设置。比如name就是项目名称,version是版本号。

1. name 字段

2. version 字段

格式为 x.x.x,name 和 version 一起构成一个标识符,该标识符被认为是完全唯一的。每次发布时 version不能与已存在的一致。

3. description 字段用于编写描述信息的字符串。有助于模块在 npm库被搜索发现。

4. keywords 字段字符串组成的数组,有助于模块在 npm库被搜索发现。

5. homepage 字段

项目的主页地址。

6. bugs 字段 用于反馈项目问题的 issue 地址或者邮箱。

7. license字段当前项目的协议—— 模块使用权限和限制。

8. author字段 & contributors字段author和 contributors均表示当前项目的共享者。

contributors是对象数组,具有 name字段和可选的 url及 email字段。

author 可以是具有 name字段和可选的 url及 email字段的对象,或包括name, url 和 email 字符串:

"author": "edemao edemao@xx.com (https://edemao.top/)"
 
/** 或 */
"author": {
  "name" : "edemao",
  "email" : "edemao@xx.com",
  "url" : "https://edemao.top/"
}

9. files字段

是模块下文件名或者文件夹名构成的数组,如果是文件夹名,则文件夹下所有的文件也会被包含进来(除非文件被另一些配置排除了)。可以在模块根目录下创建一个.npmignore文件,写在这个文件里边的文件即便被写在files属性里边也会被排除在外,这个文件的写法与.gitignore类似。

10. main字段指定加载的入口文件,require导入的时候会加载这个文件。默认值是模块根目录下面的index.js。

12. bin字段用来指定每个内部命令对应的可执行文件的位置。node工具必然会用到该字段。

当我们编写一个cli工具的时候,需要指定工具的运行命令,比如webpack执行 bin/index.js文件中的代码:

"bin": {
  "webpack": "bin/index.js",
}

档模块以依赖的方式被安装,如果存在选项,会在生成对应的文件,并建立符号链接。由于node_modules/.bin/目录会在运行时加入系统的 PATH 变量,所以 npm run 就可以不带路径,直接通过命令来调用这些脚本文件。

bin
node_modules/.bin/
所有 node_modules/.bin/ 目录下的命令,都可以用 npm run [命令] 的格式运行。在命令行键入npm run,按tab键会显示所有可以使用的命令。

13. man 字段

用来指定当前模块的 man文档的位置。

14. directories 字段directories制定一些方法来描述模块的结构, 用于告诉用户每个目录在什么位置。

15. repository 字段指定一个源代码存放地址。

16. scripts字段指定了运行脚本命令的 npm 命令行缩写。使用 scripts字段可以快速的执行 shell 命令,可以理解为 alias。scripts可以直接使用node_modules中安装的模块,否则需要使用npx命令才能直接运行:

"scripts": {
  "build": "webpack"
}
 
// npm run build 相当于 npx webpack

17. config 字段

用于添加命令行的环境变量。在脚本就可以引用字段的值。

server.js
config
console.log(process.env.npm_package_config_port); // 8080

也可以通过进行修改:

npm config set
npm config set edemao:port 8000

18. dependencies字段 & devDependencies字段dependencies指定项目运行所依赖的模块,devDependencies指定项目开发所需要的模块。

值对象的每一项为一个键值对,前面是模块名称,后面是对应模块的版本范围。版本号遵循“major.minor.patch”的格式规定(主版本号.次版本号.修补版本号)。

修补版本中的更改表示不会破坏任何内容的错误修复。
次要版本的更改表示不会破坏任何内容的新功能。
主要版本的更改代表了一个破坏兼容性的大变化。 如果用户不适应主要版本更改,则内容将无法正常工作。
1. 固定版本:比如 5.3.1,安装时只安装指定版本。

2. 波浪号:比如 ~5.3.1, 表示安装 5.3.x 的最新版本(不低于5.3.1),但是不安装5.4.x,也就是说安装时不改变大版本号和次要版本号。

3. 插入号:比如 5.3.1, ,表示安装 5.x.x 的最新版本(不低于5.3.1),但是不安装 6.x.x,也就是说安装时不改变大版本号。需要注意的是,如果大版本号为 0,则插入号的行为与波浪号相同,这是因为此时处于开发阶段,即使是次要版本号变动,也可能带来程序的不兼容。

4. latest:安装最新版本。

依赖安装时,–save参数表示写入dependencies,–save-dev表示写入devDependencies。

19. peerDependencies 字段peerDependencies字段,就是用来供插件指定其所需要的主工具的版本。

比如,项目依赖 A 模块和 B 模块的 1.0.0 版本,而 A 模块本身又依赖 B 模块的 2.0.0 版本,用 peerDepedencies 指定 A 模块 使用 B 的时候,必须是 2.0.0 版本:

{
  "name": "A",
  "peerDependencies": {
    "B": "2.0.0"
  }
}

注意,从npm 3.0版开始,初始化的时候 peerDependencies不会默认带出。

20. bundledDependencies 字段指定发布的时候会被一起打包的模块。

21. optionalDependencies 字段可选的项目运行依赖,写法和dependencies一样,不同之处在于如果安装失败不会导致 npm install失败。

22. engines 字段指明模块运行的平台限制,比如 Node或者 npm的某个版本或者浏览器。

23. os 字段指定模块能运行的操作系统。

24. cpu 字段限制模块只能在某种架构的cpu下运行。

25. private 字段布尔值,可以防止一个私有模块被无意间发布,true则 npm拒绝发布它。

26. publishConfig 字段在模块发布时生效,用于设置发布用到的一些值的集合。如果你不想模块被默认标记 tag 为最新的,或者默认发布到公共仓库,可以在这里配置 tag 或仓库地址。如果只想让模块被发布到一个特定的 npm仓库,通常 publishConfig会配合 private来使用。

27. preferGlobal字段布尔值,表示当用户不将该模块安装为全局模块时(即不用–global参数),true 表示显示警告。

28. browser 字段指定供浏览器使用的模块版本。指定浏览器打包工具比如 Browserify该打包的文件。

package-lock.json

package-lock.json 目的是对整个依赖树进行版本固定的(锁死),会在 npm 更改 node_modules 目录树 或者 package.json 时自动生成的 ,它准确的描述了当前项目 npm 包的依赖树,并且在随后的安装中会根据 package-lock.json 来安装,保证是相同的一个依赖树,不考虑这个过程中是否有某个依赖有小版本的更新。项目中有 package-lock.json 文件,会根据 package-lock.json 里的内容来处理和安装依赖而不再根据 package.json,除非对 package.json 中依赖的版本进行了修改。

注意,使用cnpm install时候,并不会生成 package-lock.json 文件,也不会根据 package-lock.json 来安装依赖包,还是会使用 package.json 来安装。

package-lock.json 可能被意外更改的原因:

package.json 文件修改了;

挪动了包的位置:将部分包的位置从 dependencies 移动到 devDependencies 这种操作,虽然包未变,但是也会影响 package-lock.json,会将部分包的 dev 字段设置为 true;

registry 的影响:安装源 registry 不同,执行 npm i 时也会修改 package-lock.json使用 npm ci来 而不是 npm i 安装依赖,可以避免异常的修改 package-lock.json。

目前很多项目代码 lockfileVersion = 1,如果不小心更新node > 14,可能会导致 lockfileVersion = 2,而且会出现以下告警:

npm WARN read-shrinkwrap This version of npm is compatible with lockfileVersion@1, but package-lock.json was generated for lockfileVersion@2. I’ll try to do my best with it!
v1=> npm v5 和 v6。
v2: => npm v7&v8,向后兼容 v1 锁文件。
v3: => npm v7&v8 没有 向后兼容性

需要在确定升级到 npm 8 和 package-lock.json 2 之前,对 npm 版本进行降级:

/** 1. mac 或 linux 上需要先 运行: */rm /usr/local/bin/npm && ln -s ~/.npm-packages/bin/npm /usr/local/bin/npm/** 2. 全局安装旧 npm */npm install -g npm@6.14.15