前端工程化基石:package.json 40+ 字段逐一拆解

每个前端项目的根目录下几乎都有一个 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.11.0.0-beta.21.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 类型声明文件的入口路径。typestypings 等价,推荐用 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+ 引入的现代模块解析方案 ,是 mainmodulebrowser 的"终极替代方案"。

核心能力:

特性 说明
条件导出 根据环境(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.json
  • README(任何大小写和扩展名)
  • LICENSE / LICENCE
  • CHANGELOG
  • main 字段指向的文件

始终排除的文件(无法包含):

  • .git
  • node_modules
  • .npmrc
  • package-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 会依次执行:prebuildbuildpostbuild

注意: 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 字段 会把整个项目(含源码)都发布上去
exportstypes 条件放在后面 TypeScript 要求 types 必须在第一个
不设置 sideEffects 使用者无法有效 Tree Shaking
不设置 engines 用户在低版本 Node 上可能出现诡异问题
不设置 private: true monorepo 根目录可能被意外 npm publish

结语

package.json 看似简单,实则承载了包的身份信息、入口解析、依赖管理、构建配置、发布流程等方方面面。理解每一个字段的含义和使用场景,不仅能帮你写出更规范的 npm 包,还能在排查 "模块找不到"、"类型丢失"、"打包体积过大" 等问题时快速定位根因。

希望这篇文章能成为你的 package.json 随身手册,收藏备用!


如果觉得有帮助,别忘了点个赞 👍 收藏一下,后续还会更新更多前端工程化干货。

相关推荐
OpenTiny社区1 小时前
WebMCP + WebSkills:企业级智能化页面操控方案,兼顾隐私安全与高效落地!
前端·ai编程·mcp
酉鬼女又兒2 小时前
零基础快速入门前端JavaScript四大核心内置对象:Math、Date、String、Array全解析(可用于备赛蓝桥杯Web应用开发)
前端·javascript·css·蓝桥杯·前端框架·js
__sgf__2 小时前
ES11(ES2020)新特性
前端·javascript
架构师沉默2 小时前
Gemini 正式登陆香港,不用翻墙!
java·后端·架构
__sgf__2 小时前
ES8(ES2017)新特性
前端·javascript
__sgf__2 小时前
ES9(ES2018)新特性
前端·javascript
飞Link2 小时前
LangChain Core 架构深度剖析与 LCEL 高阶实战
人工智能·架构·langchain
送鱼的老默2 小时前
学习笔记--vue3 watchEffect监听的各种姿势用法和总结
前端·vue.js
你挚爱的强哥2 小时前
解决:动态文本和背景色一致导致文字看不清楚,用js获取背景图片主色调,并获取对比度最大的hex色值给文字
前端·javascript·github