前言
作为前端开发,相信大家对package.json并不陌生。但平时在构建业务项目时,对于package.json的关注度其实并不高。大多数情况下都只是打开json文件看一看scripts的指令有哪些,大致浏览一下项目的依赖。那这篇文章的目的就是稍详细地再重温一下package.json文件,其字段的含义,作用,以及注意事项。
正文
理解package.json
package.json
文件其实是npm
的产物。npm
大家并不陌生,其全称是node package manager
:是node包管理器。那么package.json
文件中的package
自然指的就是node package
。而package.json
就是npm
生成的对node包进行描述的文件。
官方对package.json
的作用如下所述:
list the packages your project depends on
- 列出了项目依赖的包
specifies versions of a package that your project can using semantic versioning rules
- 使用语义化版本控制规则指定了包的版本
makes your build reproducible, and therefore easier to share with other developers
- 使你的构建具有可复制的特性,便于与其他开发者协作。
总的来说,package.json文件,描述了你的项目、项目依赖、依赖关系、依赖版本,以及带有一些配置信息来实现可复制的开发。
认识package.json字段
package.json
文件的字段并不是固定的个数,因为它可以包含来自第三方库、插件的配置字段。也就是说,package.json
文件的字段可以分为
- 官方字段
- 非官方字段
本文只介绍官方字段,至于非官方字段,依据字段所在的第三方库、插件的api文档自行查阅使用方法即可。
为了便于认识、理解、记忆package.json
的字段内容,我把整个官方文档的字段分为三大类:
- 信息类
- 配置类
- 依赖类
- 其他
如图所示:
package.json字段详解
信息类
name
,version
name and version together form an identifier that is assumed to be completely unique.
名称和版本共同组成了一个唯一的id。(供npm识别)
- name
平时名称可能起的非常随意,然而公司也肯定有公司的规范,一般来说遵循公司的命名规范不会触及npm规范的底线,然而给项目起名字,确确实实是有规则的:
1. <214个字符
2. 不可以以`.`或者`_`开头(除了域包)
3. 不可以包含大写字母
4. 不可以包含非-URL-安全的字符
这四个条规则是官方文档定义的命名规则,也都很好理解。而name
字段也会作为包名、以及require("")
的参数出现在相应的位置。
编辑器例如:vscode会对package.json文件的字段进行检查。而vscode对于命名错误时出现的提示为:满足^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$
该条正则。
事实上该条正则会在你使用了域的情况下以.
、_
开头的时候给出警告,但官方是允许这个写法的,所以不管编辑器如何,一切以官方文档为准,同时符合公司规范即可。
version
一个项目版本号,大致由三个部分组成(其实还有标签):
[major].[minor].[patch]
1. major
主要版本号,其递增表示了项目具有类似“模块重构”,“不兼容api的修改”的变动。
2. minor
次要版本号,其递增表示了项目进行了向下兼容的功能性新增。
3. patch
补丁号,其递增表示了项目修复了某些bug,解决了某些小的问题。(当然也必然是向下兼容的)
版本号的变动告知了使用者项目的更新以及迭代的内容,使用者以此来判断是否需要将依赖更新为新的版本。尤其对于组件开发者来说,语义化的版本控制尤为的重要。
keywords
, description
这两个字段主要是用来描述你的项目,其目的是为了SEO
(Search Engine Optimization —— 搜索引擎优化)
如果你在打算在npm上发布自己的项目,并且希望拥有使用的用户、希望其他开发者可以搜索到你开发的组件。那么就需要好好地填写这两个字段。
license
You should specify a licese for your package so that people know how they are permitted to use it, and any restrictions you're plcing on it.
为你的项目指定一个开源协议。该字段体现了你授权其他开发者使用你的代码的权限,包括不限于:拷贝、修改、使用、出售等。
常见的开源协议有:
不推荐商用
1. GPL
2. LGPL
3. MPL
可商用
1. BSD
2. MIT
3. Apache
最常见的就是MIT
协议,名称源自麻省理工大学(Massachusetts Insitute of Technology License)。
被授权人有权利使用、复制、修改、合并、出版发行、散布、再授权及贩售软体及软体的副本;可根据程式的需要修改授权条款为适当的内容;在软件和软件的所有副本中都必须包含版权声明和许可声明。
如果你不想授予任何人任何权限,可以指定UNLICENSED
。
开源协议的种类非常多,注册在案的可以用过spdx查阅。
同时可以在项目根目录指定一个license
文件:SEE LICENSE IN <filename>
author
, contrubutors
The "author" is one person, "contributors" is an array of people.
描述作者以及贡献者的信息。
1. name 名称
2. email 邮箱
3. url 相关网站地址
总结构上来看,author
包含这三个字段,而contributors
为该结构的一个数组。
而这三个字段也可以合并为一个字符串简写:
Your Name <email@example.com> (http://example.com)
homepage
, bugs
, repository
, funding
这四个字段主要内容都是一个网站地址,表达了不同的信息。
1. homepage
即项目主页地址
2. bugs
提交issue的地址,可以是单独的字符,也可以使用对象的结构。
{
url: string;
email?: string;
}
3. repository
代码存放的仓库地址
{
type: string;
url: stirng;
directory?: string;
}
其中,directory表示使用了域包时,相对于根目录的路径。
4.funding
捐赠地址。
{
type: string;
url: string;
}
配置类
files
The optional files field is an array of file patterns that describes the entries to be included when your package is installed as a dependency.
项目发布的时候包含的文件,可以是带有通配符的表达式。
可能项目发布时你会有很多不希望包含的文件,例如配置文件等。你可以仅仅把需要的文件写入该字段,其他文件会自动忽略。
-
默认包含的文件
- package.json
- README
- CHANGES / CHANGELOG / HISTORY
- LICENCE / LICENSE
- NOTICE
- file in "main" field
-
默认排除的文件
- .git
- .snv
- .DS_Store
- .npmrc
- npm-debug.log
- node_modules
- package-lock.json
- files contain "*" 字符
默认排除的文件其实还有几个,但前端开发会遇到的文件都在这里了。DS_Store
是mac文件夹相关的的系统文件。
可以使用.npmIgnore
或者.gitIgnore
来指定想要排除的文件。
files
字段里面所包含的文件,不会被.npmIgnore
和.gitIgnore
排除
如果项目根目录没有.npmIgnore
但是有.gitIgnore
,npm
也会使用.gitIgnore
文件
main
The main field is a module ID that is the primary entry point to your program.
项目的主入口文件。
使用者import
或者require
所导入的模块,便是main
字段指定的文件所默认导出的内容。
对于组件开发来说,main
指定的文件所导出的模块便是项目的主要模块。
scripts
The "scripts" property is a dictionary containing script command that are run at various times in the lifecycle of your package.
scripts
字段主要用来指定、编写脚本。
无论是内置的脚本,还是自定义的脚本,都拥有生命周期:
- pre
- post
官方默认脚本
- publish
- install / uninstall
- version
- test
- stop
- start / restart
即运行npm run start
的时候,会先后执行:prestart
, start
, poststart
。
脚本生命周期的意义在于自动化执行某些操作,例如在postinstall
中进行一些文件编译,环境搭建的工作,还可以防止遗漏这些工作。
编写npm脚本的时候需要注意:
- 不要写npm可以做的事情。
- 不要在指令中写
sudo
,获取管理员权限的操作不应该使用脚本完成。 - 不要书写
install
和preinstall
脚本。
另外可以使用双中划线--
来向npm脚本传参。
可以使用&&
和&
符号来继发/并发执行多个npm脚本
bin
a lot of packages have one or more executable files. bin is a map of command name to local file name.
bin用来指定可执行文件以及指令名称。
{
[commandName]: <local file name>
}
一般来说,可执行文件用于搭建项目的环境,或者快速生成一些模板文件提高效率。
如果只有一个需要执行的文件,并且指令名称就是项目的名称(name),那么可以只用一个文件路径字符来代替bin
字段的值。
config
, publishConfig
a "config" object can be used to set configuration parameters used in package scripts that persist across upgrades.
总体来说就是npm的配置信息,也可以写在.npmrc
文件中,影响npm的行为。
比较需要关注的就以下三个字段:
-
tag 标签,默认是
latest
,安装依赖时,不指定的情况下就是latest
最新版本。 -
registry npm包地址,可以指定为公司的私服地址。
-
access 开放类型,非域包默认为
public
,域包默认是私有的,设为public
也可以公开。
publishConfig
即发布时候的配置,完全替代config
。
依赖类
几种不同的依赖:
dependencies
生产依赖,生产环境下仍需要使用到的依赖。
devDependencies
开发依赖,仅在开发阶段需要使用到的依赖,例如webpack插件,css预处理语言等。
peerDependencies
同辈依赖。用来解决第三方和项目本身的共同依赖版本不同的问题。
npm3.0以前,安装依赖的行为方式有些不同。
例如A,B同时依赖C,那么主项目安装A和B的时候,C依赖会分别成为A和B的子依赖,在A、B目录下node_modules中存在。
而3.0以后npm会将C依赖安装在A和B的同级目录下,这样更好处理依赖关系。
而npm3.0
以后peerDependencies
中的依赖,npm不会主动安装,而是提示宿主环境去手动安装,以此来同步第三方和项目共同使用的依赖的版本。(即都使用宿主环境安装的依赖)
optionalDependencies
可选依赖,当可选依赖安装失败时不会导致错误,npm会继续运行,但需要手动处理错误情况。
可选依赖顾名思义是可有可无的,所以项目必须用到的依赖不可以放在这里。
还有一种使用场景:你的项目同时需要自己启动,以及作为别的项目的依赖,那么两种场景下必然有依赖的差异性。而optinoalDependencies
中的依赖可以使用--no--option
选项不安装。
bundleDependencies
打包依赖。在npm pack
的时候,该字段下的依赖会打包进tgz文件。(使用场景极其有限
版本控制
无论什么类型的依赖,在package.json
中,都需要指定他的版本,以此来确保项目所使用的依赖版本都是正确的,不会导致程序崩溃。
而版本控制会通过一些前导符号来指定,具体的细节可以查阅相关网站node-semver。
语义化版本控制:
-
^ 表示大于等于当前版本,并允许
minor
级别的递增。 -
~ 表示大于等于当前版本,并允许
patch
级别的递增。 -
> / >= 表示大于/大于等于当前版本即可。
-
< / <= 表示小于/小于等于当前版本即可。
-
- 表示两个版本范围之间,并包括两个版本。(闭区间)
-
x 可以在
major
,minor
,patch
任意位置,表示任何数字。 -
|| 表示或,任意版本或版本范围满足其一。
-
预发布标签 alpha, beta, release, rc等。
需要注意的是,主版本为0版本号规则与其他稍有不同
通常在组件开发期间,以0.1.0
作为初始版本号,任何major
级别的修改,均递增第二位,minor
位置的数字。直到整个项目有一个稳定可公开的版本时,将版本重置为1.0.0
,随后按照正常规则进行迭代即可。
所以0开头的版本在版本控制中,~
表示主要版本的迭代,包含不可兼容的修改。
others
其他字段都是一些并不常用,只需要了解,不需要过于关注的字段。使用场景非常有限,即便真的遇到了需要使用的场景,查阅npm文档即可。
- private
防止意外发布的手动,设置为true,npm
会阻止发布。
- engines
可以用来指定node
和npm
的版本。
- borwser
面向客户端的项目可以指定这个字段来代替main
- directories
描述项目的目录结构,功能仍未完善。
- man
- os
- cpu
后记
所有的官方字段都已经在上面做了详细地介绍,包括一些使用场景和注意事项。(已去除官方文档设为deprecated字段)对于npm官方字段来说,清楚地了解以上这些字段的含义和作用后,也可以一定程度上在出现一些问题的情况下,拥有迅速解决问题的能力。同时也能够更好的理解我们前端开发所离不开的工具 —— node package manager
的行为。
更多的配置信息,CLI的相关api,皆可以再官方文档中查询到。npm
的文档也进行了更新,可读性比以前更加好。阅读官方文档是一个好的习惯,同时也有助于提升英语阅读的能力。