package-lock.json 引起 "Error: Cannot find module node:fs"

2,372 阅读3分钟

一次线上事故

Nuxt 官网项目,线上启动时,报错 Error: Cannot find module node:fs,确立怀疑:一是发版问题,二是环境不匹配,三是 jenkins 构建文件的问题,四是本地电脑的问题。

提示:由于项目较简单,直接走生产环境,本地开发 => jenkins 构建 => 传输文件至线上服务器 => npm install 安装依赖包 => 启动 docker 容器运行。线上官网文件夹包含 .nuxt 文件夹(打包文件)、static 文件夹(静态文件)、package.json、nuxt.config.js(配置文件),然后作为数据卷(volume)挂载到 docker 容器,启动时运行 npm start

  1. 回退多个版本后,查看日志,报错信息相同,排除怀疑一(发版问题)
  2. 对比 node 和 npm 版本,开发、jenkins、线上三个环境版本一致,排除怀疑二(环境问题)
  3. 拉取线上文件夹,本地 npm i,启动运行,同样报错
  4. 测试服务器重复步骤 2,报错信息相同,可能是怀疑三(jenkins 问题)
  5. 本地 npm build 打包项目,根据线上文件夹内容,提取.nuxt 文件夹、static 文件夹、package-lock.json,package.json、nuxt.config.js 组成测试文件
  6. 测试文件夹经过本地电脑、测试服务器,皆可运行
  7. 等等,有些不对劲,盲生你发现华点啦 😆, package-lock.json ???
  8. 线上文件夹的 package-lock.json 替换成测试文件夹的,重新启动——成功 🥳

重点来了,👨‍🏫 敲黑板:

official description:package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.
官方解释:对于 npm 修改 node_modules 树或 package.json 的任何操作,都会自动生成(更新) package-lock.json。package-lock.json 描述了根据安装包生成的完整依赖树,以便后续安装能够生成相同的树,无需考虑中间的依赖关系更新。
简单来说就是,package-lock.json 文件锁定了依赖安装结构,保证在任意机器和环境上执行 npm install 都会得到完全相同的 node_modules。

package-lock.json 文件提交到源存储库中(官方推荐),可用于各种目的:

  • 描述依赖关系树的单一表示,以确保团队成员、部署和持续集成能够安装完全相同的依赖。
  • 可以回溯 node_module 树先前的状态,而不必提交 node_module 目录本身。
  • 通过差异文件(diffs),提升 node_module 树更改的可见性。
  • 允许 npm 跳过先前安装包的重复元数据的解析,优化安装过程。
  • 从 npm v7 开始,lockfile(npm 中用的是 package-lock.json,yarn 中用的是 yarn.lock)包含了足够的信息来获取树的完整描述,减少了读取 package.json 文件的需要,从而显著提高性能。

package-lock.json 生成

早期 npm 锁定版本的方式使用 npm-shrinkwrap.json,package-lock.json 是 npm v5.x 新增特性,npm v5.6 以上逐步稳定,在 5.0-5.6 中间 npm install 的规则进行了三次更新。

  • npm v5.x 版本,无论 package.json 文件如何改变,npm install 根据 package-lock.json 文件下载 npm 包。
  • npm v5.1.0 版本到 npm v5.4.2,无视 package-lock.json 文件,下载最新的 npm 包并更新 package-lock.json 文件。
  • npm 5.4.2 版本后:
    • 项目只有 package.json 文件,npm install 后生成一个 package-lock.json 文件。
    • 项目中存在 package.json 和 package-lock.json 文件,同时 package.json 文件的 semver-range 版本 (早期为了解决「依赖地狱」的问题,Github 起草了一个具有指导意义的,统一的版本号表示规则,称为 Semantic Versioning(语义化版本),即 Semver,目前由 npm 的团队维护,可参考底部文章👇)和 package-lock.json 中版本兼容,即使此时有新的适用版本,npm install 时会根据 package-lock.json 进行更新。
    • 项目存在 package.json 和 package-lock.json 文件,同时 package.json 文件的 semver-range 版本和 package-lock.json 中版本不兼容,npm install 时会将其更新到兼容 package.json 的版本。
    • 项目根目录同时存在 package-lock.json 和 npm-shrinkwrap.json ,package-lock.json 会被忽略。

package-lock.json 格式

package-lock.json 是一个包含你所有依赖的树状结构列表, 包含固定的版本号, 依赖的获取地址, 一个用于验证完整性和正确性的哈希值等等,具体参数信息可查看官方文档

参考文章