大家好,我是刘布斯。
我们在前端项目或者 npm 中,都会看到package.json
文件,但大家应该很少关注里面的东西。
其实 package.json
是前端开发中很基础,却又重要的一环,今天将带大家了解 package.json
的作用以及常用配置。
简单来说,package.json
是一个配置文件,并且通过记录项目的关键信息、依赖、脚本和配置,帮助开发者高效管理和维护项目。
展开一点讲,下面是它包含的数据,或者提供的能力:
项目元数据: 包含了关于项目的基本信息,如项目名称(name
)、版本号(version
)、描述(description
)和作者(author
)等。这些信息有助于识别和管理项目。
依赖管理: 记录了项目的所有依赖项,包括 dependencies
(生产依赖)和 devDependencies
(开发依赖)。通过这些信息,项目在安装时会自动下载和管理所需的库和工具。
脚本管理: scripts
字段允许你定义自定义的命令和脚本,例如启动服务器、运行测试、构建项目等。这些脚本可以通过 npm run
或 yarn run
命令执行,简化了常见的开发任务。
版本控制: package.json
支持版本控制和语义化版本(SemVer),通过 version
字段和依赖项的版本范围来管理项目版本和依赖项的兼容性。
配置管理: 可以在 package.json
中配置各种工具和插件,例如 Babel、Webpack 和 ESLint。这使得项目的配置和依赖管理更加集中和一致。
项目和团队协作: 通过 package.json
,团队成员可以确保在不同的开发环境中使用相同的依赖版本和配置,从而减少环境不一致带来的问题。
package.json 文件包含了多个字段,每个字段都有其特定的用途和作用。
我们来介绍下常用的字段。
name
: 包的名称,用于唯一标识包。名称通常应该是全局唯一的,并符合 npm 的命名规范。
version
: 包的版本号,用于表示包的版本,遵循语义化版本控制(SemVer)。版本号格式通常为 major.minor.patch
(主版本号.次版本号.补丁号)。
description
: 对包的简要描述,介绍包的功能或目的,有助于用户了解包的用途。
main
: 包的入口文件。指定模块的主要入口文件,通常是一个 JavaScript 文件。如果不设置则默认查找这个包根目录下的 index.js
文件。当我们使用 require
引入包的时候则会查找 main
对应路径的文件进行引入。这个文件应该遵循 CommonJS
模块规范,并且基于 ES5
规范编写。
module
: npm 包的 ESM
规范的入口文件。这个文件可以使用 ES6
的 import/export
语法,并支持 Tree Shaking
等特性。main
和 module
字段在 package.json 中共同存在时,分别用于指定不同模块规范下的入口文件,以满足不同环境和工具的需求。
scripts
: 定义可执行的命令。通过 npm run
或 yarn run
运行自定义脚本。例如,可以定义 start
、test
、build
等脚本,用于启动开发服务器、运行测试或构建项目。
dependencies
: 生产环境的依赖项。列出项目运行时所需的依赖包及其版本。npm install
安装这些依赖项。
devDependencies
: 开发环境的依赖项。列出项目开发和测试时所需的依赖包。例如,构建工具、测试框架等。npm install --save-dev
安装这些依赖项。
peerDependencies
: 同步依赖项。指定包的同行依赖(peer dependencies),这些依赖需要在宿主项目中安装,以确保兼容性。
engines
:支持的 Node.js 版本或其他引擎版本。指定项目所需的 Node.js 版本范围或其他运行时环境版本,以确保在合适的环境中运行。
license
:项目的许可证类型。规定项目的使用和分发许可,常见的许可证有 MIT、Apache-2.0 等。
repository
:项目的版本控制仓库信息。指定项目的源代码仓库地址,以便用户和贡献者可以访问和协作。
browserslist
:支持的浏览器范围。配置支持的浏览器版本范围,用于前端工具(如 Babel、Autoprefixer)生成兼容的代码。
还有一些可能没那么常用的,比如:
keywords
: 关的关键字列表。提高包在 npm 上的可搜索性,帮助用户更容易找到包。
author
: 包的作者信息。提供作者的名字和联系方式,有助于用户联系或了解包的维护者。
contributors
: 贡献者列表。列出为项目做出贡献的其他开发者和其信息。
files
: 包含在发布包中的文件。指定哪些文件和目录应包含在发布的包中,有助于减少包的大小。如果你只有少数不上传的文件,那也可以创建一个.npmignore 文件(类似于.gitignore,但该文件不会上传 npm),记录不需要上传的文件或目录,其余都上传。
bin
: 可执行文件的映射。指定包中包含的可执行脚本及其对应的命令,便于全局安装时创建命令行工具。
{
"name": "my-tool",
"version": "1.0.1",
"bin": {
"my-tool": "./bin/index.js"
},
"scripts": {
"start": "node index.js"
}
//...
}
config
: 包的配置选项。提供自定义的配置项,供脚本或工具使用。
homepage
: 目的主页 URL。
bugs
: 提交问题的地址。
license
: 的许可证(软件的开源协议)。
types
: TypeScript
类型定义文件的路径。
exports
: 定义包的子路径导出映射。
"exports": {
".": {
"import": "./index.esm.js", // 当使用 ESM 语法导入包时,解析到这个文件
"require": "./index.cjs" // 当使用 require() 导入包时,解析到这个文件
},
"./feature": {
"import": "./feature/esm/index.js", // 当导入特定的特性时,为 ESM 提供不同的入口点
"require": "./feature/cjs/index.js" // 当导入特定的特性时,为 CommonJS 提供不同的入口点
}
},
unpkg
: CDN 服务地址。
publishConfig
: npm 包的发布指定特定的配置。该配置将覆盖全局或用户级别的 npm 配置。这对于需要将包发布到私有 npm 仓库或具有特殊发布需求的场景特别有用。
publishConfig 是一个对象包含以下属性:
registry
:指定 npm 包的发布仓库地址。(私有 npm 仓库可以在这指定 url)
access
:包的访问级别(默认public
公开,restricted
私有)
tag
:为发布的 npm 包指定一个标签。默认情况下 npm 包会使用latest
标签发布,你可以手动指定为beta
style
: 该字段不是标准的 npm 字段,代表包中的样式文件路径。当 style 字段被设置时,某些工具(如 Webpack 的某些 loader 或构建脚本)可能会自动处理或包含这个样式文件。这通常用于那些希望将样式文件直接包含在其包中的前端库或组件。
sideEffects
:用于告知打包工具(如 Webpack)哪些文件或模块在引入时具有副作用,从而影响 tree shaking 的行为。
在 package.json 中,sideEffects 字段是 Webpack v4 及更高版本引入的一个特性,用于标记项目中的某些文件或模块是否包含副作用(side effects)。这个字段对于 Webpack 的 tree shaking(树摇)优化至关重要。通过正确配置 sideEffects,打包工具可以更有效地移除未使用的代码,减小最终打包文件的大小。
版本号也是一块值得介绍的内容,大家了解的可能都是版本号遵循 semver 版本规范,通常由三位构成:x.y.z。分别对应主版本号、次版本号、修订号。
其实还有预发布版本以及构建元数据:
预发布版本(Pre-release): 使用破折号(-
)添加额外的标识,例如 1.0.0-alpha
。表示该版本尚未正式发布,可能不稳定。
构建元数据(Build Metadata):使用加号(+
)添加,例如 1.0.0+20130313144700
。提供附加的构建信息,不影响版本的排序或兼容性。
大家实践中,会发现很多依赖的版本号前面会有不同的符号,其实这是用于定义版本范围和兼容性。
常见的符号包括:
符号 | 定义 | 示例 | 解释 |
---|---|---|---|
^ | 接受指定版本及其向后兼容的次版本号和补丁号更新,但不升级主版本号。 | ^1.2.3 | 兼容 1.2.3 至 1.x.x (小于 2.0.0 ) |
~ | 接受指定版本及其向后兼容的补丁号更新,但不升级次版本号。 | ~1.2.3 | 兼容 1.2.3 至 1.2.x (小于 1.3.0 ) |
>= | 接受指定版本及其任何更高的版本。 | >=1.2.3 | 兼容 1.2.3 及其更高版本 |
<= | 接受指定版本及其任何更低的版本。 | <=1.2.3 | 兼容 1.2.3 及其更低版本 |
> | 接受指定版本及其任何更高版本(不包括指定版本)。 | >1.2.3 | 兼容高于 1.2.3 的版本 |
< | 接受指定版本及其任何更低版本(不包括指定版本)。 | <1.2.3 | 兼容低于 1.2.3 的版本 |
- | 版本范围。 | 1.2.3 - 2.3.4 | 兼容 1.2.3 至 2.3.4 (包括这两个版本) |
* | 任何版本。 | * | 兼容任何版本 |
在实际的开发中,大家可能会经常遇到这样的情况:
lodash@4.17.19
,而 B 依赖 lodash@4.17.21
,这可能导致版本冲突。webpack@4.x
,而库 D 需要 webpack@5.x
。package.json
中的版本号而没有充分测试可能导致意外的版本冲突。这样就会出现版本冲突的问题,我们一般可以手动编辑 package.json
,调整为兼容的版本,并重新安装依赖。或者是使用 package-lock.json
或 yarn.lock
文件锁定依赖版本,以确保在不同环境中使用相同的依赖版本。
在没有这些文件的项目中,首次使用 npm
/yarn
/pnpm
安装依赖的时候会自动生成。
当我们使用命令更新某个包的版本的时候,同时也会修改这些锁定的文件。
上面介绍了这么多,再放一个大家常用的 element-plus
中的package.json
,大家可以检测下,看是否能理解各个字段的含义:
{
"name": "element-plus",
"version": "2.3.12",
"description": "A Component Library for Vue 3",
"keywords": [
"element-plus",
"element",
"component library",
"ui framework",
"ui",
"vue"
],
"homepage": "https://element-plus.org/",
"bugs": {
"url": "https://github.com/element-plus/element-plus/issues"
},
"license": "MIT",
"main": "lib/index.js",
"module": "es/index.mjs",
"types": "es/index.d.ts",
"exports": {
".": {
"types": "./es/index.d.ts",
"import": "./es/index.mjs",
"require": "./lib/index.js"
},
"./es": {
"types": "./es/index.d.ts",
"import": "./es/index.mjs"
},
"./lib": {
"types": "./lib/index.d.ts",
"require": "./lib/index.js"
},
"./es/*.mjs": {
"types": "./es/*.d.ts",
"import": "./es/*.mjs"
},
"./es/*": {
"types": ["./es/*.d.ts", "./es/*/index.d.ts"],
"import": "./es/*.mjs"
},
"./lib/*.js": {
"types": "./lib/*.d.ts",
"require": "./lib/*.js"
},
"./lib/*": {
"types": ["./lib/*.d.ts", "./lib/*/index.d.ts"],
"require": "./lib/*.js"
},
"./*": "./*"
},
"unpkg": "dist/index.full.js",
"jsdelivr": "dist/index.full.js",
"repository": {
"type": "git",
"url": "git+https://github.com/element-plus/element-plus.git"
},
"publishConfig": {
"access": "public"
},
"style": "dist/index.css",
"sideEffects": [
"dist/*",
"theme-chalk/**/*.css",
"theme-chalk/src/**/*.scss",
"es/components/*/style/*",
"lib/components/*/style/*"
],
"peerDependencies": {
"vue": "^3.2.0"
},
"dependencies": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.0.6",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.14.182",
"@types/lodash-es": "^4.17.6",
"@vueuse/core": "^9.1.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.3",
"escape-html": "^1.0.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-unified": "^1.0.2",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
},
"devDependencies": {
"@types/node": "*",
"csstype": "^2.6.20",
"vue": "^3.2.37",
"vue-router": "^4.0.16"
},
"vetur": {
"tags": "tags.json",
"attributes": "attributes.json"
},
"web-types": "web-types.json",
"browserslist": ["> 1%", "not ie 11", "not op_mini all"],
"gitHead": "89d4ec863ce55fc3de2f0513631e76f695f8e791"
}
还没有使用过我们刷题网站(https://fe.ecool.fun/)或者刷题小程序的同学,如果近期准备或者正在找工作,千万不要错过,题库主打无广告和更新快哦~。
有会员购买、辅导咨询的小伙伴,可以通过下面的二维码,联系我们的小助手。