WHAT - package.json 解释
目录
- 一、前言
- 二、介绍
- 2.1 `package.json` 文件示例
- 2.2 关键字段
- 2.3 常用命令
- 2.4 自定义脚本
- 三、element-plus 完整示例
- 3.1 main 和 module
- 1. main 字段
- 2. `module` 字段
- 3. 综合示例
- 3.2 types
- 1. 示例
- 2. TypeScript 类型定义文件的作用
- 3. 类型定义文件示例
- 4. 发布带有类型定义的包
- 3.3 styles
- 1. 示例
- 2. 用途
- 3.4 peerDependencies
- 1. dependencies
- 示例
- 2. devDependencies
- 示例
- 3. peerDependencies
- 示例
- 进一步理解
- 3.5 exports
- 为什么使用 `exports`
- `exports` 字段示例
- 解释
- 更多复杂示例
- 使用场景
- 3.6 unpkg 和 jsdelivr
- unpkg
- jsDelivr
- 共同特点
- 如何选择
- 3.7 publishConfig
- 示例
- 使用场景
- 注意事项
- 3.8 sideEffects
- 为什么需要 `sideEffects`
- `sideEffects` 的取值
- 示例
- 使用场景
- 注意事项
- 3.9 browserslist
- 为什么需要 `browserslist`
- `browserslist` 的使用
- 使用场景
- 注意事项
一、前言
在 HOW - 编写并发布一个 npm 包模块(含 CLI 工具包开发) 中我们简单介绍过 package.json
文件,并提供了如下示例:
{// 包的名称"name": "changelog-tool",// 包的版本号"version": "0.5.0",// 这将显示在NPM搜索结果中"description": "A CLI tool for manipulating changelogs",// 这告诉Node这是一个ESM包// 当然不是严格需要的,如果我们在每个地方都是使用 .mjs"type": "module",// 如果需要在编码的时候使用此包中的方法(不是 CLI 中),则需要在这里指定导出的模块入口文件"main": "index.mjs",// 将必须的文件才发布到 npm"files": {"dist","types",//...}"scripts": {// 运行测试用例"test": "node --test",},// 方便更好的在 npmjs.org 上发现此包"keywords": ["changelog","markdown"],// 作者信息"author": "Evert Pot (https://evertpot.com/)",// 做任何你想做的事(MIT协议基本没有约束)"license": "MIT","engine": {// 警告尚未升级的用户"node": ">16"},"bin": {// 指定执行文件,当人们安装这个包时,可以通过 `npx changelog` 执行// 如果全局安装了这个包,就会有一个 `changelog` 命令"changelog": "./cli.mjs"},"devDependencies": {"@types/node": "^18.11.19",}
}
除了上述几个 Key Fields,一个完整的开源库还应该设置更多属性。今天我们就来主要介绍一下 package.json
。
二、介绍
package.json
文件是 Node.js 项目中的一个关键组件,它包含了项目的元数据,比如项目依赖、脚本、版本等信息。package.json
文件是管理 Node.js 项目的灵活而强大的方式,确保项目的一致性和便于协作。
下面是一个 package.json
文件的示例以及各个字段的解释。
2.1 package.json
文件示例
{"name": "example-project","version": "1.0.0","description": "一个展示 package.json 文件的示例项目","main": "index.js","scripts": {"start": "node index.js","test": "echo \"Error: no test specified\" && exit 1"},"repository": {"type": "git","url": "git+https://github.com/username/example-project.git"},"keywords": ["示例","演示","node"],"author": "Your Name <youremail@example.com>","license": "ISC","bugs": {"url": "https://github.com/username/example-project/issues"},"homepage": "https://github.com/username/example-project#readme","dependencies": {"express": "^4.17.1"},"devDependencies": {"nodemon": "^2.0.7"}
}
2.2 关键字段
- name: 项目的名称,应为小写字母,可以包含连字符和下划线。
- version: 项目的当前版本,遵循语义化版本控制(semver)。
- description: 项目的简短描述。
- main: 应用程序的入口文件(通常是主 JavaScript 文件)。
- scripts: 定义一组可以通过
npm run <script-name>
运行的脚本命令。常见的脚本包括:"start"
: 通常用于启动应用程序。"test"
: 用于运行测试。
- repository: 关于源代码托管仓库的信息。
- keywords: 一个字符串数组,帮助人们在搜索时找到你的项目。
- author: 项目作者的名字和联系方式。
- license: 项目的许可证。
- bugs: 报告问题的地址。
- homepage: 项目的主页 URL。
- dependencies: 一个对象,指定了项目的运行时依赖及其版本。
- devDependencies: 一个对象,指定了项目的开发时依赖,仅在开发过程中需要。
2.3 常用命令
- 安装依赖: 运行
npm install
安装package.json
中列出的所有依赖。 - 添加依赖: 运行
npm install <package-name>
添加一个新的依赖,并自动更新package.json
。 - 运行脚本: 运行
npm run <script-name>
执行scripts
部分定义的脚本。
2.4 自定义脚本
你可以在 scripts
部分定义任何自定义脚本。例如:
"scripts": {"start": "node index.js","test": "echo \"Error: no test specified\" && exit 1","build": "webpack --config webpack.config.js","lint": "eslint ."
}
这样你就可以运行自定义命令,比如 npm run build
使用 Webpack 打包你的应用程序,或者 npm run lint
使用 ESLint 检查你的代码。
三、element-plus 完整示例
业内有名的组件库 element-plus 其 package.json
文件:
{"name": "element-plus","version": "2.7.1","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"},"./global": {"types": "./global.d.ts"},"./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.3.1","@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": "b0ce448b4dc7c8981ed73bd2554f4dbbe05d1446"
}
3.1 main 和 module
在 package.json
文件中,main
和 module
字段用于指定项目的入口文件,但它们有不同的用途和作用范围,主要与模块系统的选择有关。
1. main 字段
main
字段指定了 Node.js 项目入口文件的路径。它告诉 Node.js 在使用 require()
函数引入模块时应该加载哪个文件。如果没有指定 main
字段,Node.js 默认会寻找项目根目录下的 index.js
文件。
示例
{"main": "index.js"
}
在上面的例子中,如果你的项目被其他项目引入,Node.js 会从 index.js
文件开始加载。
2. module
字段
module
字段用于指定 ECMAScript 模块(ESM)的入口文件路径。它主要面向现代 JavaScript 环境,如使用 import
语句的前端项目或支持 ESM 的 Node.js 项目。这个字段提供了一个入口点,允许 JavaScript 运行时和打包工具(如 webpack、rollup)以 ESM 格式加载模块。
示例
{"module": "index.mjs"
}
在这个例子中,当你的项目被打包工具或支持 ESM 的环境引入时,它会从 index.mjs
文件开始加载。
3. 综合示例
一个完整的 package.json
文件可能同时包含 main
和 module
字段,以便兼容 CommonJS 和 ESM 模块系统。
{"name": "example-project","version": "1.0.0","description": "一个展示 package.json 文件的示例项目","main": "index.js","module": "index.mjs","scripts": {"start": "node index.js","test": "echo \"Error: no test specified\" && exit 1"},"dependencies": {"express": "^4.17.1"},"devDependencies": {"nodemon": "^2.0.7"}
}
通过同时定义 main
和 module
字段,可以确保你的包在不同的模块系统中都能被正确加载和使用。这对于兼容性和灵活性非常重要,尤其是在需要支持多种环境的库或工具中。
3.2 types
types
字段(或 typings
)用于指定 TypeScript 类型定义文件的路径。它通常用于那些用 JavaScript 编写的包,并且希望提供 TypeScript 类型支持。这个字段指向一个包含 TypeScript 声明的文件,通常是 .d.ts
文件。
1. 示例
假设你有一个项目,其中包含一个 TypeScript 类型定义文件 index.d.ts
,你的 package.json
文件可以这样配置:
{"name": "example-project","version": "1.0.0","description": "一个展示 package.json 文件的示例项目","main": "index.js","module": "index.mjs","types": "index.d.ts","scripts": {"start": "node index.js","test": "echo \"Error: no test specified\" && exit 1"},"dependencies": {"express": "^4.17.1"},"devDependencies": {"nodemon": "^2.0.7"}
}
2. TypeScript 类型定义文件的作用
- 提供类型支持: 当使用你的库时,TypeScript 编译器可以引用这个类型定义文件,提供类型检查和代码补全。
- 提高开发体验: 使用 TypeScript 类型定义文件可以使你的库在 TypeScript 项目中更容易使用,因为开发者可以获得更好的代码提示和类型检查。
3. 类型定义文件示例
假设你的项目的主要功能在 index.js
文件中实现,你可以创建一个 index.d.ts
文件来描述这些功能的类型:
index.js
function greet(name) {return `Hello, ${name}!`;
}
module.exports = {greet
};
index.d.ts
export function greet(name: string): string;
4. 发布带有类型定义的包
当你发布带有类型定义文件的包时,TypeScript 项目可以直接使用你的类型定义文件,无需额外配置。这使得你的包对使用 TypeScript 的开发者更加友好。
3.3 styles
styles
字段(虽然不属于官方的 package.json
规范)有时会出现在某些前端项目中,用于指定项目的主要样式表文件路径。这个字段主要用于与构建工具和打包工具(如 webpack)集成,方便这些工具找到并处理样式文件。
1. 示例
假设你有一个项目,其中包含一个主要的 CSS 文件 dist/index.css
,你的 package.json
文件可以这样配置:
{"name": "example-project","version": "1.0.0","description": "一个展示 package.json 文件的示例项目","main": "index.js","module": "index.mjs","types": "index.d.ts","styles": "dist/index.css","scripts": {"start": "node index.js","test": "echo \"Error: no test specified\" && exit 1"},"dependencies": {"express": "^4.17.1"},"devDependencies": {"nodemon": "^2.0.7"}
}
2. 用途
- 构建工具集成: 某些构建工具(如 webpack、rollup)或插件可能会读取
styles
字段,以便自动加载和处理样式文件。 - 模块化 CSS: 当你的包被其他项目引用时,
styles
字段可以帮助开发者快速找到并加载样式文件。
这在一些组件库提供按需加载能力时常见。
3.4 peerDependencies
在 package.json
文件中,dependencies
、devDependencies
和 peerDependencies
是用于管理和声明项目所需依赖的三种不同方式。它们的主要区别在于依赖的用途和安装时机。
1. dependencies
dependencies
字段列出了项目在生产环境中运行所需的包。换句话说,这些依赖是项目在正常运行时必需的。安装项目时,npm install
会自动安装这些依赖。
示例
{"dependencies": {"express": "^4.17.1","lodash": "^4.17.21"}
}
2. devDependencies
devDependencies
字段列出了项目在开发阶段所需的包。这些依赖在项目构建、测试或开发时使用,但在生产环境中不需要。安装项目时,如果使用 npm install --production
或 NODE_ENV=production npm install
,则不会安装这些依赖。
示例
{"devDependencies": {"eslint": "^7.32.0","jest": "^27.0.6"}
}
3. peerDependencies
peerDependencies
字段用来声明项目对某个包的依赖,但是该包应由项目的使用者(即最终用户)来安装。
这在创建插件或库时特别有用,确保依赖的版本与最终使用项目的版本兼容。例如,一个 React 组件库可能会将 react
和 react-dom
声明为 peerDependencies
,以确保使用该库的项目使用的是正确版本的 react
。
示例
{"peerDependencies": {"react": "^17.0.0","react-dom": "^17.0.0"}
}
进一步理解
peerDependencies
字段的主要作用是声明项目对某些依赖包的兼容性要求,但并不直接安装这些依赖包。它通常用于插件或库,以确保这些插件或库与宿主应用的依赖版本一致。
理解 peerDependencies
可以通过以下几个方面来更清晰:
- 声明依赖的兼容性:
当你的库或插件需要与某个主项目共享依赖时,peerDependencies
可以声明这些共享依赖的版本范围。例如,一个 React 组件库可能需要使用者项目中的 react
和 react-dom
,但不希望自己安装这些依赖,因为它们应该由使用者项目来管理和安装。
- 避免版本冲突:
通过使用 peerDependencies
,可以避免安装多个版本的同一个包,从而减少版本冲突的风险。如果每个库都各自安装自己的 react
版本,可能会导致不同版本的 react
互相冲突,从而引发错误。
假设你在开发一个 React 组件库:
package.json
{"name": "my-react-library","version": "1.0.0","peerDependencies": {"react": "^17.0.0","react-dom": "^17.0.0"}
}
使用者项目中安装你的库时,npm 会发出警告,提示需要安装特定版本的 react
和 react-dom
:
npm install my-react-library
如果用户项目中没有安装 react
或 react-dom
,或安装的版本与 peerDependencies
中指定的不兼容,npm 会显示警告信息。
例如,如果用户的项目中安装了 React 16 而不是 React 17,运行 npm install
时可能会看到这样的警告:
npm WARN my-react-library@1.0.0 requires a peer of react@^17.0.0 but none is installed. You must install peer dependencies yourself.
用户需要确保其项目中的依赖版本与 peerDependencies
中声明的版本兼容。通常这意味着用户需要更新其项目中的相关依赖版本:
npm install react@^17.0.0 react-dom@^17.0.0
3.5 exports
exports
字段是在 Node.js 12 及其以上版本中引入的,用于指定模块的导出路径和条件导出。
它提供了一种更精细的方式来定义项目中的入口点和模块分发,支持不同的模块系统(如 CommonJS 和 ES Module)以及不同的运行环境(如浏览器和 Node.js)。
为什么使用 exports
- 更安全的模块导出:通过限制模块的导出路径,防止用户直接访问内部文件结构。
- 条件导出:根据运行环境或模块系统提供不同的导出文件。
- 简化入口点管理:统一管理多入口点。
exports
字段示例
假设你的项目结构如下:
my-package/
├── package.json
├── index.js
├── index.mjs
└── lib/├── feature.cjs├── feature.mjs└── feature.js
你可以在 package.json
中使用 exports
字段来定义不同环境下的导出:
{"name": "my-package","version": "1.0.0","main": "index.js","module": "index.mjs","exports": {".": {"require": "./index.js","import": "./index.mjs"},"./feature": {"require": "./lib/feature.cjs","import": "./lib/feature.mjs","default": "./lib/feature.js"}}
}
解释
-
"."
: 代表包的根路径,定义包的主要入口点。"require"
: 指定 CommonJS 模块系统下的入口点。"import"
: 指定 ES Module 模块系统下的入口点。
-
"./feature"
: 定义my-package/feature
的导出路径。"require"
: 使用 CommonJS 模块系统时,导出./lib/feature.cjs
文件。"import"
: 使用 ES Module 模块系统时,导出./lib/feature.mjs
文件。"default"
: 其他情况使用./lib/feature.js
文件。
更多复杂示例
可以为不同的条件提供更多的导出路径:
{"exports": {".": {"browser": {"import": "./index.browser.mjs","require": "./index.browser.cjs"},"node": {"import": "./index.node.mjs","require": "./index.node.cjs"},"default": "./index.js"},"./feature": {"browser": {"import": "./lib/feature.browser.mjs","require": "./lib/feature.browser.cjs"},"node": {"import": "./lib/feature.node.mjs","require": "./lib/feature.node.cjs"},"default": "./lib/feature.js"}}
}
使用场景
- 多模块系统支持:同时支持 CommonJS 和 ES Module。
- 环境特定导出:为浏览器和 Node.js 环境提供不同的导出文件。
- 模块拆分:可以根据需要将模块拆分成多个文件,并通过
exports
字段统一管理。
通过合理使用 exports
字段,可以使你的 Node.js 包在现代 JavaScript 生态系统中更具适应性和灵活性。
3.6 unpkg 和 jsdelivr
unpkg 和 jsDelivr 都是用于提供前端资源(如 JavaScript、CSS、图像等)的 CDN(内容分发网络)服务,使得开发者可以方便地在项目中引用这些资源而无需自行托管。
unpkg
{"unpkg": "dist/umd/package.min.js"
}
这个字段告诉 unpkg CDN,当有人访问该包时,应该返回 dist/umd/package.min.js
文件。
unpkg 是一个快速、稳定的 CDN,用于托管 npm 中的开源包。它允许你通过简单地提供包名和版本号来直接引用 npm 包中的文件,而无需安装这些包或手动下载文件。通过 unpkg,你可以在浏览器中直接访问 npm 包中的任何文件。
例如,如果你想在项目中使用 React,你可以通过以下方式引用 React 的主要文件:
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
jsDelivr
{"jsdelivr": "dist/umd/package.min.js"
}
这个字段告诉 jsDelivr CDN,当有人访问该包时,应该返回 dist/umd/package.min.js
文件。
jsDelivr 是另一个流行的 CDN,提供了更多的功能和定制选项。它支持各种前端资源,包括 JavaScript 库、CSS 框架、图像、字体等。jsDelivr 的优点之一是它有多个节点,因此可以提供更快的下载速度和更高的可用性。
与 unpkg 类似,你可以使用 jsDelivr 来直接引用各种开源资源,而无需自行下载和托管。例如,你可以通过以下方式引用 jQuery:
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
共同特点
- 快速可靠:unpkg 和 jsDelivr 都是快速可靠的 CDN 服务,能够提供高性能的前端资源加载。
- 免费使用:它们都是免费使用的,任何人都可以直接引用它们提供的资源。
- 支持版本控制:你可以通过指定版本号来确保获取特定版本的资源,这有助于保持你的应用程序的稳定性和一致性。
如何选择
- 如果你只需要简单快速地引用 npm 包中的文件,并且不需要太多的定制选项,那么 unpkg 是一个不错的选择。
- 如果你需要更多的功能和定制选项,或者希望提供更好的性能和可用性,那么可以考虑使用 jsDelivr。
无论你选择哪个 CDN,它们都可以帮助你更轻松地管理前端资源,加速网站加载速度,并提高开发效率。
3.7 publishConfig
publishConfig
字段是 package.json
文件中的一个配置项,用于指定发布 npm 包时的额外设置。
通过 publishConfig
字段,你可以设置一些发布相关的配置,例如发布时的访问权限、发布时所使用的注册表等。
示例
以下是一个典型的 publishConfig
字段的示例:
{"name": "my-package","version": "1.0.0","description": "A sample package","main": "index.js","publishConfig": {"access": "public","registry": "https://registry.npmjs.org/"}
}
在这个示例中,publishConfig
字段指定了两个选项:
access
: 指定了发布时的访问权限。在这个例子中,设置为"public"
表示发布后的包是公共的,所有人都可以访问。registry
: 指定了发布时所使用的 npm 注册表的 URL。在这个例子中,设置为"https://registry.npmjs.org/"
表示发布到 npm 公共注册表。
使用场景
- 发布权限管理: 如果你想发布一个私有的 npm 包,你可以将
access
设置为"restricted"
,只允许有权限的用户访问。 - 自定义注册表: 如果你使用了自定义的 npm 注册表,你可以通过
registry
字段来指定发布时所使用的注册表的 URL。
注意事项
publishConfig
字段通常用于在发布 npm 包时自定义配置,但它并不是必需的。如果你没有特殊的需求,可以不用设置它。- 如果你使用的是默认的 npm 公共注册表,并且不需要设置其他发布参数,那么通常不需要额外配置
publishConfig
。
理解 publishConfig
字段的用途和配置选项,可以帮助你更好地管理和发布 npm 包。
3.8 sideEffects
sideEffects
是一个用于告知 webpack 和其他模块打包工具模块是否有副作用(side effects)的字段,出现在模块的 package.json
文件中。副作用是指模块执行时,不仅仅是导出一个值,而是会执行一些额外的操作,例如修改全局变量、执行某些代码等。
为什么需要 sideEffects
对于纯粹的 JavaScript 模块,大部分情况下,模块导入后只是为了获取导出的值,而不会对环境产生任何副作用。然而,一些模块可能会包含副作用,这些副作用可能会影响到整个应用程序的行为,甚至影响到其他模块。在模块打包时,如果可以确定某个模块没有副作用,打包工具就可以进行更多的优化,例如删除未使用的代码、提取公共代码等。而如果某个模块包含了副作用,打包工具则需要谨慎处理,以避免意外行为。
有关模块包含副作用的内容可以阅读 WHAT - Webpack 详解系列(七)。
Webpack 4 中新增了一个 sideEffects 特性,它允许我们通过配置标识我们的代码是否有副作用,从而提供更大的压缩空间。模块的副作用指的是:模块执行的时候除了导出成员,是否还做了其他的事情。这个特性一般只有我们去开发一个 npm 模块时才会用到。以自定义 npm 项目为例,那此时 Webpack 在打包某个模块之前,会先检查这个模块所属的 package.json 中的 sideEffects 标识,以此来判断这个模块是否有副作用,如果没有副作用的话,这些没用到的模块就不再被打包。
sideEffects
的取值
sideEffects
字段的取值可以是以下三种形式之一:
false
: 表示模块没有副作用。这意味着打包工具可以安全地进行一些额外的优化。true
: 表示模块具有副作用。在打包时,打包工具将假定该模块具有副作用,并相应地处理它。- 数组: 数组中的每个元素是一个匹配模式,表示具有副作用的文件路径。这些路径可以是文件名、文件夹名,也可以是通配符表达式。
示例
以下是一个 sideEffects
字段的示例:
{"name": "my-package","version": "1.0.0","description": "A sample package","main": "index.js","sideEffects": ["*.css", "*.scss", "*.less"]
}
在这个示例中,sideEffects
字段告知打包工具,在打包时应该考虑所有的 .css
、.scss
和 .less
文件,因为它们可能包含一些样式文件的副作用。
使用场景
- 优化打包: 通过准确地声明模块是否具有副作用,打包工具可以更好地进行代码优化,提高打包性能。
- 避免意外行为: 对于具有副作用的模块,打包工具可以采取适当的措施,以避免意外行为,例如不删除未使用的代码等。
注意事项
- 在很多情况下,你可以放心地将
sideEffects
设置为false
,因为大多数模块都不会有副作用。 - 如果你不确定模块是否具有副作用,最好是不设置
sideEffects
字段,或者设置为true
,以确保不会因为错误的优化而导致意外行为。
通过正确地设置 sideEffects
字段,可以帮助你更好地管理和优化你的模块打包过程。
3.9 browserslist
browserslist
是一个用于指定项目目标浏览器的字段,出现在项目根目录下的 package.json
文件中。它告知前端工具(例如 Autoprefixer、Babel、PostCSS 等)需要支持哪些浏览器版本,以便自动添加适当的 CSS 前缀或将 JavaScript 代码转换成兼容性更好的形式。
为什么需要 browserslist
Web 开发中,不同的浏览器对于一些 CSS 属性和 JavaScript 特性的支持程度有所差异。为了确保项目在不同浏览器中的兼容性,开发者通常需要根据项目需求选择目标浏览器,并进行相应的兼容性处理。
browserslist
的出现简化了这个过程,使得开发者只需在项目中设置一次目标浏览器列表,然后前端工具就可以根据这个列表自动进行相应的处理,大大提高了开发效率。
browserslist
的使用
你可以在 package.json
文件中的 browserslist
字段中指定目标浏览器的列表,也可以通过 .browserslistrc
文件或者 browserslist
配置文件来配置。
示例 browserslist
配置:
"browserslist": ["last 2 versions","> 1%","IE 11"
],
这个配置表示项目的目标浏览器为:
- 最近两个版本的所有浏览器
- 浏览器市场份额大于 1% 的浏览器
- Internet Explorer 11
"browserslist": ["> 1%","not ie 11","not op_mini all"
],
这个配置表示项目的目标浏览器为:
- 浏览器市场份额大于 1% 的浏览器
- 不包括 Internet Explorer 11
- 不包括 Opera Mini 浏览器
使用场景
- CSS 兼容性处理: Autoprefixer 等工具可以根据
browserslist
配置自动添加 CSS 前缀,以确保样式在目标浏览器中的兼容性。 - JavaScript 转换: Babel 等工具可以根据
browserslist
配置自动将 ES6+ 的 JavaScript 代码转换成向下兼容的代码,以确保在目标浏览器中的兼容性。
注意事项
- 选择目标浏览器: 在选择目标浏览器时,应考虑项目的实际需求和用户群体使用的浏览器情况,避免过度或不必要的兼容性处理。
- 定期更新配置: 随着浏览器的更新和市场份额的变化,建议定期更新
browserslist
配置,以确保项目始终针对最新的浏览器进行优化。
通过合理配置 browserslist
,可以帮助开发者更轻松地管理项目的浏览器兼容性,提高开发效率。
相关文章:

WHAT - package.json 解释
目录 一、前言二、介绍2.1 package.json 文件示例2.2 关键字段2.3 常用命令2.4 自定义脚本 三、element-plus 完整示例3.1 main 和 module1. main 字段2. module 字段3. 综合示例 3.2 types1. 示例2. TypeScript 类型定义文件的作用3. 类型定义文件示例4. 发布带有类型定义的包…...

Python知识点14---被规定的资源
提前说一点:如果你是专注于Python开发,那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了,而如果你和作者一样只是操作其他技术的Python API那就足够了。 在Python中被规定的东西不止有常识中的那些关键字、构造器等编程语言…...

文献阅读:GCNG:用于从空间转录组数据推断基因相互作用的图卷积网络
文献介绍 「文献题目」 GCNG: graph convolutional networks for inferring gene interaction from spatial transcriptomics data 「研究团队」 Ziv Bar-Joseph(美国卡内基梅隆大学) 「发表时间」 2020-12-10 「发表期刊」 Genome Biology 「影响因子…...

Mybatis第一讲——你会Mybatis吗?
文章目录 什么是MybatisMybatis的作用是什么 Mybatis 怎么使用注解的方式注解的多种使用Options注解ResultType注解 XML的方式update标签 #{} 和 ${}符号的区别#{}占位${}占位 ${}占位的危险性(SQL注入)数据库连接池 什么是Mybatis 首先什么是Mybatis呢?Mybatis是一…...

【HarmonyOS】List组件多层对象嵌套ForEach渲染更新的处理
【HarmonyOS】List组件多层对象嵌套ForEach渲染更新的处理 问题背景: 在鸿蒙中UI更新渲染的机制,与传统的Android IOS应用开发相比。开发会简单许多,开发效率提升显著。 一般传统应用开发的流程处理分为三步:1.画UI,…...

PostgreSQL基础(六):PostgreSQL基本操作(二)
文章目录 PostgreSQL基本操作(二) 一、字符串类型 二、日期类型 三、...

【前端部署——vercel】部署next.js使用了prisma的项目
部署流程参考 https://blog.csdn.net/qq_51116518/article/details/137042682 问题 PrismaClientInitializationError: Prisma has detected that this project was built on Vercel, which caches dependencies. This leads to an outdated Prisma Client because Prisma’s …...

Vue插槽与作用域插槽
title: Vue插槽与作用域插槽 date: 2024/6/1 下午9:07:52 updated: 2024/6/1 下午9:07:52 categories: 前端开发 tags:VueSlotScopeSlot组件通信Vue2/3插槽作用域API动态插槽插槽优化 第1章:插槽的概念与原理 插槽的定义 在Vue.js中,插槽(…...

类和对象(一)(C++)
类和对象: 类的引入: C语言结构体中只能定义变量,在C中,结构体内不仅可以定义变量,也可以定义函数。比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量&#…...

【免费Web系列】JavaWeb实战项目案例六
这是Web第一天的课程大家可以传送过去学习 http://t.csdnimg.cn/K547r 员工信息-删除&修改 前面我们已经实现了员工信息的条件分页查询以及新增操作。 关于员工管理的功能,还有两个需要实现: 删除员工 修改员工 除了员工管理的功能之外&#x…...

git分布式版本控制系统(四)
目前世界上最先进的分布式版本控制系统 官方网址:https://git-scm.com 学习目标: 1 了解 git 前世今生 2 掌握 git 基础概念、基础操作 3 各种 git 问题处理 4 互联网常用 gitflow(工作流程规范) 5 git 代码提交规范 6 git 分支管理及命名规范 常见问…...

【React篇】简述React-Router 的实现原理及工作方式
React Router 路由的基础实现原理分为两种,如果是切换 Hash 的方式,那么依靠浏览器 Hash 变化即可;如果是切换网址中的 Path,就要用到 HTML5 History API 中的 pushState、replaceState 等。在使用这个方式时,还需要在…...

Django里多app
在 Django 里的某一个项目,里面得包含很多 App (功能),那么如何在该项目里管理这么多App呢? 先说明下背景:未先创建 apps 文件夹来存各个app文件夹,直接在项目文件目录里创建各个app。为了便于管理,得将各…...

Prime1 - 信息收集和分析能力的试炼
主机发现 nmap扫描与分析 端口22、80 详细扫描;linux、ubuntu、 udp扫描 端口都是关闭的 脚本扫描 web渗透 打开只有一张图片;源码有图片和一个alt:hnp security不知道有啥用,先记录下来吧 继续web渗透思路走吧,目录…...

3.location的写法
location的写法 一、location的写法1、 精确匹配2、~ 以正则表达式匹配请求,区分大小写3、~* 以正则匹配请求,不区分大小写4、^~ 不以正则的方式匹配请求 二、stub_status模块显示工作状态三、url地址重写 rewrite模块1、语法2、针对项目结构有变化3、网…...

AndroidStudio设置允许APP获取定位权限
1. 在AndroidManifest.xml中声明权限 常用的定位权限有以下两种: <uses-permission android:name"android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name"android.permission.ACCESS_COARSE_LOCATION"/>2. …...

Spring Boot 统一数据返回格式
在 Spring Boot 项目中,统一的数据格式返回是一种良好的实践,它提高了代码的可维护性和一致性,并改善了客户端与服务端之间的通信。本文将介绍如何在 Spring Boot 中实现统一的数据格式返回。 1 为什么需要统一数据返回格式 ⽅便前端程序员更…...

Android 项目Gradle文件讲解(Groovy和Kotlin)
Android 项目Gradle文件讲解(Groovy和Kotlin) 前言正文一、Gradle的作用二、Gradle的种类① 工程build.gradle② 项目build.gradle③ settings.gradle④ gradle.properties⑤ gradle-wrapper.properties⑥ local.properties 三、Groovy和Kotlin的语言对比…...

python-最接近target的值
【问题描述】:给定一个数组,在数组中找到两个数,使它们的和最接近目标值的值但不超过目标值,然后返回它们的和。 【问题示例】:输入target15,array[1,3,5,11,7],输出14,31114。 完整代码如下: …...

转换张量形状:`nlc_to_nchw` 函数详解
在深度学习和计算机视觉领域,张量的形状转换是一个常见的操作。本文将详细讲解一个用于形状转换的函数 nlc_to_nchw,它能够将形状为 [N, L, C] 的张量转换为 [N, C, H, W] 的张量。 函数定义 def nlc_to_nchw(x, hw_shape):"""Convert …...

「架构」云上自动化运维及其应用
随着云计算的普及,自动化运维成为企业提升运营效率和降低成本的关键。本文通过分析一家中型企业实施云上自动化运维(CloudOps)的案例,探讨了自动化监控、配置管理和持续集成/持续部署(CI/CD)三个核心模块的实际应用。文章详细阐述了每个模块的技术选型、实施原因、优缺点…...

分布式和集群的区别
分布式系统(Distributed System)和集群(Cluster)是两个经常被提及的计算机科学概念,它们在提高系统性能和可靠性方面都扮演着重要角色,很多同学会觉得这俩个是同一种东西,但事实上它们之间有着本…...

最新h5st(4.7.2)参数分析与纯算法还原(含算法源码)
文章目录 1. 写在前面2. 加密分析3. 算法还原 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…...

Spark大数据 掌握RDD的创建
在Apache Spark中,弹性分布式数据集(Resilient Distributed Dataset,简称RDD)是一个核心的数据结构,用于表示不可变、可分区、可并行操作的元素集合。理解并掌握RDD的创建是使用Spark进行大数据处理的关键步骤之一。 …...

Chrome谷歌浏览器如何打开不安全页面的禁止权限?
目录 一、背景二、如何打开不安全页面被禁止的权限?2.1 第一步,添加信任站点2.2 第二步,打开不安全页面的权限2.3 结果展示 一、背景 在开发过程中,由于测试环境没有配置 HTTPS 请求,所以谷歌浏览器的地址栏会有这样一…...

3D目标检测入门:探索OpenPCDet框架
前言 在自动驾驶和机器人视觉这两个飞速发展的领域中,3D目标检测技术扮演着核心角色。随着深度学习技术的突破性进展,3D目标检测算法的研究和应用正日益深入。OpenPCDet,这个由香港中文大学OpenMMLab实验室精心打造的开源工具箱,…...

JS异步编程
目录 概念定时器Promise对象概念 单线程模型指的是,JavaScript 只在一个线程上运行。也就是说,JavaScript 同时只能执行一个任务,其他任务都必须在后面排队等待。JavaScript 只在一个线程上运行,不代表 JavaScript 引擎只有一个线程。事实上,JavaScript 引擎有多个线程,…...

多元联合分布建模 Copula python实例
多元联合分布建模 Copula python实例 目录 库安装 实例可视化代码 库安装 pip install copulas 实例可视化代码 import numpy as np import pandas as pd from copulas.multivariate import GaussianMultivariate# Generate some example data np.random.seed(42) data = …...

单号日入50+,全自动挂机赚钱
大家好!今天我为大家精心挑选了一个极具潜力的副业项目——“游戏工作室自由之刃2:单号日入50,全自动挂机赚钱”。 传奇游戏,无疑是许多人心中那段青春时光的珍贵回忆。 即便是其手游版本,也依旧保持着极高的热度和人…...

LabVIEW老程序功能升级:重写还是改进?
概述:面对LabVIEW老程序的功能升级,开发者常常面临重写与改进之间的选择。本文从多个角度分析两种方法的利弊,并提供评估方法和解决思路。 重写(重新开发)的优势和劣势: 优势: 代码清晰度高&a…...