package.json字段
前端每个项目的根目录上有一个 package.json 文件,定义了当前项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等)。当运行 npm install
命令时,会根据文件中的配置自动下载所需的模块配置项目所需的运行和开发环境。
package.json 会在项目的生命周期中扮演多个角色,其中某些角色仅适用于发布到 NPM 的软件包。即使你没有把项目发布到 NPM 注册表中,或者没有将其公开发布给其他人,那么 package.json 对于开发流程仍然至关重要。
你的项目还必须包含 package.json,然后才能从 NPM 安装软件包。
package.json文件是一个JSON对象,该对象的每一个成员就是当前项目的一项设置。比如name就是项目名称,version是版本号。
下面是一个更完整的package.json文件,详细解释一下每个字段的真实含义:
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/"
}
12. bin字段
用来指定每个内部命令对应的可执行文件的位置。node工具必然会用到该字段。
当我们编写一个cli
工具的时候,需要指定工具的运行命令,比如webpack
执行 bin/index.js
文件中的代码:
"bin": {
"webpack": "bin/index.js",
}
档模块以依赖的方式被安装,如果存在bin
选项,会在node_modules/.bin/
生成对应的文件,并建立符号链接。由于node_modules/.bin/目录会在运行时加入系统的 PATH 变量,所以 npm run 就可以不带路径,直接通过命令来调用这些脚本文件。
所有 node_modules/.bin/ 目录下的命令,都可以用 npm run [命令] 的格式运行。在命令行键入npm run,按tab键会显示所有可以使用的命令。
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 表示显示警告。
name
package.json 中最重要的属性是 name
和 version
两个属性,这两个属性是必须要有的,否则模块就无法被安装,这两个属性一起形成了一个 npm 模块的唯一标识。
name是 package(包)的名称。名称的第一部分(如@scope/是可选的,用作名称空间)。当我们的包发布到 NPM 网站,其他人才能通过搜索name来安装使用
{
"name": "@scope/name"
}
name 规范
- 最好取简短而语义化的值
- 不能以,.开头
- 不能有大写字母/空格/下滑线!
- 不能和 NPM 网站中已有的包名字重名!
version
version
是 package(包)的版本,通常,它不会对你的项目产生任何影响,
除非它是一个工作空间(workspaces)-其版本必须与指定的范围相匹配,才能选择该工作空间作为解决方案的候选对象。
version 规范
version
具体体现为::“x.y.z”
- 修复 bug,小改动,增加 z
- 增加了新特性,但仍能向后兼容,增加 y
- 有很大的改动,无法向后兼容,增加 x
详细内容参考语义化版本 2.0.0
使用 npm version <update_type>自动升级版本号
update_type为patch, minor, major其中之一,分别表示补丁
,小改
,大改
npm version patch
npm version minor
npm version major
在 CI(持续集成)的脚本中可以用到此命令
description
一个描述,方便别人了解你的模块作用,搜索的时候也有用。
{
"description": "xxxx"
}
keywords
一个字符串数组,方便别人搜索到本模块
{
"keywords": [
"ant",
"component",
"design"
]
}
当我们使用 npm 检索模块时,会对模块中的 description 字段和 keywords 字段进行匹配,写好 package.json 中的 description 和 keywords 将有利于增加我们模块的曝光率。
homepage
项目主页 url,默认值为/
一般来说,我们打包的静态资源会部署在 CDN 上,为了让我们的应用知道去哪里加载资源,则需要我们设置一个根路径,这时可以通过 package.json 中的 homepage 字段设置应用的根路径。
{
"homepage": "https://ant.design"
}
bugs
填写一个 bug 提交地址或者一个邮箱,被你的模块坑到的人可以通过这里吐槽,例如:
{
"bugs": {
"url":"https://github.com/ant-design/ant-design/issues"
}
}
license
你应该为你的开源代码模块制定一个开源协议,让用户知道他们有何权限来使用你的模块,以及使用该模块有哪些限制
- MIT 是最少约束的选择。
- GPL 是最多约束的。
如果是个人随意作品,建议 MIT 许可。如果是公司或者需要严格保护的开源产品,GPL。
{
"license": "MIT"
}
详细内容参考
和用户相关的属性: author, contributors
{
"author": "iikonan",
"contributors": [
"zhangsan",
"lisi"
]
}
funding
在开源领域,资金是一个长期存在的问题.
funding命令的作用是让维护 npm 的开发人员(为 Node.js 创建包)声明元数据,为有意愿的捐赠者指明捐赠平台。
在 package.json 文件中添加了一个funding 字段, 可指向在线捐赠服务的 url,如 Patreon、Open Collective、GitHub Sponsors、License Zero 或者其他支付网站。
{
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/ant-design"
}
}
files
描述了将软件包作为依赖项安装时要包括的条目,默认值为[“*”],这意味着它将包括所有文件。
如果需要把打包后的代码也发布到 NPM 仓库
{
"files": ["dist/**/*", "lib/**/*"]
}
你还可以在包的根目录或子目录中提供.npmignore 文件,以防止某些文件被发布。
.npmignore 文件的工作原理与.gitignore 一样。
如果存在.gitignore 文件,而缺少.npmignore,则将改用.gitignore 的内容。
files字段内容会覆盖.npmignore 和.gitignore的内容。
main
main 字段是 package.json 中的另一种元数据功能,它可以用来指定加载的入口文件。
假如你的项目是一个 npm 包,当用户安装你的包后,require('my-module') 返回的是 main 字段中所列出文件的 module.exports 属性。
当不指定main 字段时,默认值是模块根目录下面的 index.js 文件。
{
"main": "lib/index.js"
}
browserslist
指定该模板供浏览器使用的版本。Browserify 这样的浏览器打包工具,通过它就知道该打包那个文件。
{
"browserslist": [
"> 0.5%",
"last 2 versions",
"Firefox ESR",
"not dead",
"IE 11",
"not IE 10"
]
}
bin
用于将某些可执行 Javascript 文件公开给父包的字段。 此处列出的所有条目都可以通过$ PATH 获得。
通俗点理解就是我们全局安装, 我们就可以在命令行中执行这个文件, 本地安装我们可以在当前工程目录的命令行中执行该文件。
"bin": {
"my-bin": "./dist/my-bin.js",
}
dist/my-bin.js
#!/usr/bin/env node
console.log("cool");
repository
{
"repository": {
"type": "git",
"url": "https://github.com/ant-design/ant-design"
}
}
scripts
该字段用于列出在运行 yarn run 时将要执行的小型 shell 脚本。
请注意,包含:(冒号)的脚本是项目的全局变量,无论你当前的工作空间如何,都可以调用它们。
最后,请注意,脚本总是相对于最近的工作空间(而不是 cwd)执行。
"scripts": {
"test": "jest",
"build:dev": "webpack-cli --config ./webpack.dev.config.js",
"build:test": "webpack-cli --config ./webpack.test.config.js",
"build:pro": "webpack-cli --config ./webpack.pro.config.js"
}
NPM 脚本的原理
npm 脚本的原理非常简单。每当执行 npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。
比较特别的是,npm run 新建的这个 Shell,会将当前目录的 node_modules/.bin 子目录加入 PATH 变量,执行结束后,再将 PATH 变量恢复原样。
这意味着,当前目录的 node_modules/.bin 子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写 mocha test 就可以了。
"test": "mocha test"
而不用写成下面这样。
"test": "./node_modules/.bin/mocha test"
由于 npm 脚本的唯一要求就是可以在 Shell 执行,因此它不一定是 Node 脚本,任何可执行文件都可以写在里面。
npm 脚本的退出码,也遵守 Shell 脚本规则。如果退出码不是0,npm 就认为这个脚本执行失败。
config
{
"name": "foo",
"config": {
"port": "8080"
}
}
当执行npm start命令,就会引用 npm_package_config_port 环境变量,
如上面的配置npm start时,就会通过端口8080启动
但是用户可以通过执行例如 npm config set foo:port 8001 来覆盖config配置。
dependencies
应用依赖,或者叫做业务依赖/生产环境依赖,这是我们最常用的依赖包管理对象!它用于指定应用依赖的外部包,这些依赖是应用发布后正常执行时所需要的,但不包含测试时或者本地打包时所使用的包
{
"dependencies": {
"react": "^16.9.0",
"react-dom": "^16.9.0"
}
}
放置生产环境依赖包的地方,即执行项目的 npm run build 时需要的依赖包。因此不要把开发环境的依赖包放在这里,比如
- eslint
- typesctipt
- webpack-dev-server
……
因为会增加生产环境安装依赖的时间
devDependencies
与dependencies字段类似,但这些依赖项仅在本地开发环境中安装,而不会由软件包的使用者(生产环境)安装。
开发环境依赖,仅次于dependencies的使用频率!它的作用和dependencies一样,只不过它里面的包只用于开发环境,不用于生产环境,这些包通常是单元测试或者打包工具等,例如gulp, webpack, moca等
{
"devDependencies": {
"webpack": "^4.40.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.1"
}
}
放置开发环境依赖包的地方,即执行项目的 npm start 时需要的依赖包。因此不要把生产环境的依赖包放在这里
peerDependencies
peerDependencies 的目的是提示宿主环境去安装满足插件 peerDependencies 所指定依赖的包,然后在插件 import 或者 require 所依赖的包的时候,永远都是引用宿主环境统一安装的 NPM 包,最终解决插件与所依赖包不一致的问题。
举个例子,ant-design UI 组件库要求宿主环境安装指定的 React 版本。具体可以看它的 package.json配置
{
"peerDependencies": {
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
}
}
optionalDependencies
除非你依赖于 fsevents 软件包,否则通常不需要此字段。
如果仅在使用特定功能时才需要包,请使用可选的对等依赖项。
{
"optionalDependencies": {
"fsevents": "^5.0.0"
}
}
engines
engines 字段指明了该模块运行的平台,比如 Node 的某个版本或者浏览器
该字段也可以指定适用的 npm 版本。
{
"engines": {
"node": ">=12.18.3",
"npm": ">7.0.0"
}
}
private
如果为 true,则该程序包被视为私有程序,Yarn/NPM 会在任何情况下均拒绝发布该程序包。这防止私人存储库意外发布
{
"private": true
}
publishConfig
此字段包含各种设置,仅当从本地来源生成包时才考虑这些设置(通过 yarn pack 或像 yarn npm publish 这样的发布命令之一)。
publishConfig.access定义将程序包发布到 npm 注册表时要使用的程序包访问级别。 有效值是公开的并且是受限制的,但是受限制的通常需要注册付费计划(这取决于你使用的注册表)。
publishConfig.bin如果存在,则在打包打包以将其运送到远程注册表之前,清单中的顶级 bin 字段将被设置为此新值。 这不会修改真正的清单,只会修改存储在 tarball 中的清单。
publishConfig.browser与publishConfig.bin属性的原理相同; 生成工作空间 tarball 时,将使用此值代替顶级浏览器字段。
publishConfig.executableFiles默认情况下,出于可移植性的原因,在 bin 字段中列出的文件之外的文件都不会在结果包归档文件中标记为可执行文件。 executeFiles 字段使你可以声明必须设置了可执行标志(+ x)的其他字段,即使不能通过 bin 字段直接访问它们也是如此。
publishConfig.main与publishConfig.bin属性相同的原理; 生成工作空间 tarball 时,将使用此值代替顶级“ main”字段。
publishConfig.module与publishConfig.bin属性相同的原理; 生成工作空间 tarball 时,将使用此值代替顶级“ module”字段。
publishConfig.registry如果存在,当将包推送到远程位置时,将替换配置中定义的任何注册表。
可能的值
{
"publishConfig": {
"access": "public",
"bin": "./build/bin.js",
"browser": "./build/browser.js",
"executableFiles": ["./dist/shim.js"],
"main": "./build/index.js",
"module": "./build/index.mjs",
"registry": "https://npm.pkg.github.com"
}
}
workspaces
工作区是 monorepos 用来将一个大型项目拆分为半独立子项目的一项可选功能,每个子项目都列出了自己的一组依赖关系。 工作区字段是全局模式列表,这些模式与应成为应用程序工作区的所有目录匹配。
{
"workspaces": ["packages/*"]
}
type
可能的值
- commonjs(默认值),适用于 Node.js 环境(服务端)
- module,即 ES Module 语法,适用于浏览器环境(客户端)
无论使用什么值,当使用 PnP 时,Yarn 3+都会生成一个.pnp.cjs 文件。
{
"type": "commonjs"
}
main 字段通常用于指向 UMD 版本的库/包,一般指定为 webpack/rollup 打包 UMD 版本后的路径
UMD 是什么呢?
- CommonJS + AMD 的组合(即 CommonJS 的语法 + AMD 的异步加载)
- 可以用于 AMD/CommonJS 环境
- UMD 还支持全局变量定义。因此,UMD 模块能够在 客户端和服务器 上工作。
main 字段还可以在发布时通过使用 publishConfig.main 字段来修改。
module
与 ES6 兼容的环境尝试通过其名称访问程序包时将使用的路径。
module 字段用于指向 ES 版本的库/包,一般指定为 webpack/rollup 打包 ES 版本后的路径
{
"module": "es/index.js"
}
unpkg
unpkg 是一个内容源自 npm 的全球快速 CDN
配置unpkg 字段后,发布到 npmjs.com 中的包会自动同步到 unpkg.com 上,一般为 umd 格式。
{
"unpkg": "dist/antd.min.js"
}
typings
{
"typings": "lib/index.d.ts"
}
sideEffects
与 webpack 相关的字段,声明该模块是否包含 sideEffects(副作用),从而可以为 tree-shaking 提供更大的优化空间。
{
"sideEffects": ["dist/*", "es/**/style/*", "lib/**/style/*", "*.less"]
}
(官方手册:https://docs.npmjs.com/cli/v8/configuring-npm/package-json)