关于javascript:结合实践解读-packagejson

49次阅读

共计 13790 个字符,预计需要花费 35 分钟才能阅读完成。

前言

平时大家在公司接手一个已有我的项目的时候,首先会看的是什么呢?我的习惯是先看 README.mdpackage.json

通过 README 理解我的项目是做什么和留神点,通过 package.json 理解我的项目波及的技术栈和 npm 库等等。

明天就来深刻理解下 package.json 这个文件,不仅是解释具体字段含意与使用(疏忽局部第三方字段本文就不介绍了),更重要的是想借此扩大总结下波及工作中与社区出名库的一些实际,对咱们本人做开源我的项目也有肯定帮忙。

本文同步于我的 Github 集体博客

常见配置字段

name

我的项目的名称,该字段决定了你公布的包在 npm 的名字,也就是平时装置库的包名了 npm i 包名

该字段也是有 命名标准 的,如下:

  • 名称的长度必须小于或等于 214 个字符,不能以 ._结尾。不要应用 空格<>[]{}|\^% 等。
  • 不能应用大写字母命名
  • 如果要公布到 npm 上,名称不能和社区已有的反复,能够应用 npm view 命令查问,或间接上 npm 查。比方随机想一个包名,jacky-summer-utils
npm view jacky-summer-utils

# 报 404,证实该名称可用
npm ERR! code E404

除了惯例命名,咱们还会见到社区有 @ 结尾的命名,格局如:@[scope]/[name]

例子:@ant-design/icons@babel/preset-env,这代表一个组织下的库。

如果你也想应用这样的构造,比方用本人名字 @ 结尾的话,须要在本人 npm 上建设组织(Add Organization),不这么做的话包名带 @ 则公布时会不通过。

比方我创立了个组织 @summer-toolkit,包名是 config,则我的这个包和name 值就命名为 @summer-toolkit/config

"name": "@summer-toolkit/config"

version

我的项目版本号 ,当公布 npm 包时nameversion这两个字段是必须的,两个独特形成惟一的我的项目标识,通过更改 version 来对你的 npm 包进行公布更新。

"version": "1.1.0"

通常举荐应用 semver 版本控制策略,开源我的项目也通常遵循这个语义化标准

版本格局:主版本号. 次版本号. 订正号,版本号递增规定如下:

  1. 主版本号 Major,当你做了不兼容的 API 批改,通常在波及重大性能更新,产生了破坏性变更时会更新此版本号
  2. 次版本号 Minor,引入了新性能,但未产生破坏性变更,仍然能够向下兼容时会更新此版本号,可了解为 Feature 版本
  3. 订正号 Patch,修复了一些 bug,也未产生破坏性变更时会更新此版本号,可了解为 Bug Fix

当要公布大版本或者外围的性能时,无奈确定该版本性能稳固,可能无奈满足预期的兼容性需要,这个时候就须要通过公布 后行版本 。后行版本通过会加在版本号的前面,通过- 号连贯以 . 分隔的标识符和版本编译信息:

  • 外部版本(alpha):通常该版本软件的 Bug 较多,须要继续批改
  • 公测版本(beta):绝对于 alpha 版已有很大改良,会持续加新个性,修复了较重大的谬误,但仍然存在一些缺点
  • 候选版本(rc,即 release candiate):正式版本的候选版本,该版本个别能够说谬误较少了,根本是修复而不是再加新个性了
react:16.3.0-alpha.0
vue:3.2.34-beta.1、3.0.0-rc.13

比方想查看 vue 的历史 Tag 版本,可看到 vue 是比拟严格遵循 semver 版本标准的:

# 查看 vue 历史版本
npm view vue versions
# 查看 vue 最新版本
npm view vue version

一些问题解答:

在库初始开发阶段,该如何进行版本控制?

最简略的做法是以 0.1.0 作为你的初始化开发版本,并在后续的每次发行时递增次版本号。当最终实现用于正式线上环境了,这时就能够改为 1.0.0,之后就都依照 Semver 标准走了

公司一些较小的公共库版本,怎么保护?

这个可视乎库规模和应用人数多少决定,像个别公司大部分私库测试环境都可间接公布 beta 版本,等 UAT/ 线上就是间接走的正式版本

description

我的项目的形容,信息会间接展现在 npm 官网,通过它能让他人能疾速你的我的项目。

dayjs 库的:

"description": "2KB immutable date time library alternative to Moment.js with the same modern API"

Webpack 的形容就绝对长一些了:

"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",

keywords

我的项目关键词。关键词填得准,可不便在 npm 上更好地检索

如 Ant Design 的 keywords

"keywords": [
    "ant",
    "component",
    "components",
    "design",
    "framework",
    "frontend",
    "react",
    "react-component",
    "ui"
],

Redux 的:

"keywords": [
    "redux",
    "reducer",
    "state",
    "predictable",
    "functional",
    "immutable",
    "hot",
    "live",
    "replay",
    "flux",
    "elm"
],

repository

我的项目的仓库地址以及版本控制信息,可通过该字段找到代码托管地址

// Ant Design
"repository": {
    "type": "git",
    "url": "https://github.com/ant-design/ant-design"
}

license

我的项目的开源许可证,阐明你的库应用哪个许可证,用户爱护你本人和贡献者。

没有 License 的内容是默认会被版权保护,如果你容许社区内开发者可基于你的我的项目二次革新等,须要抉择适合的许可证能力赋予任何人放心使用(革新、分享等)。

目前 Github 咱们熟知的大部分我的项目都是 MIT 许可证

 "license": "MIT"

MIT 根本就是没有任何限度,示意任何人都能够售卖我的软件,甚至能够用作者的名字促销。
我的项目的版权领有人能够应用开源许可证来限度源码的应用、复制、批改和再公布等行为,

通常开源我的项目都会在根目录下新建 LICENSE 文件,并将许可证的文本复制到这里。如看下 Vue 的

对于公司不开源的我的项目,这个配置项个别可疏忽。

理解具体可浏览:

  • 七种开源许可证
  • 如何为本人的 Github 项目选择开源许可证?

private

设置为公有避免意外公布。如果你不心愿把我的项目公布到 npm 仓库上,能够将 private 设为 true。

"private": true

当设置为 true 时,执行 npm publish 会报错,npm 会回绝公布这个我的项目。

像公司的非开源我的项目就能够设置为 true,避免被无意间公布进来

publishConfig

npm 包公布应用的配置 ,通常publishConfig 会配合 private 应用;如果只想让模块公布到特定 npm 仓库,就能够这样来配置

"publishConfig": {
    "registry": "https://registry.npmjs.org", // 私源地址配置
    "tag": "beta", // 如果没有指定 tag,默认是 latest
    "access": "public"
}
  • registry:npm 私源地址
  • tag:指定以后版本对应的 tag
  • access:包的拜访级别。如果是 scoped 包(如 @babel/xxx,@ant-design/xxx),肯定须要设置为 public(除非退出付费打算)

bugs

bug 反馈地址,通过该链接向你的仓库反馈 bug,github 上的个别都是 github issue 页的链接

"bugs": "https://github.com/webpack/webpack/issues",

homepage

我的项目主页地址,如:仓库 Github 链接、官网地址、文档地址等

// Ant Design:"homepage": "https://ant.design"

// Redux:"homepage": "http://redux.js.org"

homepage字段会展现在 npm 的这个中央:

homepage 还可设置利用的根门路,具体可见【小技巧】package.json 中 homepage 属性的作用

author

我的项目的作者(信息)

  • 字符串模式
"author": "JackySummer"
  • 对象模式:蕴含必选的 name 属性和可选的 url、email 属性
"author": {
    "name": "JackySummer",
    "email": "xxxxx@qq.com",
    "url": "https://jackylin.vercel.app"
}

也能够用上面的字符串简写,npm 会帮咱们解析:

"author": "JackySummer <xxxxx@qq.com> (https://jackylin.vercel.app)"

contributors

贡献者信息 。对象格局数组,对象的内容和author 一样

"contributors": [{
    "name": "JackySummer",
    "email": "xxxxx@qq.com",
    "url": "https://jackylin.vercel.app"
}]

通常对应的,Github 开源我的项目通常会有 /.github/CONTRIBUTING.md奉献指南这个文件,外面也可能有列出一些贡献者简要信息等,如 Vue 的 CONTRIBUTING.md

scripts

我的项目内置的脚本命令,这一字段下的货色是我比拟感兴趣的,通常能够看到我的项目的启动形式、prettier/eslint 运行脚本,是否用了单元测试等等 …

找到我的项目的 /node_modules/.bin 目录,我的项目 npm run xx的底层调用命令在这里都能找到

npm 脚本的原理:每当执行 npm run,就会主动新建一个 Shell,在这个 Shell 外面执行指定的脚本命令。因而,只有是 Shell(个别是 Bash)能够运行的命令,就能够写在 npm 脚本外面

比方咱们装置了 eslint,scripts外面配置:

"eslint": "eslint --fix --ext .ts,.tsx ."

而不用写成门路的形式

"eslint": "./node_modules/.bin/eslint --fix --ext .ts,.tsx .",

npm scripts 钩子

npm 脚本有 pre 和 post 两个钩子,如 运行 npm run install 的时候,分 3 个阶段:

  1. 查看 scripts 对象中是否存在 preinstall 命令,如果有,先执行该命令;
  2. 查看是否有 install 命令,有的话运行 install 命令,没有的话报错;
  3. 查看是否存在 postinstall 命令,如果有,执行 postinstall 命令

npm 默认提供上面这些钩子。

prepublish,postpublish
preinstall,postinstall
preuninstall,postuninstall
preversion,postversion
pretest,posttest
prestop,poststop
prestart,poststart
prerestart,postrestart

另外,咱们自定义的脚本命令也能够加上 pre 和 post 钩子。

上面举例我工作中应用到 npm 钩子的场景:

  1. 所有我的项目都由 npm 迁徙 pnpm,但有的人没留神或忘了,拿到我的项目还是应用 npm 装置,也产生了 package-lock.json 文件

解决方案:在 npm install 之前限制住只能应用 pnpm 装置。.gitignore 增加 npm 和 yarn 的 lock 文件

"scripts": {"preinstall": "npx only-allow pnpm"}

.gitignore

yarn.lock
package-lock.json
  1. 第三方库有 Bug,如何长期紧急修复

这个以前遇过,年代久远了举不出例子来了,找了他人的文章能够理解下:

patch-package 和 postinstall:【十分实用】如何优雅地解决 npm 依赖 bug

理解更多 npm scripts 可参考学习:npm scripts 使用指南


倡议 script 有约定俗成的标准脚本命令,进步可读性与升高保护老本

来看下一些开源我的项目的 scripts 配置:

Vue:

 "scripts": {
    "dev": "rollup -w -c scripts/config.js --environment TARGET:full-dev",
    "dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:runtime-cjs-dev",
    "dev:esm": "rollup -w -c scripts/config.js --environment TARGET:runtime-esm",
    "dev:ssr": "rollup -w -c scripts/config.js --environment TARGET:server-renderer",
    "dev:compiler": "rollup -w -c scripts/config.js --environment TARGET:compiler",
    "build": "node scripts/build.js",
    "build:ssr": "npm run build -- runtime-cjs,server-renderer",
    "build:types": "rimraf temp && tsc --declaration --emitDeclarationOnly --outDir temp && api-extractor run && api-extractor run -c packages/compiler-sfc/api-extractor.json",
    "test": "npm run ts-check && npm run test:types && npm run test:unit && npm run test:e2e && npm run test:ssr && npm run test:sfc",
    "test:unit": "vitest run test/unit",
    "test:ssr": "npm run build:ssr && vitest run server-renderer",
    "test:sfc": "vitest run compiler-sfc",
    "test:e2e": "npm run build -- full-prod,server-renderer-basic && vitest run test/e2e",
    "test:transition": "karma start test/transition/karma.conf.js",
    "test:types": "npm run build:types && tsc -p ./types/tsconfig.json",
    "format": "prettier --write --parser typescript \"(src|test|packages|types)/**/*.ts\"","ts-check":"tsc -p tsconfig.json --noEmit","ts-check:test":"tsc -p test/tsconfig.json --noEmit","bench:ssr":"npm run build:ssr && node benchmarks/ssr/renderToString.js && node benchmarks/ssr/renderToStream.js","release":"node scripts/release.js","changelog":"conventional-changelog -p angular -i CHANGELOG.md -s"
  },

dayjs:

 "scripts": {
    "test": "TZ=Pacific/Auckland npm run test-tz && TZ=Europe/London npm run test-tz && TZ=America/Whitehorse npm run test-tz && npm run test-tz && jest",
    "test-tz": "date && jest test/timezone.test --coverage=false",
    "lint": "./node_modules/.bin/eslint src/* test/* build/*",
    "prettier": "prettier --write \"docs/**/*.md\"","babel":"cross-env BABEL_ENV=build babel src --out-dir esm --copy-files && node build/esm","build":"cross-env BABEL_ENV=build node build && npm run size","sauce":"npx karma start karma.sauce.conf.js","test:sauce":"npm run sauce -- 0 && npm run sauce -- 1 && npm run sauce -- 2  && npm run sauce -- 3","size":"size-limit && gzip-size dayjs.min.js"
  },

config

用于增加命令行的环境变量,即咱们脚本在运行时的参数。

"config" : {"port" : "8080"},
"scripts" : {"start" : "node server.js"}

在 server.js 脚本就能够援用 config 字段的值

http
  .createServer(...)
  .listen(process.env.npm_package_config_port) // 8080

执行 npm run start 命令时,这个脚本就能够失去值。

用户能够扭转这个值

npm config set foo:port 80

这个字段没用过,实战中这些配置个别不会间接写在 package.json 文件外面

例子援用自 config 字段

engines

申明我的项目须要在怎么的 node 环境下运行,曾遇过比拟老旧的我的项目,甚至可能要降级 node 版本能力跑起来。这时能够给我的项目增加字段,阐明哪个版本下运行能跑起来我的项目,当然你当初正保护开发的我的项目也举荐补充下。

"engines": {
    "node": ">=14.16.0",
    "pnpm": ">=6 <7"
},

engines只是起一个阐明的作用,即便版本不符合要求也丝毫不影响装置应用。

但如果真的遇上对 node 版本要求比拟严格的我的项目,就能够在 .npmrc文件设置

engine-strict = true

这时本地 node 版本不匹配的话就会报错 Unsupported engine,要求你必须切换 engines 配置的对应版本能力失常装置

workspaces

monorepo 我的项目的工作区配置,用于在本地的根目录下治理多个子项目,能够主动地在 npm install 时将 workspaces 上面的包,软链到根目录的 node_modules 中,而不必手动执行 npm link 操作

workspaces 字段接管一个数组,数组里能够是文件夹名称或者通配符,通常子项目都会治理在 packages 目录下。比方:

  "workspaces": ["packages/*"]

Babel 的配置:

  "workspaces": [
    "codemods/*",
    "eslint/*",
    "packages/*",
    "test/esm",
    "test/runtime-integration/*",
    "benchmark"
  ],

files

我的项目公布时蕴含的文件,配置格局为数组,能够指定独自的文件或整个文件夹。

如 Ant Design:

"files": [
    "dist",
    "lib",
    "es"
]

申明 files 字段后,当该 npm 包被装置时,装置的是 files 字段指定的内容,从而做到精准管制公布内容,也管制了 npm 包大小。

如果有不想提交的文件,能够在我的项目根目录中新建一个 .npmignore 文件进行配置,申明不须要提交的文件;写在这里的文件即便 files 申明了也不会被提交,这是为了避免垃圾无用文件被推到 npm 上

.vscode

sideEffects

申明设置哪些模块具备副作用,让打包工具晓得你的模块是否是“纯”的以此更好的 Tree Shaking。

首先要晓得什么会让一个模块有副作用?

例如批改一个全局变量,发送 API 申请,或导出 CSS,是否重写了原生对象办法,总结起来就是函数可能对外部产生影响的行为

window.foo = 'global foo'

Tree Shaking 怎么优化的

Webpack 的 Tree Shaking 机制由 optimization.usedExportssideEffects 独特承当

  1. 通过设置 usedExports 为 true,示意模块只导出被应用的成员,配合 terser 删除我的项目所有模块中未被援用的导出变量
module.exports = {
  optimization: {usedExports: true, // 作用于代码语句层面,只导出(export)有应用的变量 / 办法},
}

当然这个 webpack 打包生产环境默认开启的

  1. 通过 package.json 配置的 sideEffects,用于标记整个模块的副作用。

sideEffects 设为 false,示意没有任何模块具备副作用,所有模块都是 ” 纯 ” 的,即打包的时候不论它是否有没有副作用,只有它没有被援用,整个模块 / 包都会被残缺的移除

"sideEffects": false

也能够应用字符串数组来列出哪些文件具备副作用

如 Ant Design 的 sideEffects 申明如下,告知这些文件有副作用,引入后不能被删除

"sideEffects": [
    "dist/*",
    "es/**/style/*",
    "lib/**/style/*",
    "*.less"
],

type

定义 package.json 文件和及其所在目录根目录中 .js 文件和没有拓展名文件的解决形式

默认值为 commonjs

"type": "commonjs"

比方咱们在我的项目根目录下新建两个文件:

// test.js
export const foo = 10

// index.js
import {foo} from './test.js'

console.log(foo)

而后在控制台运行node index.js,这时会报错

SyntaxError: Cannot use import statement outside a module

因为 Node 的模块化计划采纳的是 CommonJS,而代码是 ES 语法,所以报错;

而 Node 在 v13.2.0 已开始正式反对 ES Modules 个性,咱们可在 package.json 设置:

"type": "module"

这样子 Node 就会用 ES 标准进行解析,从新运行就不会报错了

须要留神的是,无论 package.json 中的 type 字段设置为何值,只有文件后缀是 .mjs的文件都仍然依照 ES 模块标准来解决,.cjs的文件都依照 CommonJS 模块标准来解决,不会受 type影响

types/typings

对外裸露相干的类型,指定 TypeScript 的类型定义的入口文件,前提是我的项目是用 TypeScript 写的,用于不便 IDE 辨认与智能提醒。

"typings": "types/index.d.ts"

应用 typestypings 都能够,作用雷同

main

mainbrowsermodule三个字段都是用于 npm 包的,如果我的项目不是作为 npm 包公布,这三个字段不须要写。

main 字段指定加载的入口文件 ,指向一个兼容 CommonJS 格局的产出,这个文件名是我的项目作为 npm 包被打包时配置的,在 browser 和 node 环境中都能够应用。如应用require 的形式导入该 npm 包时,返回的就是 main 字段指定文件的 module.exports 属性。

当不设置该字段时,默认值是根目录下的index.js 文件

"main": "./index.js"
// Vue
"main": "dist/vue.runtime.common.js"

browser

指向反对 UMD 模块的入口文件 ,这个字段也会被一些公共 CDN 应用,比方 unpkgjsdelivr
也能够间接通过申明 unpkgjsdelivr 字段来配置入口文件,上面再细说这两个字段。

UMD:兼容 CommonJS 和 AMD 的模块,既能够在 node 环境中被 require 援用,也能够在浏览器中间接用 CDN 被 script 标签 引入

unpkg 和 jsDelivr 是开源 CDN 服务

main 字段里指定的入口文件在 browser 和 node 环境中都能够应用。如果只想在 web 端应用,禁止在 server 端应用,能够通过 browser 字段指定入口。

"browser": "./browser/index.js"

module

  • module 指向反对 ESM 模块的入口文件,browser 环境和 node 环境均可应用
"module": "./index.mjs"

如果一个我的项目同时定义了 mainbrowsermodule,Webpack 等构建工具打包的时候会依据环境以及不同的模块标准来进行不同的入口文件查找。

// Vue:"main": "dist/vue.runtime.common.js",
"module": "dist/vue.runtime.esm.js",

总结 npm 包 mainmodulebrowser

  • 导出包只在 web 端应用,并且禁止在 server 端应用,应用 browser
  • 导出包只在 server 端应用,应用 main
  • 导出 ESM 标准的包,应用 module
  • 导出包在 web 端和 server 端都容许应用,应用 modulemain

还有其余具体情况这里就不开展了

exports

如果打包工具反对 exports 字段,则该字段优先级最高,会疏忽 main/browser/module的配置。

比方同时应用 requireimport 字段定义模块标准入口:

"exports": {
  "require": "./index.js",
  "import": "./index.mjs"
 }
}

// 下面写法还等同于
"exports": {
  // 这里门路申明在根目录下,因为还反对配置包的子门路
  ".": {
    "require": "./index.js",
    "import": "./index.mjs"
  }
 }
}

更多 exports 文档可看 NodeJS 文档阐明

// Vue 的配置:"exports": {
    ".": {
      "import": {
        "node": "./dist/vue.runtime.mjs",
        "default": "./dist/vue.runtime.esm.js"
      },
      "require": "./dist/vue.runtime.common.js",
      "types": "./types/index.d.ts"
    },
    "./compiler-sfc": {
      "import": "./compiler-sfc/index.mjs",
      "require": "./compiler-sfc/index.js"
    },
    "./dist/*": "./dist/*",
    "./types/*": "./types/*",
    "./package.json": "./package.json"
},

unpkg/jsdelivr

让 npm 上所有的文件都开启 cdn 服务。留神文件须要是 UMD 模块标准格局

"unpkg": "dist/redux.js",

应用 unpkg/jsdelivr 字段能够让 npm 上所有的文件都开启 cdn 服务,比方当咱们从 CDN 拜访应用 Redux时(https://unpkg.com/redux),

会重定向到 https://unpkg.com/redux@4.2.0/dist/redux.js(取最新 Redux 版本)获取文件

dependencies

运行依赖 ,我的项目线上环境下须要用到的依赖。
应用 npm install xxxnpm install xxx --save 时,npm 包就会主动插入到该字段下。

"dependencies": {
  "react": "18.2.0",
  "react-dom": "18.2.0",
  "@ant-design/icons": "4.7.0",
}

在装置之前就能够判断 npm 包是否须要在线上运行,如不须要则不要放到该字段下。

在我经验过的来看,倡议一些重要且稳固的库锁死版本,避免意外降级导致生产 bug,因为升级库的次版本,也有概率呈现较重大 Bug。

"antd": "4.21.0",

找了篇文章能够看下:如何治理 npm 版本号:语义化版本策略 SemVer

devDependencies

开发依赖,我的项目开发环境须要用到而线上运行时不须要的依赖,用于辅助开发。

比方 webpackeslintjest、TS @types/xxx类型文件等等。

当打包上线时并不需要这些包,所以能够把这些依赖增加到 devDependencies 中,这些依赖仍然会在本地指定 npm install 时被装置和治理,然而不会被装置到生产环境中。

应用 npm install xxx -D 或者 npm install xxx --save-dev 时,npm 包就会主动插入到该字段下。

peerDependencies

伙伴依赖,避免包防止反复装置,个别组件库比拟常见。

如 Ant Design 的配置:示意咱们我的项目应用 antd npm 包还需装置 reactreact-dom,且版本都要>=16.9.0

"peerDependencies": {
    "react": ">=16.9.0",
    "react-dom": ">=16.9.0"
},

peerDependenciesMeta

可选的伙伴依赖

举例:react-redux package.json

 "peerDependencies": {
    "@types/react": "^16.8 || ^17.0 || ^18.0",
    "@types/react-dom": "^16.8 || ^17.0 || ^18.0",
    "react": "^16.8 || ^17.0 || ^18.0",
    "react-dom": "^16.8 || ^17.0 || ^18.0",
    "react-native": ">=0.59",
    "redux": "^4"
  },
  "peerDependenciesMeta": {
    "@types/react": {"optional": true},
    "@types/react-dom": {"optional": true},
    "react-dom": {"optional": true},
    "react-native": {"optional": true},
    "redux": {"optional": true}
  },

上述指定了 5 个 npm 包在 peerDependenciesMeta 中,示意都为可选项,所以只装置任意几个可能不会报错,当然也不须要全副装置,因为这里显著看出这是辨别 native 和 web 两个环境的,应用的话就任选只在一种环境下。

bin

指定各个外部命令对应的可执行文件的地位,指定了 bin 字段的 npm 包,如果被全局装置,就会被加载到全局环境中,能够通过别名来执行该文件。如带有工具性质的 npm 包。

// webpack
"bin": {"webpack": "bin/webpack.js"},

// eslint
"bin": {"eslint": "./bin/eslint.js"},

node_modules/.bin/目录下的命令,都能够用 npm run [命令] 的格局运行

拿 eslint 举例,eslint 命令对应的可执行文件为 bin 子目录下的 eslint.js。npm 会在 node_modules/.bin/ 目录下建设符号链接,因为 node_modules/.bin/ 目录会在运行时退出零碎的 PATH 变量,所以在运行 npm 时,就能够不带门路,间接通过命令来调用这些脚本。

"eslint": "./node_modules/bin/eslint.js --fix --ext .ts,.tsx"

// 简写为
"eslint": "eslint --fix --ext .ts,.tsx"

overrides

重写我的项目依赖的依赖,及其依赖树下某个依赖的版本号,进行包的替换,反对任意深度的嵌套。。

这个拿我遇过的问题来解释,比方 ts-ebml 库,咱们在我的项目中曾经锁死了版本,然而有次发现 lock 文件更新了,当然它还是放弃原来版本不变,然而它的子依赖 matroska 被降级了小版本导致 bug。

因为 matroska 这个库的场景在咱们我的项目只有一处中央,为了解决这个问题,就须要把 matroska 版本锁死,复原到之前没有 bug 的版本,所以能够用该字段

"overrides": {"matroska": "2.2.3"}

此时查找 lock 文件依赖树,会发现 lock 文件全副被装置为咱们指定的版本/matroska/2.2.3,当然你也能够针对独自的库进行版本重写,如下:

"overrides": {
  "ts-ebml": {"matroska": "2.2.3"}
}
  • pnpm 同样也是应用 overrides 字段
  • yarn 须要应用 resolution 字段

更多可理解:前端依赖版本重写指南

参考

  • 前端工程化基建摸索:从外部机制和外围原理理解 npm
  • package.json 配置齐全解读
  • 对于前端大管家 package.json,你晓得多少?

正文完
 0