package.json

package.json 是一个用于描述和配置项目的重要文件,其中包含了许多字段和选项,可以影响项目的构建、依赖管理、脚本执行等方面。了解这些字段可以帮助开发者更好地理解和控制项目的行为

package.json 对于大部分前端开发者来说,知道 dependenciesdevDependencies 就够了。但对于库开发者或有更高级需求的开发者来说,了解 package.json 的其他字段是非常有必要的

必须属性

name

  1. 定义项目的名称,不能以 ._ 开头,不能包含大写字母

version

  1. 定义项目的版本号,格式为 大版本号.次版本号.修订号

描述信息

description

  1. 项目描述

keywords

  1. 项目关键字

author

  1. 项目作者
1
"author": "name (https://github.com)"

contributors

  1. 项目贡献者
1
2
3
"contributors": [
"name <emial> (https://github.com)"
]

homepage

  1. 项目主页地址

repository

  1. 项目代码仓库地址

bugs

  1. 项目提交问题地址
1
2
3
4
5
 //提交问题的地址和反馈的邮箱,url通常是Github中的issues页面
"bugs": {
"url" : "https://github.com/facebook/react/issues",
"email" : "xxxxx@xx.com"
}

funding

  1. 指定项目的资金支持方式和链接
1
2
3
4
 "funding": {
"type": "afdian",
"url": "https://afdian.net/"
}

依赖配置

dependencies

  1. 生产环境的依赖包
  2. 版本号
    • ^ 限定大版本
    • ~ 限定次版本
  3. package-lock.json 中存储当前实际安装的版本

devDependencies

  1. 开发环境的依赖包,比如一些打包工具、babel、eslint

peerDependencies

  1. 对等依赖的作用

    • 减小打包体积:例如使用 react 开发的组件库,安装 react 是必不可少的,而使用组件库的开发者,本地项目肯定安装了 react 因此开发的组件库中不必把 react 打包进去 (期望项目的使用者来提供这些模块的实现)
    • 版本一致性:使用你的组件库的开发者需要确保它们的项目中安装了与你声明的对等依赖版本兼容的包,以确保组件库可以正常运行
  2. 例如:声明使用组件库,需要在项目中安装大于 17.0.1 版本的 react

    1
    2
    3
    "peerDependencies": {
    "react": ">17.0.1"
    }

peerDependenciesMeta

  1. 将对等依赖标记为可选,如果用户没有安装对等依赖,npm 不会发出警告
1
2
3
4
5
"peerDependenciesMeta": {
"react": {
"optional": true //标记为可选
}
}

bundledDependencies

  1. 声明捆绑依赖项(使用情景较少)

optionalDependencies

  1. 声明可选依赖项(使用情景较少)

engines

  1. 声明对 npmnode 版本要求
    • engines 只是起到一个说明的作用,即使用户安装的版本不符合要求,也不影响依赖包的安装
1
2
3
4
"engines": {
"node": ">=8.10.3 <12.13.0",
"npm": ">=6.9.0"
}

workspaces

  1. 单个代码库中管理多个包(monorepo),在 workspaces 声明目录下的 package 会软链接到根目录的 node_modules

  2. 初始化项目

1
2
3
# 初始化项目

npm init -y
  1. 声明本项目是 workspaces 模式
1
2
3
4
"private": "true",
"workspaces": [
"packages/*"
]

表示所有子包都在 packages 文件夹下

  1. 创建子包 p1
1
npm init -w packages/p1 -y

node_modules/.package-lock.json 中可以看到 "link": true 链接符号信息

  1. 新建 packages/p1/index.js
1
module.exports = 'p1包';
  1. 创建子包 p2
1
npm init -w packages/p2 -y
  1. 将子包 p1 添加到 p2
1
npm i p1 -w p2

安装,卸载等命令都是一样的,只是多了 --workspace= 参数(简写 -w),用来指定在哪个包中执行命令

  1. 子包 p2 中使用 p1
1
2
3
4
5
const p1 = require("p1");

console.log('使用', p1);

module.exports = 'p2包';

workspaces 功能与 lerna 类似,如果只需简单地管理多个包,workspaces 足够了。lerna 具有版本管理,发包提示,简化多包项目发布流程等更多功能

脚本配置

scripts

  1. 脚本入口

config

  1. 用于定义项目的配置项,例如设置环境变量
  2. config 配置
1
2
3
"config": {
"baseUrl": "https://example.com"
}
  1. scripts 配置
1
2
3
"scripts": {
"start": "node index.js"
}
  1. 新建 index.js
1
2
3
// 使用 process.env.npm_package_config_xxx取值 注意需要写到 config里面

console.log(process.env.npm_package_config_baseUrl);

运行 npm start 打印对应 baseUrl

文件&目录

module (非官方字段)

  1. 指定 es 模块入口文件
  2. 例子:当其他开发者在它们的项目中导入你的包,会加载并执行包中的 dist/index.esm.js
1
"module": "dist/index.esm.js"

main

  1. 指定 commonjs 模块 或 es 模块入口文件,如果不指定该字段,默认是根目录下的 index.js
  2. node12.20.0 版本开始 main 字段也可以指定 es 模块的入口文件

browser

  1. 指定浏览器使用的入口文件,例如 umd 模块

types (非官方字段)

  1. 指定 TypeScript 类型声明文件 .d.ts 文件的路径

exports (非官方字段)

  1. 当打包工具支持 exports 字段时,(webpack rollup 等),以上 main browser module types 四个字段都被忽略
1
2
3
4
5
6
7
8
"exports": {
".": {
"import": "./dist/index.esm.js",
"require": "./dist/index.cjs.js",
"browser": "./dist/index.umd.js",
"types": "./dist/index.d.ts"
}
}
  1. . 表示默认导出
    • import 指定了 ES module esm 规范下的导出文件路径
    • require 指定了 commonJs 规范下的导出文件路径
    • browser 指定了用于浏览器环境的导出文件路径
    • types 指定了类型声明文件的路径
  2. 导出其他文件,例如除了导出默认路径,导出源文件
1
2
3
4
"exports":{
// ...
"./main" : "./src/main.js"
},

其他项目上使用

1
2
import main from 'packageName'; // . 方式定义的
import main from 'packageName/main'; // ./mian 方式定义的

type (非官方字段)

  1. 指定模块系统的使用方式 commonjs module umd json
  2. 例如:指定模块系统为 ES module 模式,使用 CommonJS 文件时,需显式的定义为 .cjs 文件扩展名,来明确指定这些文件为 CommonJS 模块
1
"type": "module"

files

  1. 指定哪些包会被推送到 npm 服务器
  2. 例子: 只推送 index.jsdist 包到 npm 服务器
1
2
3
4
"files": [
"index.js",
"dist"
]
  1. 可以在项目根目录新建一个 .npmignore 文件,说明不需要提交到 npm 服务器的文件,类似 .gitignore 写在这个文件中的文件即便被写在 files 属性中也会被排除在外

bin

  1. 定义在全局安装时可执行的命令 (使用情景较少)

man

  1. linux 中的帮助指令 (使用情景较少)

directories

  1. 定义项目目录结构的字段(使用情景较少)

发布配置

private

  1. 防止私有包发布到 npm 服务器,要发布到 npm 上设为 false

preferGlobal (非官方字段)

  1. 当设置 "preferGlobal" 字段为 true 时,它表示你的包更适合以全局方式安装,而不是作为项目的依赖项进行本地安装,这个字段的设置是为了向用户传达关于你的包的最佳使用方式的建议。它并不会直接影响包的安装方式或包管理器的行为

publishConfig

  1. 在发布包时指定特定的配置
  2. 指定包发布的注册表 URL,指定所有用户都可以访问(私有的会收费)
1
2
3
4
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
}

os

  1. 指定你的包适用的操作系统
  2. 示例:包只适用于 darwin(macOS)linux
1
"os": ["darwin", "linux"]
  1. 示例:禁用 win32
1
"os": ["!win32"]

cpu

  1. 该配置和 OS 配置类似,用 CPU 可以更准确的限制用户的安装环境

license

  1. 指定软件的开源协议
  2. ISC:在所有副本中保留版权声明和许可证声明,使用者就可以拿你的代码做任何想做的事情,你也无需承担任何责任
  3. MIT:在所有副本或主要部分中保留版权声明和许可证声明,使用者就可以拿你的代码做任何想做的事情,你也无需承担任何责任

第三方配置 (非官方字段)

eslintConfig

  1. eslint 的配置,更推荐使用 .eslintrc 等方式进行配置

babel

  1. babel 的配置,更推荐使用 .babelrc 进行配置

unpkg

  1. unpkg 是一个基于 CDN 的前端包托管服务,用于在浏览器中直接引用和加载 npm 上发布的包
1
<script src="https://unpkg.com/package-name@version"></script>

lint-staged

  1. lint-staged 是一个在 Git 暂存文件上运行 linters 的工具,通常配合 gitHooks 一起使用

browserslist

  1. 支持哪些浏览器以及版本 autoprefixer 常用到它
1
2
3
4
5
6
7
8
"browserslist": [
"defaults",
"not ie < 8",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
]

sideEffects

  1. 指定包是否具有副作用,协助 webpack rollup 等进行 tree shaking
  2. 多数情况下可以直接设置为 false,这样打包工具就会自动删除未被 import 的代码
  3. 但是有些情况例外
    • 有一些特定的模块文件,它们执行一些副作用操作,如注册全局事件监听器、修改全局状态等
    • 告诉构建工具不要将样式文件排除在无用代码消除的优化范围之外
1
"sideEffects": ["./path/to/module.js", "*.css"]