package.json基础

认识 package.json

WebStrom 中创建 Node.js 项目后,会默认生成一个 package.json 文件,如图3.3所示。

package.json 文件是项目的清单文件,其中可以做很多完全互不相关的事情。例如,图3.3中的 package.json 文件主要用来对项目进行配置,而在 npm 安装目录中,同样有一个 package.json 文件,存储了所有已安装软件包的名称和版本等信息。

image 2024 04 08 22 26 12 638
Figure 1. 图3.3 创建 Node.js 项目后默认生成的 package.json 文件

对于 Node.js 程序,package.json 文件中的内容没有固定要求,唯一的要求是必须遵守 JSON 格式,否则,尝试以编程的方式访问其属性的程序会无法读取它。

创建 Node.js 项目时默认生成的 package.json 文件如下:

{
   "name": "nodepro",
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
   "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
   },
   "keywords": [],
   "author": "",
   "license": "ISC"
}

上面的代码中包含很多属性,具体说明如下。

  • name:应用程序或软件包的名称。名称必须少于 214 个字符,且不能包含空格,只能包含小写字母、连字符(-)或下画线(_)。

  • version:当前的版本,该属性的值遵循语义版本控制法,这意味着版本始终以 3 个数字表示—x.x.x,其中,第一个数字是主版本号,第二个数字是次版本号,第三个数字是补丁版本号。

  • description:应用程序/软件包的简短描述。如果要将软件包发布到 npm,则这个属性特别有用,使用者可以知道该软件包的具体作用。

  • main:设置应用程序的入口点。

  • scripts:定义一组可以运行的 Node.js 脚本,这些脚本是命令行应用程序。可以通过调用 npm run XXXXyarn XXXX 来运行它们,其中的 XXXX 是命令的名称。例如 npm run dev

  • keywords:包含与软件包功能相关的关键字数组。

  • author:列出软件包的作者名称。

  • license:指定软件包的许可证。

除了上面列出的属性,package.json 文件中还支持其他的很多属性,常用的如下。

  • contributors:除作者外,该项目可以有一个或多个贡献者,此属性是列出他们的数组。

  • bugs:链接到软件包的问题跟踪器,最常用的是 GitHub 的 issues 页面。

  • homepage:设置软件包的主页。

  • repository:指定程序包仓库所在的位置。例如:

    "repository": "github:nodejscn/node-api-cn",

    上面的 github 前缀表示 github 仓库,其他流行的仓库还包括:

    "repository": "gitlab:nodejscn/node-api-cn",
    "repository": "bitbucket:nodejscn/node-api-cn",

    开发人员可以显式地通过该属性设置版本控制系统,例如:

    "repository": {
         "type": "git",
         "url": "https://github.com/nodejscn/node-api-cn.git"
    }

    也可以使用其他的版本控制系统:

    "repository": {
         "type": "svn",
         "url": "..."
    }
  • private:如果设置为 true,则可以防止应用程序/软件包被意外发布到 npm 上。

  • dependencies:设置作为依赖安装的 npm 软件包的列表。当使用 npmyarn 安装软件包时,该软件包会被自动插入此列表中。

  • devDependencies:设置作为开发依赖安装的 npm 软件包的列表。它们不同于 dependencies,因为它们只需安装在开发机器上,而无须在生产环境中运行代码。当使用 npmyarn 安装软件包时,该软件包会被自动地插入此列表中。

  • engines:设置软件包/应用程序要运行的 Node.js 或其他命令的版本。

  • browserslist:用于告知要支持哪些浏览器(及其版本)。

npm 中的 package-lock.json 文件

npm5 以上的版本中,引入了 package-lock.json 文件,该文件旨在跟踪被安装的每个软件包的确切版本,以便产品可以以相同的方式被 100% 复制(即使软件包的维护者更新了软件包)。

package-lock.json 文件的出现解决了 package.json 一直存在的特殊问题,在 package.json 中,可以使用 semver(语义化版本)表示法设置要升级到的版本(补丁版本或次版本),例如:

  • 如果写入的是 ~0.13.0,则只更新补丁版本:即 0.13.1 可以,但 0.14.0 不可以。

  • 如果写入的是 ^0.13.0,则要更新补丁版本和次版本:即 0.13.1、0.14.0……以此类推。

  • 如果写入的是 0.13.0,则始终使用确切的版本。

无须将 node_modules 文件夹(该文件夹通常很大)提交到 Git,当尝试使用 npm install 命令在另一台机器上复制项目时,如果指定了 ~ 语法并且软件包发布了补丁版本,则该补丁版本会被安装,^ 语法中的次版本也一样。

如果指定确切的版本,例如示例中的 0.13.0,则不会受到此问题的影响。

这时如果多个人在不同时间获取同一个项目,使用 npm install 安装时,有可能安装的依赖包版本不同,这样可能会给程序带来不可预知的错误。而通过使用 package-lock.json 文件,可以固化当前安装的每个软件包的版本,当运行 npm install 时,npm 会使用这些确切的版本,确保每个人在任何时间安装的版本都是一致的,从而避免使用 package.json 文件时可能出现的版本不同问题。

例如,在 package.json 文件中有如下属性:

"express": "^4.15.4"

在只有 package.json 文件时,如果后续出现了 4.15.5 版本、4.15.6 版本等,则有可能每个人安装的依赖包就会不同,从而导致一些未知的兼容性问题。这时如果使用 package-lock.json 文件,则文件中的内容可以设置如下:

"express": {
     "version": "4.15.4",
     "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz",
     "integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=",
     "requires": {
          "accepts": "1.3.3",
          "array-flatten": "1.1.1",
          "content-disposition": "0.5.2",
          "content-type": "1.0.2",
          "cookie": "0.3.1",
          "cookie-signature": "1.0.6",
          "debug": "2.6.8",
          "depd": "1.1.1",
          "encodeurl": "1.0.1",
          "escape-html": "1.0.3",
          "etag": "1.8.0",
          "finalhandler": "1.0.4",
          "fresh": "0.5.0",
          "merge-descriptors": "1.0.1",
          "methods": "1.1.2",
          "on-finished": "2.3.0",
          "parseurl": "1.3.1",
          "path-to-regexp": "0.1.7",
          "proxy-addr": "1.1.5",
          "qs": "6.5.0",
          "range-parser": "1.2.0",
          "send": "0.15.4",
          "serve-static": "1.12.4",
          "setprototypeof": "1.0.3",
          "statuses": "1.3.1",
          "type-is": "1.6.15",
          "utils-merge": "1.0.0",
          "vary": "1.1.1"
    }
},

上面的代码中,由于在 package-lock.json 文件中使用了校验软件包的 integrity 散列值,这样就可以保证所有人在任何时间安装的依赖包的版本都是一致的。

在使用 package-lock.json 文件时,需要将其提交到 Git 仓库,以便被其他人获取(如果项目是公开的或有合作者,或者将 Git 作为部署源),这样,在运行 npm update 时,package-lock.json 文件中的依赖版本就会被更新。