每个前端项目的根目录下几乎都有一个
package.json,但你真的了解它的每个字段吗?本文将从基础字段 到高级配置 ,逐一拆解package.json中的所有字段,帮你彻底搞懂它。
一、必填字段
1.1 name --- 包名
json
{
"name": "@packageName/sdk"
}
规则:
- 长度不超过 214 个字符
- 不能以
.或_开头 - 不能包含大写字母
- 不能包含 URL 不安全字符(如空格、
~等) - 支持 scope (作用域),格式为
@scope/name,常用于组织级别的包管理,例如@vue/cli、@babel/core
作用:
name 是包的唯一标识符。当你执行 npm install xxx 时,xxx 就是这个字段的值。配合 version,它们共同构成了包的"身份证"。
1.2 version --- 版本号
json
{
"version": "1.6.7"
}
必须遵循 Semantic Versioning(语义化版本) 规范,格式为 MAJOR.MINOR.PATCH:
| 位 | 含义 | 示例场景 |
|---|---|---|
MAJOR |
不兼容的 API 变更 | 重构了核心 API |
MINOR |
向下兼容的功能新增 | 新增了一个工具函数 |
PATCH |
向下兼容的问题修复 | 修复了一个边界 Bug |
还支持预发布标签:1.0.0-alpha.1、1.0.0-beta.2、1.0.0-rc.1
二、描述信息字段
2.1 description --- 包描述
json
{
"description": "packageDescription"
}
简短描述包的功能,会展示在 npm search 的搜索结果中,也是 npm 官网搜索排序的权重因子之一。
2.2 keywords --- 关键词
json
{
"keywords": ["cloud", "sdk", "vue", "plugin", "micro-frontend"]
}
字符串数组,用于 npm 官网的搜索优化(SEO),帮助其他开发者更快找到你的包。
2.3 homepage --- 项目主页
json
{
"homepage": "https://github.com/user/project#readme"
}
项目官网或文档地址,会展示在 npm 包详情页的侧边栏。
2.4 bugs --- Bug 反馈地址
json
{
"bugs": {
"url": "https://github.com/user/project/issues",
"email": "bugs@example.com"
}
}
也可以简写为字符串:"bugs": "https://github.com/user/project/issues"。
2.5 license --- 开源协议
json
{
"license": "MIT"
}
常见协议:
| 协议 | 特点 |
|---|---|
MIT |
极其宽松,几乎无限制 |
Apache-2.0 |
允许商用,需保留版权,提供专利许可 |
GPL-3.0 |
传染性协议,衍生作品也需开源 |
ISC |
类似 MIT,更简洁 |
UNLICENSED |
私有包,不允许他人使用 |
2.6 author --- 作者
json
{
"author": {
"name": "张三",
"email": "zhangsan@example.com",
"url": "https://zhangsan.dev"
}
}
也支持简写形式:"author": "张三 <zhangsan@example.com> (https://zhangsan.dev)"
2.7 contributors --- 贡献者
json
{
"contributors": [
{ "name": "李四", "email": "lisi@example.com" },
"王五 <wangwu@example.com>"
]
}
格式同 author,是一个数组。
2.8 funding --- 赞助信息
json
{
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/project"
}
}
也支持数组形式,用于声明多个赞助渠道。执行 npm fund 可查看项目的赞助信息。
三、入口文件字段
这是 package.json 中最核心也最容易混淆的一组字段,直接决定了别人引用你的包时,加载的是哪个文件。
3.1 main --- CommonJS 入口
json
{
"main": "dist/cloud-sdk.umd.js"
}
作用:
Node.js 和旧版打包工具默认读取的入口。当执行 require('your-package') 时,实际加载的就是 main 指向的文件。
3.2 module --- ESModule 入口
json
{
"module": "dist/cloud-sdk.esm.js"
}
作用:
这不是 Node.js 官方字段,而是由打包工具(Webpack、Rollup、Vite)约定的。当打包工具发现 module 字段时,会优先使用它,因为 ESM 格式支持 Tree Shaking,能有效减小打包体积。
3.3 browser --- 浏览器入口
json
{
"browser": "dist/cloud-sdk.browser.js"
}
当包需要在浏览器中运行,且浏览器版本与 Node 版本实现不同时使用。打包工具在构建浏览器端代码时会优先读取此字段。
也支持对象形式,用于替换特定模块:
json
{
"browser": {
"./lib/server-utils.js": "./lib/browser-utils.js",
"fs": false
}
}
3.4 types / typings --- TypeScript 类型入口
json
{
"types": "dist/index.d.ts"
}
指定 TypeScript 类型声明文件的入口路径。types 和 typings 等价,推荐用 types。
3.5 exports --- 条件导出(重点!)
json
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/cloud-sdk.esm.js",
"require": "./dist/cloud-sdk.umd.js"
},
"./utils": {
"types": "./dist/utils.d.ts",
"import": "./dist/utils.esm.js",
"require": "./dist/utils.cjs.js"
}
}
}
这是 Node.js 12.11+ 引入的现代模块解析方案 ,是 main、module、browser 的"终极替代方案"。
核心能力:
| 特性 | 说明 |
|---|---|
| 条件导出 | 根据环境(import / require / node / browser / default)返回不同文件 |
| 子路径导出 | 允许 import { foo } from 'pkg/utils' 形式的子路径引用 |
| 封装隔离 | 未在 exports 中声明的路径,外部无法访问,保护内部实现 |
条件匹配的优先级(从上到下):
json
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"node": {
"import": "./dist/node.mjs",
"require": "./dist/node.cjs"
},
"browser": "./dist/browser.js",
"default": "./dist/index.js"
}
}
}
注意:
types条件必须放在最前面,否则 TypeScript 可能无法正确解析类型。
3.6 type --- 模块系统声明
json
{
"type": "module"
}
| 值 | 含义 |
|---|---|
"module" |
.js 文件默认作为 ESModule 处理 |
"commonjs"(默认值) |
.js 文件默认作为 CommonJS 处理 |
设置为 "module" 后:
.js→ ESM.cjs→ CommonJS(强制).mjs→ ESM(强制)
四、文件管控字段
4.1 files --- 发布包含的文件
json
{
"files": ["dist", "README.md", "LICENSE"]
}
白名单机制 ,指定 npm publish 时需要包含的文件和目录。类似 .gitignore 的反向操作。
始终包含的文件(无法排除):
package.jsonREADME(任何大小写和扩展名)LICENSE/LICENCECHANGELOGmain字段指向的文件
始终排除的文件(无法包含):
.gitnode_modules.npmrcpackage-lock.json
技巧: 也可以用
.npmignore做黑名单控制,但files字段优先级更高,两者同时存在时以files为准。
4.2 directories --- 项目目录结构
json
{
"directories": {
"lib": "src/lib",
"bin": "bin",
"man": "man",
"doc": "docs",
"example": "examples",
"test": "test"
}
}
声明项目的目录结构。实际使用较少,主要是一种语义化描述。
五、脚本与命令字段
5.1 scripts --- NPM 脚本
json
{
"scripts": {
"dev": "vite build --watch",
"build": "vite build",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"format": "prettier --write src",
"prepare": "husky install",
"preinstall": "npx only-allow pnpm"
}
}
通过 npm run <script-name> 执行。部分脚本名有特殊含义:
生命周期脚本:
| 脚本名 | 触发时机 |
|---|---|
preinstall |
安装依赖之前执行 |
install |
安装依赖时执行 |
postinstall |
安装依赖之后执行 |
prepare |
npm install 之后、npm publish 之前执行 |
prepublishOnly |
仅在 npm publish 之前执行 |
prepack |
打 tarball 之前(npm pack / npm publish) |
postpack |
打 tarball 之后 |
pre/post 钩子:
任何自定义脚本都可以加 pre / post 前缀:
json
{
"scripts": {
"prebuild": "rimraf dist",
"build": "vite build",
"postbuild": "echo 构建完成"
}
}
执行 npm run build 会依次执行:prebuild → build → postbuild。
注意: pnpm 和 yarn 现代版本默认不会自动执行
pre/post钩子,需手动配置开启。
5.2 bin --- 可执行文件
json
{
"bin": {
"create-uver": "./bin/create.js"
}
}
当用户全局安装(npm install -g)或通过 npx 执行时,系统会创建软链接到 bin 指定的文件。
如果只有一个可执行文件,可以简写为:
json
{
"name": "create-uver",
"bin": "./bin/create.js"
}
此时命令名就是 name 字段的值。
5.3 man --- 帮助手册
json
{
"man": ["./man/doc.1", "./man/doc.2"]
}
指定 man 命令的文档文件路径,文件必须以数字结尾或以 .gz 压缩。
六、依赖管理字段
6.1 dependencies --- 生产依赖
json
{
"dependencies": {
"lodash-es": "^4.17.21",
"vue": "^3.4.0",
"vue-router": "^4.5.0"
}
}
项目运行时必须的依赖,npm install 默认安装,最终会被打包进产物中。
6.2 devDependencies --- 开发依赖
json
{
"devDependencies": {
"typescript": "^5.3.3",
"vite": "^6.3.5",
"eslint": "^9.3.4",
"prettier": "^3.2.5"
}
}
仅开发阶段需要的依赖(构建工具、Linter、测试框架等)。其他项目安装你的包时不会 安装 devDependencies。
6.3 peerDependencies --- 宿主依赖
json
{
"peerDependencies": {
"vue": "^3.0.0",
"react": "^18.0.0"
}
}
声明"我需要宿主环境提供这个依赖" ,而不是自己安装一份。最经典的场景是 UI 组件库 ------ element-plus 声明 peerDependencies: { "vue": "^3.0.0" },因为它不应该自带一份 Vue。
| npm 版本 | 行为 |
|---|---|
| npm 3-6 | 仅发出警告 |
| npm 7+ | 自动安装 peerDependencies |
6.4 peerDependenciesMeta --- 宿主依赖元信息
json
{
"peerDependencies": {
"vue": "^3.0.0",
"react": "^18.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
}
}
}
标记某个 peerDependency 为可选,未安装时不会报警告。
6.5 optionalDependencies --- 可选依赖
json
{
"optionalDependencies": {
"fsevents": "^2.3.0"
}
}
安装失败时不会导致整个 npm install 失败。典型场景:fsevents 仅在 macOS 下可用。
6.6 bundleDependencies / bundledDependencies --- 捆绑依赖
json
{
"bundleDependencies": ["lodash", "chalk"]
}
npm pack 时会将这些依赖打包进 tarball。适用于需要确保特定版本依赖的场景,或内网环境发布。
6.7 overrides(npm)/ resolutions(yarn)--- 依赖覆盖
npm(overrides):
json
{
"overrides": {
"source-map": "^0.7.4"
}
}
yarn(resolutions):
json
{
"resolutions": {
"source-map": "^0.7.4"
}
}
pnpm(pnpm.overrides):
json
{
"pnpm": {
"overrides": {
"source-map": "^0.7.4"
}
}
}
强制将依赖树中所有匹配的包替换为指定版本。常用于修复深层依赖的安全漏洞或兼容性问题。
版本号范围速查
| 符号 | 含义 | 示例 | 匹配范围 |
|------|------|-----------|------------------|--------------------|--------|
| ^ | 兼容版本 | ^1.2.3 | >=1.2.3 <2.0.0 |
| ~ | 近似版本 | ~1.2.3 | >=1.2.3 <1.3.0 |
| >= | 大于等于 | >=1.2.3 | >=1.2.3 |
| * | 任意版本 | * | 所有版本 |
| 无符号 | 精确版本 | 1.2.3 | 仅 1.2.3 |
| ` | | ` | 或 | ^1.0.0 || ^2.0.0 | 满足任一条件 |
七、发布配置字段
7.1 private --- 私有包
json
{
"private": true
}
设置为 true 后,npm publish 会直接拒绝发布。用于防止 monorepo 根目录或内部项目被意外发布到公共 npm。
7.2 publishConfig --- 发布配置
json
{
"publishConfig": {
"registry": "http://jfrog.gdu-tech.com/artifactory/api/npm/gdu-npm-package/",
"access": "public",
"tag": "latest"
}
}
| 字段 | 说明 |
|---|---|
registry |
发布到指定 npm 仓库(私有源) |
access |
"public" 或 "restricted",scope 包默认 restricted |
tag |
发布时的 dist-tag,默认 latest |
7.3 repository --- 仓库信息
json
{
"repository": {
"type": "git",
"url": "https://github.com/user/project.git",
"directory": "packages/cloud-sdk"
}
}
directory 字段在 monorepo 中非常有用,指明包在仓库中的具体位置。
npm 官网会根据此字段在包详情页展示源码链接。
八、环境约束字段
8.1 engines --- 运行环境要求
json
{
"engines": {
"node": ">=18.0.0",
"pnpm": ">=9.15.0",
"npm": ">=8.0.0"
}
}
声明项目所需的 Node.js 和包管理器版本。默认仅作为建议,如需强制校验:
- npm: 在
.npmrc中设置engine-strict=true - yarn: 自动强制检查
- pnpm: 自动强制检查
8.2 os --- 操作系统限制
json
{
"os": ["darwin", "linux", "!win32"]
}
限制包可运行的操作系统。! 前缀表示排除。
8.3 cpu --- CPU 架构限制
json
{
"cpu": ["x64", "arm64", "!ia32"]
}
限制包可运行的 CPU 架构。
8.4 packageManager --- 指定包管理器
json
{
"packageManager": "pnpm@9.15.0"
}
Node.js 16.9+ 引入的 Corepack 特性。声明项目使用的包管理器及精确版本,搭配 corepack enable,其他包管理器会被拦截。
九、Monorepo 相关字段
9.1 workspaces --- 工作空间
npm/yarn:
json
{
"workspaces": [
"packages/*",
"business/*"
]
}
pnpm 使用独立的 pnpm-workspace.yaml:
yaml
packages:
- 'packages/*'
- 'business/*'
工作空间允许在一个仓库中管理多个包,共享 node_modules,实现包之间的互相引用。
9.2 pnpm --- pnpm 专有配置
json
{
"pnpm": {
"overrides": {
"source-map": "^0.7.4"
},
"peerDependencyRules": {
"ignoreMissing": ["@babel/*"],
"allowedVersions": {
"vue": "3"
}
},
"neverBuiltDependencies": ["fsevents"],
"patchedDependencies": {
"express@4.18.2": "patches/express@4.18.2.patch"
}
}
}
pnpm 的专属扩展配置项,功能非常丰富:
| 字段 | 说明 |
|---|---|
overrides |
强制覆盖依赖版本 |
peerDependencyRules |
控制 peerDep 检查行为 |
neverBuiltDependencies |
跳过某些包的 postinstall 脚本 |
patchedDependencies |
声明补丁文件,搭配 pnpm patch 使用 |
十、工具链配置字段
许多工具支持直接在
package.json中配置,免去创建额外配置文件。
10.1 lint-staged
json
{
"lint-staged": {
"*.{js,ts,vue}": ["eslint --fix", "prettier --write"],
"*.{json,md,yaml,yml}": ["prettier --write"]
}
}
配合 husky 在 git commit 前对暂存文件执行 lint 和格式化。
10.2 browserslist
json
{
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
}
声明目标浏览器范围,影响 Babel、PostCSS Autoprefixer、SWC 等工具的编译输出。
10.3 sideEffects
json
{
"sideEffects": false
}
告知打包工具(Webpack/Rollup/Vite)该包的所有模块都没有副作用,可以安全 Tree Shaking。
也可以指定有副作用的文件:
json
{
"sideEffects": ["*.css", "*.scss", "./src/polyfill.js"]
}
这是优化打包体积最关键的字段之一 。如果你的库设置了
"sideEffects": false,使用者只 import 了一个函数,打包工具就敢放心地把其余代码全部删掉。
10.4 config
json
{
"config": {
"port": "8080"
}
}
可以在 npm scripts 中通过 npm_package_config_port 环境变量读取,用户可以用 npm config set project:port 3000 覆盖。
10.5 其他工具内联配置
以下工具都支持在 package.json 中直接配置:
| 工具 | 字段名 | 说明 |
|---|---|---|
| ESLint(旧版) | eslintConfig |
ESLint 配置 |
| Prettier | prettier |
代码格式化配置 |
| Babel | babel |
编译器配置 |
| Jest | jest |
测试框架配置 |
| Stylelint | stylelint |
CSS Lint 配置 |
| commitlint | commitlint |
Commit 消息规范 |
| unplugin-auto-import | auto-import |
自动导入配置 |
十一、不常见但有用的字段
11.1 flat --- 扁平化依赖(yarn)
json
{
"flat": true
}
强制 yarn 安装依赖时使用扁平结构,如果有版本冲突会提示用户选择。
11.2 preferGlobal --- 建议全局安装(已废弃)
json
{
"preferGlobal": true
}
npm 5+ 已废弃此字段,但部分老项目可能还在使用。
11.3 deprecated --- 废弃提示
不是在 package.json 中设置的字段,而是通过 npm deprecate 命令发布:
bash
npm deprecate my-package@"<2.0.0" "请升级到 2.x 版本"
安装时会显示黄色警告。
十二、字段优先级总结
入口文件解析优先级
不同工具对入口字段的解析优先级不同:
Node.js(>=12.11):
css
exports > main
Webpack 5:
java
exports > browser > module > main
Vite / Rollup:
java
exports > module > main
TypeScript:
css
exports["."]["types"] > types > typings > main(.d.ts)
一张图看清全貌
bash
package.json
├── 📋 基本信息
│ ├── name # 包名
│ ├── version # 版本号
│ ├── description # 描述
│ ├── keywords # 关键词
│ ├── license # 协议
│ ├── author # 作者
│ └── contributors # 贡献者
│
├── 📦 入口文件
│ ├── main # CJS 入口
│ ├── module # ESM 入口
│ ├── browser # 浏览器入口
│ ├── types # TS 类型入口
│ ├── exports # 条件导出(现代方案)
│ └── type # 模块系统声明
│
├── 📁 文件管控
│ ├── files # 发布白名单
│ └── directories # 目录结构声明
│
├── ⚙️ 脚本与命令
│ ├── scripts # NPM 脚本
│ ├── bin # 可执行文件
│ └── man # 帮助手册
│
├── 📚 依赖管理
│ ├── dependencies # 生产依赖
│ ├── devDependencies # 开发依赖
│ ├── peerDependencies # 宿主依赖
│ ├── peerDependenciesMeta # 宿主依赖元信息
│ ├── optionalDependencies # 可选依赖
│ ├── bundleDependencies # 捆绑依赖
│ └── overrides/resolutions # 依赖覆盖
│
├── 🚀 发布配置
│ ├── private # 私有标记
│ ├── publishConfig # 发布配置
│ └── repository # 仓库信息
│
├── 🔒 环境约束
│ ├── engines # Node/npm 版本要求
│ ├── os # 操作系统限制
│ ├── cpu # CPU 架构限制
│ └── packageManager # 包管理器声明
│
├── 🏗️ Monorepo
│ ├── workspaces # 工作空间
│ └── pnpm # pnpm 专有配置
│
└── 🔧 工具链配置
├── lint-staged # 暂存文件 lint
├── browserslist # 目标浏览器
├── sideEffects # 副作用声明
└── config # 自定义配置
十三、最佳实践
1. 库开发的标准 package.json 模板
json
{
"name": "@scope/my-lib",
"version": "1.0.0",
"description": "A modern library",
"type": "module",
"main": "dist/index.cjs",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"files": ["dist"],
"sideEffects": false,
"scripts": {
"build": "tsup src/index.ts --format cjs,esm --dts",
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
"lint": "eslint src",
"test": "vitest"
},
"peerDependencies": {
"vue": "^3.0.0"
},
"peerDependenciesMeta": {
"vue": { "optional": true }
},
"engines": {
"node": ">=18.0.0"
},
"publishConfig": {
"access": "public"
},
"license": "MIT"
}
2. Monorepo 根目录模板
json
{
"name": "my-monorepo",
"version": "1.0.0",
"private": true,
"type": "module",
"packageManager": "pnpm@9.15.0",
"engines": {
"node": ">=18.0.0"
},
"scripts": {
"dev": "pnpm --filter app dev",
"build": "pnpm -r build",
"lint": "eslint .",
"prepare": "husky install"
},
"devDependencies": {
"eslint": "^9.0.0",
"husky": "^9.0.0",
"lint-staged": "^15.0.0",
"prettier": "^3.0.0",
"typescript": "^5.0.0"
},
"lint-staged": {
"*.{js,ts,vue}": ["eslint --fix", "prettier --write"]
}
}
3. 常见误区
| 误区 | 正解 |
|---|---|
把 vite/webpack 放到 dependencies |
构建工具应放在 devDependencies |
不设置 files 字段 |
会把整个项目(含源码)都发布上去 |
exports 中 types 条件放在后面 |
TypeScript 要求 types 必须在第一个 |
不设置 sideEffects |
使用者无法有效 Tree Shaking |
不设置 engines |
用户在低版本 Node 上可能出现诡异问题 |
不设置 private: true |
monorepo 根目录可能被意外 npm publish |
结语
package.json 看似简单,实则承载了包的身份信息、入口解析、依赖管理、构建配置、发布流程等方方面面。理解每一个字段的含义和使用场景,不仅能帮你写出更规范的 npm 包,还能在排查 "模块找不到"、"类型丢失"、"打包体积过大" 等问题时快速定位根因。
希望这篇文章能成为你的 package.json 随身手册,收藏备用!
如果觉得有帮助,别忘了点个赞 👍 收藏一下,后续还会更新更多前端工程化干货。