package.json配置解读
前言
package.json是每个前端项目都会有的json文件,位于项目的根目录中。很多脚手架在创建项目的时候会帮我们自动初始化好 package.json。package.json有许多配置与项目息息相关,了解他们有助于对项目的开发,接下来让我们开始了解package.json的配置。
今天主要介绍一些常用的配置,分为了七大类,分别是:
- 描述配置
- 脚本配置
- 文件配置
- 依赖配置
- 发布配置
- 系统配置
- 第三方配置
一、描述配置
主要是项目的基本信息,包括名称、版本、描述、仓库、作者等。
name
项目的名称,如果是第三方包的话,可以通过该名称通过 npm install 安装。
npm install name
version
项目的版本号,开源项目的版本号遵循 semver 语义化规范,具体如下所示:
简单介绍一下这个数组代表什么意思:
- 1 代表主版本号 Major,通常涉及重大功能更新时更新此版本号;
- 2 代表次版本号 Minor,在引入了新功能,但未产生破坏性变更,依然向下兼容时会更新此版本号;
- 3 代表修订号 Patch,在修复了一些问题,也未产生破坏性变更时会更新此版本号;
回到 package.json 的 version 字段,name + version 能共同构成一个完全唯一的项目标识符,所以它两是最重要的两个字段。
repository
项目的仓库地址以及版本控制信息。
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",
"directory": "packages/react"
}
description
关于项目的描述,会在 npm 官网展示,让其他人更快了解该项目。
"description": "package.json配置解读"
keywords
项目的技术关键词,合适的关键词可以在 npm 官网更好的检索到该项目。
"keywords": [
"component",
"components",
"design",
"framework",
"frontend",
"ui",
"axios"
],
license
项目的开源许可证。项目的版权拥有人可以使用开源许可证来限制源码的使用、复制、修改和再发布等行为。常见的开源许可证有 BSD、MIT、Apache 等。具体可以参考阮一峰老师的这篇文章 如何选择开源许可证。
"license": "BSD"
author
这个字段不用多说,指的是该项目的作者。
"author": "May",
二、文件配置
包括项目所包含的文件以及入口等信息。
files
项目在进行发布时,可以通过 files 指定需要跟随一起发布的内容来控制 npm 包的大小,避免安装时间太长。发布时默认会包括 package.json,license,README 和main 字段里指定的文件。忽略 node_modules,lockfile 等文件。在此基础上我们可以指定其他可以发布的内容,可以是单独的文件,文件件以及通配符匹配到的文件。一般情况下,files 里会指定构建出来的产物以及类型文件,而 src 目录下的文件不需要跟随发布。
"files": [
"file.js",
"may/",
"global/*.{js,json}"
]
type
在node支持ES模块后,要求ES模块采用 .mjs 后缀文件名,只要遇到 .mjs 结尾的文件,就认为它是ES模块。如果不想修改文件后缀名,可以在 package.json 中修改 type 值为 module。
"type": "module"
如果还要使用 CommonJs 模块规范,那么需要将 CommonJS 模块的文件以 .cjs 结尾,不过建议这两种模块不要混合使用,会有异常报错。
main
项目发布时,默认会包括 package.json,license,README 和 main 字段里指定的文件,因为 main 字段里指定的是项目的入口文件,在 browser 和 Node 环境中都可以使用。如果不设置 main 字段,那么入口文件就是根目录下的 index.js。
browser
main 字段里指定的入口文件在 browser 和 Node 环境中都可以使用。如果只想在 web 端使用,不允许在 server 端使用,可以通过 browser 字段指定入口。
"browser": "./browser/index.js"
module
module 字段可以用来指定 ES 模块的入口文件。
"module": "./index.mjs"
当一个项目同时定义了 main,browser 和 module,webpack,rollup 等构建工具会感知这些字段,并会根据环境以及不同的模块规范来进行不同的入口文件查找。比如 webpack 构建项目时默认的 target 为 ‘web’,也就是 Web 构建。它的 resolve.mainFeilds 字段默认为 [‘browser’, ‘module’, ‘main’]。
module.exports = {
//...
resolve: {
mainFields: ['browser', 'module', 'main'],
},
};
此时会按照 browser -> module -> main 的顺序来查找入口文件。
exports
node 在 14.13 支持在 package.json 里定义 exports 字段,拥有了条件导出的功能。exports 字段可以配置不同环境对应的模块入口文件,并且当它存在时,它的优先级最高。比如使用 require 和 import 字段根据模块规范分别定义入口:
"exports": {
"require": "./index.js",
"import": "./index.mjs"
}
}
这样的配置在使用 import ‘xxx’ 和 require(‘xxx’) 时会从不同的入口引入文件,exports 也支持使用 browser 和 node 字段定义 browser 和 Node 环境中的入口。上方的写法其实等同于:
"exports": {
".": {
"require": "./index.js",
"import": "./index.mjs"
}
}
}
为什么要加一个层级,把 require 和 import 放在 “.” 下面呢?因为 exports 除了支持配置包的默认导出,还支持配置包的子路径。
workspaces
项目的工作区配置,用于在本地的根目录下管理多个子项目。可以自动地在 npm install 时将 workspaces 下面的包,软链到根目录的 node_modules 中,不用手动执行 npm link 操作。workspaces 字段接收一个数组,数组里可以是文件夹名称或者通配符。比如:
"workspaces": [
"workspace-s"
]
表示在 workspace-s 目录下还有一个项目,它也有自己的 package.json。
package.json
workspace-a
└── package.json
通常子项目都会平铺管理在 packages 目录下,所以根目录下 workspaces 通常配置为:
"workspaces": [
"packages/*"
]
三、脚本配置
scripts
指定项目的一些内置脚本命令,这些命令可以通过 npm run 来执行。通常包含项目开发,构建 等 CI 命令,比如:
"scripts": {
"build": "webpack"
}
我们可以使用命令 npm run build 来执行项目构建。除了指定基础命令,还可以配合 pre 和 post 完成命令的前置和后续操作,比如:
"scripts": {
"build": "webpack",
"prebuild": "xxx", // build 执行之前的钩子
"postbuild": "xxx" // build 执行之后的钩子
}
当执行 npm run build 命令时,会按照 prebuild -> build -> postbuild 的顺序依次执行上方的命令。但是这样的隐式逻辑很可能会造成执行工作流的混乱,所以 pnpm 和 yarn2 都已经废弃掉了这种 pre/post 自动执行的逻辑。如果需要手动开启,pnpm 项目可以设置
enable-pre-post-scripts=true
config
config 用于设置 scripts 里的脚本在运行时的参数。比如设置 port 为 3001:
"config": {
"port": "8080"
}
在执行脚本时,我们可以通过 npm_package_config_port 这个变量访问到 3001。
// 8080
console.log(process.env.npm_package_config_port);
四、依赖配置
项目开发过程中会依赖其他包,需要在 package.json 里配置这些依赖的信息。
dependencies
运行依赖,也就是项目生产环境下需要用到的依赖。比如 vue,vuex以及组件库等。使用 npm install xxx 或则 npm install xxx –save 时,会被自动插入到该字段中。
"dependencies": {
"element-plus": "^2.2.28",
"pinia": "^2.0.28",
"sass": "^1.57.1",
"vite": "^4.0.3",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
},
devDependencies
开发依赖,项目开发环境需要用到而运行时不需要的依赖,用于辅助开发,通常包括项目工程化工具比如 vite,eslint 等。使用 npm install xxx -D 或者 npm install xxx –save-dev 时,会被自动插入到该字段中。
"devDependencies": {
"cz-git": "^1.4.1",
"eslint": "^8.30.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-define-config": "^1.12.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.8.0",
"husky": "^8.0.0",
"less": "^4.1.3",
"lint-staged": "^13.1.0",
"postcss-html": "^1.5.0",
"postcss-less": "^6.0.0",
"prettier": "^2.8.1",
"stylelint": "^14.16.0",
"stylelint-config-html": "^1.1.0",
}
peerDependencies
同伴依赖是一种特殊的依赖,不会被自动安装,通常用于表示与另一个包的依赖与兼容性关系来警示使用者。
optionalDependencies
可选依赖,表示依赖是可选的,它不会阻塞主功能的使用,安装或者引入失败也无妨。这类依赖如果安装失败,那么 npm 的整个安装过程也是成功的。使用 npm install xxx -O 或者 npm install xxx –save-optional 时,依赖会被自动插入到该字段中。
bundleDependencies
打包依赖。它的值是一个数组,在发布包时,bundleDependencies 里面的依赖都会被一起打包。在执行 npm pack 打包生成 tgz 压缩包中,将出现 node_modules 并包含 react 和 react-dom。
需要注意的是,这个字段数组中的值必须是在 dependencies,devDependencies 两个里面声明过的依赖才可以。普通依赖通常从 npm registry 安装,但当你想用一个不在 npm registry 里的包,或者一个被修改过的第三方包时,打包依赖会比普通依赖更好用。
五、发布配置
主要是一些和项目发布有关的配置
private
如果是私有项目,不希望发布到公共 npm 仓库上,可以将 private 设为 true。
"private": true
publishConfig
publishConfig 就是 npm 包发布时使用的配置。比如在安装依赖时指定了 registry 为 taobao 镜像源,但发布时希望在公网发布,就可以指定 publishConfig.registry。
"publishConfig": {
"registry": "https://registry.npmjs.org/"
}
六、系统配置
项目有关的系统配置,比如 node 版本或操作系统兼容性之类。但是值得注意的是这些要求只会起到提示警告的作用,即使用户的环境不符合要求,也不影响安装依赖包。
engines
一些项目由于兼容性问题会对 node 或者包管理器有特定的版本号要求,比如:要求 node 版本大于等于 12 且小于 16,同时 pnpm 版本号需要大于 7。
"engines": {
"node": ">=12 <16",
"pnpm": ">7"
}
os
在 linux 上能正常运行的项目可能在 windows 上会出现异常,使用 os 字段可以指定项目对操作系统的兼容性要求。
"os": ["darwin", "linux"]
cpu
指定项目只能在特定的 CPU 体系上运行。
"cpu": ["x64", "ia32"]
七、第三方配置
一些第三方库或应用在进行某些内部处理时会依赖这些字段,使用它们时需要安装对应的第三方库。
types 或者 typings
指定 TypeScript 的类型定义的入口文件
"types": "./index.ts",
browserslist
设置项目的浏览器兼容情况。babel 和 autoprefixer 等工具会使用该配置对代码进行转换。当然你也可以使用 .browserslistrc 单文件配置。
"browserslist": [
"> 1%",
"last 2 versions"
]
sideEffects
显示设置某些模块具有副作用,用于 webpack 的 tree-shaking 优化。比如在项目中整体引入 Ant Design 组件库的 css 文件。
import 'antd/dist/antd.css';
如果 Ant Design 的 package.json 里不设置 sideEffects,那么 webapck 构建打包时会认为这段代码只是引入了但并没有使用,可以 tree-shaking 剔除掉,最终导致产物缺少样式。
lint-staged
lint-staged 是用于对 git 的暂存区的文件进行操作的工具,比如可以在代码提交前执行 lint 校验,类型检查,图片优化等操作。
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx}": [
"eslint --fix",
"git add -A"
]
}
lint-staged 通常配合 husky 这样的 git-hooks 工具一起使用。git-hooks 用来定义一个钩子,这些钩子方法会在 git 工作流程中比如 pre-commit,commit-msg 时触发,可以把 lint-staged 放到这些钩子方法中。
结语
今天我们简单了解了 package.json 的常见配置。有了这些知识,我们可以更好的了解项目。但 package.json 里的内容远不止如此,需要我们进一步学习。
- Author: 未来可期
- Link: http://shansec.github.io/post/blog/package-json%E9%85%8D%E7%BD%AE%E8%A7%A3%E8%AF%BB/
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.