深入理解 package.json:前端项目的 "身份证"

前言

每一个 Node.js 项目都绕不开一个文件------package.json

它像项目的"身份证",又像"瑞士军刀":

  • 告诉 npm 你是谁(name、version、license)
  • 告诉打包器 怎么引入你(main、module、exports)
  • 告诉 CI 怎么测试你(scripts.test)
  • 告诉用户 怎么使用你(bin、scripts、dependencies)

本文用"渐进式"结构,带你从最小可运行 一路到企业级开源库所需的全部字段与技巧。读完可以:

  1. 手写零报错 package.json
  2. 正确拆分 dependenciespeerDependencies
  3. 让 webpack/vite/Node 同时识别你的库
  4. 避免 90% 的"为什么本地能跑,一发包就崩"

1. 最小可运行版本(MVP)

新建文件夹,执行 npm init -y,得到:

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

即可:

  • node index.js 运行
  • npm test 触发脚本

但离"能用"还差 3 件事:

  1. license 换成 SPDX 标准标识(MIT / Apache-2.0
  2. "private": true,防止误发 npm
  3. 删除无用字段,保留核心 6 项:
json 复制代码
{
  "name": "demo",
  "version": "1.0.0",
  "main": "index.js",
  "private": true,
  "scripts": {
    "start": "node index.js"
  },
  "license": "MIT"
}

2. 依赖管理三板斧

场景 命令 写入字段 例子
生产依赖 npm i lodash dependencies "lodash": "^4.17.21"
开发依赖 npm i -D vite devDependencies "vite": "^5.0.0"
宿主依赖 手动写 peerDependencies "react": ">=18.0.0"

口诀

下游需要运行 → dependencies

只是构建/测试 → devDependencies

防止多实例 → peerDependencies

踩坑

  • peerDependencies 版本范围过严会导致用户无法安装!
    ✅ 正确:">=16.8.0"
    ❌ 错误:"16.8.0"(只允许 exact 版本)

3. 脚本进阶:一条命令跑完开发全流程

json 复制代码
"scripts": {
  "dev": "vite",
  "build": "tsc && vite build",
  "test": "vitest",
  "lint": "eslint . --ext .ts,.tsx",
  "lint:fix": "eslint . --ext .ts,.tsx --fix",
  "prepare": "husky install",
  "prepublishOnly": "npm run build && npm test"
}

生命周期图解:

arduino 复制代码
npm install → 触发 prepare → 自动装 husky 钩子  
npm publish → 触发 prepublishOnly → 保证发布的是 dist 产物

跨平台兼容

json 复制代码
"build": "cross-env NODE_ENV=production tsc && vite build"

4. 让三方库正确引入你:main vs module vs exports

字段 历史地位 适用场景 备注
main CommonJS 时代 老项目兼容 仅支持单一路径
module 社区约定 ESM 打包工具 无官方标准
exports Node 12+ 官方 统一替代上面两项 支持条件导出、子路径

现代库模板:

json 复制代码
{
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    },
    "./utils": {
      "types": "./dist/utils.d.ts",
      "import": "./dist/utils.mjs",
      "require": "./dist/utils.cjs"
    }
  }
}

收益:

  • import {} from 'your-lib/utils' 直接子路径
  • 用户 CommonJS / ESM 均可使用
  • TypeScript 提示不丢失

5. 发布配置:让包体积瘦身 70%

json 复制代码
{
  "files": ["dist", "README.md", "LICENSE"],
  "sideEffects": false,
  "publishConfig": {
    "registry": "https://registry.npmjs.org",
    "access": "public"
  }
}
  • files 白名单:防止把源码、测试、脚本发到 npm
  • sideEffects: false 告诉 webpack 可以摇树优化
  • 公司内网发布:registry 指向私有 Verdaccio / Nexus

6. 企业级开源库 checklist

步骤 工具 / 字段 命令
1. 版本号合规 SemVer npm version patch
2. 依赖漏洞扫描 npm audit npm audit fix
3. 声明 Node 版本 engines { "node": ">=18.0.0" }
4. 协议合规 license npx license-checker
5. 自动化发布 GitHub Actions npm publish 在 CI 触发

示例 CI 片段(.github/workflows/publish.yml):

yaml 复制代码
- name: Publish
  if: github.ref == 'refs/heads/main'
  run: |
    npm config set //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}
    npm publish

7. 可视化总结:一张思维导图

(文字版)

java 复制代码
package.json
├─ 元信息(name、version、license、private)
├─ 依赖(dependencies / dev / peer / optional)
├─ 脚本(scripts + 生命周期)
├─ 入口(main → module → exports 渐进)
├─ 发布(files、sideEffects、publishConfig)
└─ 约束(engines、os、cpu)

8. 常见报错速查表

报错 原因 快速修复
Cannot find module 'xxx' 忘了把 dist 加入 files files:["dist"]
Multiple versions of React reactdependencies peerDependencies
npm WARN deprecated xxx 依赖版本过老 npx npm-check-updates -u
403 Forbidden on publish 包名冲突或未登录 换名 / npm login

9. 结语

package.json 很小,却贯穿了 Node.js 项目的全生命周期:

开发 → 测试 → 构建 → 发布 → 依赖治理。

掌握它,你就拥有了:

  • 更小的包体积
  • 更快的安装速度
  • 更少的"在我电脑能跑"事故

把本文 checklist 保存为备忘录,下次新建项目直接套用,即可一步到位。

Happy coding!


10. 附录:模板仓库

GitHub 搜 npm-lib-boilerplate-2025,已集成:

  • TypeScript + Vite + Vitest
  • GitHub Actions 自动发布
  • husky + lint-staged 代码检查
  • 示例 package.json 与本文明细 100% 对应

克隆即可开始你的下一个开源库。

相关推荐
StarkCoder3 小时前
GetX 状态管理优化:从 GetBuilder 到 Obx 的性能提升实践
前端
StarkCoder3 小时前
Flutter ListView 数据变动导致的卡顿与跳动问题:Key 的妙用
前端
lichenyang4533 小时前
Next.js 学习笔记:从约定式路由到 Tailwind、Image、Font 优雅整合。
前端·javascript·全栈
杂鱼豆腐人3 小时前
【自用】CSS查漏补缺
前端·css
修罗-zero3 小时前
vue在获取某一个div的大小,怎么确保div渲染好,内容撑开后才去获取大小
前端·javascript·vue.js
咫尺的梦想0073 小时前
vue笔记(第一天)
前端·vue.js·笔记
zhougl9963 小时前
NoSQL 数据库和内存数据库 - MongoDB简单了解
java·前端·javascript
爱学习的马喽3 小时前
React钩子函数完全指南:从useState到useEffect的实战详解与场景剖析
前端·javascript·react.js
abigale033 小时前
开发实战 - ego商城 - 7 地址管理模块
前端·uni-app·node.js