Nodejs开发进阶I-Package.json

本文是《Nodejs开发进阶G-部署和管理》的一个组成部分,由于篇幅和内容的限制,分离出来独立成文。

概述

一个包含js文件和node_modules文件夹的普通的操作系统文件夹,之所以成其为一个nodejs项目,是因为有了一个package.json文件,它就是nodejs项目的控制和配置文件。它的角色和功能是如此重要,每个nodejs开发者都应该熟悉和掌握。

这个文件的扩展名清晰的表明,这是一个json格式文本文件,这意味着它可以承载层次化和结构化的信息和数据;另外,json简单的编码和组织形式,让程序和真人,都可以方便的阅读和管理(想象一下XML和Protobuf?);这些特性为其扩展和应用提供了很大的灵活性。package的文件名,表明它的主要功用就是描述和控制当前这个软件包。

这里吐槽一下,当初设计JSON的时候,好像只考虑了它用来数据和信息结构,并没有考虑到它被应用的如此广泛,甚至用在程序当中,就缺少了一个非常重要的特性:注释信息。当然这个可以通过在其中随便增加一个无效的key来解决,当显然在加载和处理时,会增加一些额外的工作和资源。

结构和内容

package.json文件,通常是在创建nodejs项目时,使用npm init命令创建的。实际上,开发者完全可以使用标准编辑程序,安装格式规范从空白开始编写一个package.json文件,都是没有问题的,它本质上就是一个JSON格式的纯文本文件。

我们可以使用任意一个文本编辑器,甚至linux的nano编辑命令,打开任意一个nodejs项目的package.json。都可以看到类似下面的内容:

shell 复制代码
$ nano package.json:
{
  "name": "ntest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

这个文件的项目有一定的规范,一般的项目名称都是很好理解的,常见的可能需要管理和编辑的项目包括:

  • 名称: 当前nodejs项目名称,这在需要发布为npm时非常重要
  • 版本: 项目版本,也是npm版本
  • 描述信息: 当前这个项目的描述和注释信息
  • main: 主程序入口,这就是可以使用node . 执行程序的原因
  • scripts: 通过这个配置信息,可以使用npm来执行,如这里就是npm test .
  • keywords: npm发布和搜索时有用
  • author: 作者
  • license: 许可证类型,常用的开源协议有ISC、MIT等等,只有法律意义

上面这些内容,是项目初始化时,使用npm init命令生成时,默认的内容。后续有一些相关的操作,可能会创建一些新的项目,甚至开发者可以按照规范,自己编辑一些项目,来达到项目控制的目的。

package.json规范完整的内容,和很多相关技术细节,可以参考npm的技术文档如下。

docs.npmjs.com/cli/v10/con...

下面我们例举几个常用的项目。

dependencies 依赖

在一个一般或者稍微有点规模的nodejs项目中,package.json中,最重要的一个项目,就是项目依赖软件包集合(dependencies)了,下面是笔者的一个nodejs项目package.json中的依赖项目:

package.json 复制代码
  ...
  "dependencies": {
    "@fastify/cors": "^8.1.0",
    "@fastify/formbody": "^7.0.1",
    "@fastify/multipart": "^7.1.0",
    "@fidm/x509": "^1.2.1",
    "async": "^3.2.2",
    "autocannon": "^7.5.1",
    "cbor": "^8.1.0",
    "crc": "^3.8.0",
    "eta": "^1.12.3",
    "fastify": "^4.5.2",
    "fastify-socket.io": "^4.0.0",
    "got": "^12.5.3",
    "iso-3166-1": "^2.1.1",
    "minio": "^7.1.3",
    "pg": "^8.7.1",
    "pg-cursor": "^2.7.1",
    "pg-notify": "^0.0.19",
    "pump": "^3.0.0",
    "qrcode-svg": "^1.1.0",
    "redis": "^4.0.1",
    "socket.io": "^4.4.0",
    "socket.io-client": "^4.4.0",
    "svg-captcha": "^1.4.0",
    "unzipper": "^0.10.11"
  }
  

我们看到dependencies在package.json中,是一个对象。对象的key就是软件包的名称,而对象的值,是这个项目中当前使用的这个软件包的版本。一般情况下,npm会试图搜索当前可用的最新版本来安装。很多大型的软件包,还会进行模块化,分为很多小的软件包,减少无效的依赖和磁盘空间,使安装和部署更加精简灵活。

这里面我们还看到很多应用比较广泛的项目,包括pg用于数据库、fastify用于Web框架、socket.io是WebSocket模块等等。

开发模式

一般的npm软件包,在nodejs项目中,使用--save标签,成功安装完成后,可以在dependencies中,建立对应的依赖项目。但我们知道,在开发和部署阶段,我们使用的工具和软件包可能不完全相同。这时npm提供了--save-dev标签,它可以指定这个软件包是使用开发或者测试模式安装的。

在实际操作中,它也会按照正常方式来安装这些npm包。但它会在package.json中,建立另外一个devDependencies的项目,来容纳这些内容。在实际的生产部署环境中,需要指定作为生产环境,则这些项目,将不会被npm install命令自动安装,如下:

NODE_ENV=production npm install

开发模式使用的软件包,通常包括这么几类:

  • 测试工具或者框架
  • 构建工具
  • 代码检查工具
  • 开发支持工具

关于软件包依赖,package.json还有peerDependencies,bundleDependencies,optionalDependencies等等,这些笔者尚未有机会接触或者使用,如果哪位读者有相关经验和想法,也可以反馈给笔者或者写个技术文章分享一下。

npm脚本

npm不仅仅是可以用于管理软件包和依赖关系,还可以提高一些开发工程方面的特性。例如,在package.json中,可以定义一个scripts对象,然后结合一致的npm run 命令,来执行一些开发过程中的任务和操作。这些脚本通常被称为npm script。 我们来看一些示例:

js 复制代码
// package.json内容
{
  "scripts": {
    "start": "node server.js",
    "test": "jest",
    "build": "webpack"
  }
}


// 对应npm操作
npm run start // 执行node程序
npm run test  // 执行测试程序
npm run build // 执行建构和编译

这些脚本是完全可自定义的,因为它们就是可以在shell环境中执行的命令,但npm脚本将它们的使用方式简化并且一致了。笔者认为,npm脚本本质上是软件开发工程的一个最佳实践,可以使软件开发的过程和管理更加规范和一致,有利于对软件开发过程的效率和质量进行有效的保证。

pakage-lock.json

在npm5及更新的版本之后,它为nodejs项目,引入了一个新的特性,用来解决一些版本管理不稳定造成的问题。这个特性的表现,就是使用了一个新的项目相关的配置文件: package-lock.json。从这个名字,我们大致可以理解,它是通过版本锁定的方式,来实现相对固定的版本依赖和稳定关系的。

这个文件配合npm的功能特性,可以实现以下一些作用:

  • 版本锁定

这个机制可以确保在不同的开发环境中,使用相同的软件包版本。它会精确记录每个安装的软件包及其依赖项的确切版本号。这样一来当项目进行移植或者重置时,可以确保使用相同的软件包版本,避免重新安装时软件包版本和配置不一致的问题。

  • 确保可再现性

在协作开发和持续集成环境中,确保每个团队成员和构建服务器都使用相同的软件包版本非常重要。package-lock.json 的存在可以确保项目的可再现性,即使在不同的开发环境或时间点。

  • 加速安装:

package-lock机制可以加速软件包的安装。通过记录确切的版本信息,npm在安装过程中可以直接下载软件包的特定版本,而无需进行版本解析和查询。这提高了安装速度并减少了网络请求。

  • 减少环境差异造成的问题:

在没有 package-lock机制时,不同的环境可能会因为 npm 的版本、软件包的新发布等原因导致不一致的依赖关系,进而引发一些问题。引入版本锁定可以有效减少这类问题。

总体而言,引入package-lock可以提高npm项目的稳定性、可重复性,以及确保团队协作和持续集成中的一致性。在开发实践中,也建议将package-lock.json文件纳入版本控制系统,以确保项目的所有开发者都使用相同的依赖版本。

例如,笔者的一个项目中,package-lock.json的文件内容,可能是这样的:

package-lock.json 复制代码
{
  "name": "ftest",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "ftest",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "fastify": "^3.22.0",
        "gm": "^1.23.1",
        "jimp": "^0.16.1"
      }
    },
    "node_modules/@babel/runtime": {
      "version": "7.15.4",
      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz",
      "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==",
      "dependencies": {
        "regenerator-runtime": "^0.13.4"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    ...

另外需要注意,一般情况下,这个文件不需要,也不建议开发者进行手工的管理和编辑。它的修改,都是在npm的相关操作中自动进行的。

程序引用

在程序中,可以引用package.json中的项目,来实现一些运维管理甚至业务方面的功能。比如笔者经常使用package来获得版本号,展示在API或者页面中,方便运维工作中的故障排查。

引用package.json中的信息也非常简单,就是直接require就可以了:

js 复制代码
const package = require("./package");

console.log(package.name,package.version);

小结

本文讨论了nodejs项目的核心配置文件,package.json相关的内容。这些内容包括package.json的基本结构,主要项目,并重点讨论了其中的依赖对象、脚本对象、依赖锁定等特性。笔者觉得,更好的了解和理解package.json和相关的管理机制,对于开发过程和开发项目的有效管理,是非常有帮助的。

相关推荐
长天一色7 分钟前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_23425 分钟前
npm、yarn、pnpm之间的区别
前端·npm·node.js
NiNg_1_23427 分钟前
Vue3 Pinia持久化存储
开发语言·javascript·ecmascript
读心悦29 分钟前
如何在 Axios 中封装事件中心EventEmitter
javascript·http
千里码aicood43 分钟前
【2025】springboot教学评价管理系统(源码+文档+调试+答疑)
java·spring boot·后端·教学管理系统
神之王楠1 小时前
如何通过js加载css和html
javascript·css·html
余生H1 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍1 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
流烟默1 小时前
Vue中watch监听属性的一些应用总结
前端·javascript·vue.js·watch
liuxin334455661 小时前
教育技术革新:SpringBoot在线教育系统开发
数据库·spring boot·后端