- package.json 用于记录一些项目信息,比如项目名、版本号、项目描述、依赖包…
- package.json 必须是一个合法的 JSON 文件,不能使用注释或者尾逗号等非标准语法
- package.json 必须包含 name 和 version 字段,它们组成项目的唯一标识
在日常开发中,项目的依赖包会被存放到 node_modules 目录下,因此 node_modules 文件夹的体积会很大,不方便团队之间的传输。通常我们会把 node_modules 目录配置到 .gitignore 文件中,表示 node_modules 文件夹不受 Git 管理。
项目的依赖包信息会被记录到 package.json 中,开发人员只需通过 package.json 同步代码信息即可。
拿到一个没有 node_modules 的项目时,执行 npm i
即可下载项目的依赖包。npm i
会读取 package.json 中关于依赖包的信息,然后创建 node_modules 文件夹,并将项目的依赖包下载到 node_modules 目录下。
engines
engines
字段用于声明项目所依赖的特定版本的运行时和工具。engines
字段是一个对象,key 为需要的工具或运行时的名称,value 为允许的版本范围
"engines": {
"node": "16.x",
"eslint": "7.0.0 - 8.43.0",
"typescript": "~4.8.2",
"pnpm": "^8.6.2"
}
使用 npm 管理项目依赖包时,还需要配置 .npmrc
文件才能成功管理 node 版本:
engine-strict = true
name
name
字段用于声明软件包的名称,有如下约束:
- 必须为小写
- 不能超过 214 个字符
- 不能有 [空格] / [非 URL 安全的字符];可以包含 [连字符
-
] / [下划线_
] - 不能与 [核心模块] / [已有的包] 重名
"name": "nodejs-demo"
非 URL 安全的字符串有:空格、引号、括号、分号、冒号、百分号、问号、加号、等号、星号、井号、美元符号、逗号、斜杠等。
这些字符在 URL 中有特殊的含义,如果不进行编码,可能会导致错误或者安全问题。
version
version
字段用于声明软件包的版本号
"version": "1.0.0"
版本号遵循语义化版本控制规范(Semantic Versioning),格式为 MAJOR.MINOR.PATCH
,例如 1.2.3
。每个部分具有以下含义:
MAJOR
:主版本号,表示不向后兼容的大型改动或重大升级MINOR
:次版本号,表示向后兼容的功能性增加或改进PATCH
:修订号,表示向后兼容的问题修复或补丁
除了基本的版本号格式外,还可以在版本号后面添加预发布标识 -beta.1
或构建元数据 +20211231
Semantic Versioning 会用到如下符号:
^
:不接受最左边非零数字较大的版本
eg:^0.13.0
→npm updata
→0.13.1
,不会更新到0.14.0
eg:^1.13.0
→npm updata
→1.13.1
/1.14.0
,不会更新到2.0.0
~
:只接受修订号较大的版本>
:只接受较大的版本;类似的还有>=
、<
、<=
、=
(可忽略不写)-
:只接受一定范围内的版本;eg:2.1.0 - 2.6.2
||
:只接受组合内的版本;eg:< 2.3 || > 2.6
可以使用 lastest
表示使用最新版本~
main
main
字段用于声明软件包的入口文件
"main": "src/main.js"
假设我们有一个名为 foo 的包,它的根目录下有一个 package.json 文件和一个 lib 文件夹,lib 文件夹下有一个 index.js 文件。我们想让用户能够通过 require("foo")
来引入我们的包。那么我们可以在 package.json 中设置 main
字段为 "lib/index.js"
{
"name": "foo",
"version": "1.0.0",
"main": "lib/index.js"
}
这样,当用户安装了我们的包后,就可以在他们的代码中这样使用:
const foo = require("foo")
如果 package.json 中没有配置 main
字段或配置的文件无法正常解析,就会找到项目根目录下的 index.js 文件
license
license
字段用于告诉用户你的包的使用许可证和限制,有如下 3 种情况:
- 使用常见的开源许可证:可使用当前的 SPDX 许可证标识来表示你使用的许可证
"license": "MIT"
- 使用不常见的或自定义的许可证:可使用一个文件名或 URL 来指向许可证文本
"license": "SEE LICENSE IN <filename>"
"license": "UNLICENSED"
- 不适用许可证:
"license": "UNLICENSED"
这样做可能会阻止一些用户使用你的包,因为他们不知道他们是否有权利这样做。
description
description
字段用于描述你的包的功能和用途
"description": "Fast, unopinionated, minimalist web framework"
你应该为你的包提供一个简洁而有意义的描述,让人们一目了然地知道你的包是做什么的。
keywords
keywords
字段用于描述你的包的功能和主题。这个字段可以帮助人们在 npm 搜索中发现你的包
"keywords": ["web", "framework", "http", "rest", "middleware"]
你应该为你的包提供一些相关的关键词,让人们能够根据他们的需求或兴趣找到你的包。
private
private
字段用于防止你的包被意外地发布到 npm
"private": true
如果你在你的 package.json 中设置了 "private": true
,那么 npm 将拒绝发布它
scripts
scripts
字段用于定义一些可以通过 npm run
命令执行的脚本scripts
字段是一个对象,key 为脚本的名称,value 为要执行的命令
"scripts": {
"build": "node build.js",
"test": "mocha test/*.js",
"start": "node index.js"
}
你也可以使用一些预定义的脚本名称,它们有一些特殊的功能或行为:
start
:当你运行npm start
时,会执行这个脚本,它通常用于启动你的应用程序或服务器test
:当你运行npm test
时,会执行这个脚本,它通常用于运行你的测试代码或工具install
:当你运行npm install
时,会在安装完所有依赖后执行这个脚本,它通常用于做一些安装后的初始化工作
除了这些预定义的脚本名称外,还有一些生命周期脚本,它们会在特定的情况下自动触发:
prepublish
:在你发布你的包之前,会执行这个脚本,它通常用于做一些准备工作,如编译或测试postinstall
:在你安装一个包之后,会执行这个脚本,它通常用于做一些安装后的配置工作,如生成配置文件或下载资源
你还可以为任何自定义的脚本添加 pre
/ post
前缀,来创建一个在该脚本之前或之后执行的脚本:
"scripts": {
"prebuild": "echo 'Building...'",
"build": "node build.js",
"postbuild": "echo 'Done.'"
}
这样,当你运行 npm run build
时,会依次执行 prebuild
、build
和 postbuild
脚本。
dependencies
在日常的 CSR (客户端渲染) 开发中,我们约定,对于仅开发环境使用的依赖包,放到 devDependences
里面;对于会被构建到生产环境使用的依赖包,放到 dependences
里面。但其实,不论依赖包怎么放,都不会影响项目的正常构建,也不会有性能问题。毕竟,依赖包由 npm 管理,构建由 webpack 完成,两个工具其实并没有什么关联。
在 SSR (服务端渲染) 开发中,需要注意 devDependences
和 dependences
的配置,如果没有正确配置好,会影响性能。
在依赖包的开发中,也需要注意 devDependeces
和 dependences
的配置,因为 npm 会认为 dependences
里边的依赖包为核心依赖包,而 devDependences
里边的依赖包为开发时态依赖。然后,当别人执行命令行 yarn add XXX
安装你的依赖包时,核心依赖包会被一同安装,而开发时态依赖包则不会被安装。
在 CSR 开发中,执行 npm i
时,dependencies
、devDependencies
指定的依赖包都会安装到 node_modules 目录下。
可以执行 npm i --production
表示仅安装 dependecies
指定的依赖包
peerDependencies
的目的是提示宿主环境去安装指定的依赖包,以解决插件与依赖包不一致的问题。
当我们开发的工程将作为第三方软件包发布时才会用到 peerDependencies
package-lock.json
package-lock.json 文件是一个锁定文件,它包含了你的项目安装的所有依赖包的信息,比如它们的确切版本号、来源、校验值等。
它的作用是让不同的开发者在同一个项目上能够安装相同的依赖包,即使这些包已经发布了新的版本。
package-lock.json 文件是自动生成的,当你使用 npm 修改了 node_modules 目录或者 package.json 文件时,它就会更新。
当我们在一个项目中 npm i
时,会自动生成一个 package-lock.json 文件,和 package.json 在同一级目录下。package-lock.json 记录了项目依赖包的信息。当我们下次再 npm i
时,npm 发现项目中有 package-lock.json 文件,会直接根据 package-lock.json 里的内容来处理和安装依赖,而忽略 package.json。
package-lock.json 文件不能被发布,如果在非根目录下发现该文件,它会被忽略。它和 npm-shrinkwrap.json 文件有相同的格式和功能,但是 npm-shrinkwrap.json 允许发布。不推荐使用 npm-shrinkwrap.json,除非你要部署一个 CLI 工具或者使用发布过程来生成生产环境的包。
如果在项目根目录下同时存在 package-lock.json 和 npm-shrinkwrap.json 文件,那么 package-lock.json 会被完全忽略,npm-shrinkwrap.json 会起作用。
经过实际使用发现,如果我们 node_modules 文件夹下的包中下载时,如果安装源 registry 不同,就算版本一样,执行 npm i
时也会修改 package-lock.json