Analysis of package.json

foreword

package.json, as the manifest file of the project, records the various packages that the project depends on, as well as custom scripts, versions and other information. It is one of the most important files in modern front-end projects. To get started with a project quickly, starting from package.json is definitely a good choice. And understanding the role and configuration of each field in package.json is very important for us to improve our skills in project construction, dependency management and release.

Generate package.json, use it npm init, and then enter the options one by one or press Enter all the time to automatically generate one package.json. If you find it troublesome, run npm init -yit to generate a package.json by default.

{
  "name": "project", // 项目名称
  "version": "1.0.0", // 项目版本
  "description": "", // 项目描述
  "main": "index.js", // 项目入口文件
  "scripts": { // 指定运行脚本命令的 npm 命令行缩写
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",// 作者
  "license": "ISC" // 许可证
}

Next, I will divide the different fields of package.json from the perspective of the project. Please point out if there is something wrong.

Project Overview

nameandversion

If you want to publish a package on npm, "name" and "version" are required and will be the unique id for your package.

descriptionandkeywords

"description" is a project description, accepting a string.
"keywords" is an array, and multiple project keywords can be placed in the array.
Both are for the convenience of npmsearching and for developers to understand the meaning of the project more easily.

homepage, repositoryandbugs

"homepage" is the home page path of this project, which is convenient for developers to visit the home page of this package for more information.

"homepage": "https://github.com/owner/project#readme"

"repository" is the code warehouse of this project, which is convenient for contributors to find the code warehouse.

"repository": "git+https://github.com/username/repo-name.git"
"repository": {
  "type": "git",
  "url": "git+https://github.com/username/repo-name.git"
}

"bugs" is for developers to make suggestions or comments on bugs in the project.

"bugs": { "url" : "https://github.com/owner/project/issues", "email" : "[email protected]" }

unpkgandjsdelivr

In CDN mode, import the link of the current npm package.

"unpkg": "lib/index.iife.js",
"jsdelivr": "lib/index.iife.js",

project environment

engines

The engines field in package.json is used to specify the environment required for the npm package to run. It contains the version requirements of node, npm, yarn and other environments. The format of engines is:

json
"engines": {
  "node": ">=10.13.0",
  "npm": ">=6.4.1",
  "yarn": "^1.9.4"
}

engines字段主要是确保npm包在安装后可以正确运行所需的环境。如果环境版本不匹配,npm install时会显示警告信息。让其他开发者在使用该包之前可以确保拥有匹配的环境,避免因版本不兼容导致的错误或警告。

browserslist

browserslist字段是用来指定项目的目标浏览器范围的。它曾经是package.json的标准字段之一,但是从npm v5.5.0开始,browserslist被移除了。

以 Babel 为例,它是怎么判断项目是否需要做降级处理的呢,答案就是通过 browserslist 查询出需要支持的浏览器列表,然后根据这个列表来做判断。

browserslist 配置方式
这是因为browserslist现在可以通过以下几种方式指定:

  1. package.json中使用"browserslist" key:
"browserslist": ["> 1%", "last 2 versions"] // 查询全球市场占有率大于 1% 的浏览器最后两个版本
  1. 项目根目录下的.browserslistrc文件:
> 1%
last 2 versions

os

指定操作系统

{ "os": [ "darwin", "linux" ] } // 适用
{ "os": [ "!linux" ] } // 禁止

cpu

{ "cpu" : [ "x64", "ia32" ] } # 适用
{ "cpu" : [ "!arm", "!mips" ] } # 禁止

项目分析

main

"main" 定义了项目的入口文件,默认值是根目录的"index.js"。

module

性质等同于main字段。module用于ES6规范的模块,只要支持ES6,会优先使用module入口。
这样,代码也可以启用tree shaking机制。

"module": "es/index.mjs",

bin

很多包都有一个可执行命令,并且希望被安装到环境变量中。npm 安装依赖的时候, npm会通过node_modules/.bin 将 bin 里面的文件暴露出来,当你通过 npx myapp的时候可以直接运行该命令。

{
    "bin": {
        "myapp": "./cli.js" 
    } 
}

dependenciesdevDependencies

两者的作用和区别

两者都是为了记录需要的依赖以及版本。

devDependencies用于开发环境下依赖的模块,生产环境不需要被打入包内。运行命令行npm i xxx --save-dev,会被安装到 "devDependencies"

dependencies依赖的包不仅开发环境能使用,生产环境也能使用。运行命令行npm i xxx,会被安装到 "devDependencies"

总结: 通常情况下, devDependencies一般是放置一些代码规范工具、打包工具、编译器等,而dependencies一般是放置组件库、框架等与页面相关的插件。其实依赖不管放在哪里对项目影响都不大,但是保持良好的习惯就会让人觉得项目很整洁。

指定不同版本

{ 
    "dependencies": {
        "foo": "1.0.0 - 2.9999.9999", // 1.0.1-2.9999.9999版本(和下面的表达差不多意思)
        "bar": ">=1.0.2 <2.1.2", // 大于或等于1.0.2版本小于2.1.2版本
        "baz": ">1.0.2 <=2.3.4", // 大于1.0.2版本小于等于2.3.4版本
        "boo": "2.0.1", // 指定版本
        "qux": "<1.0.0 || >=2.3.1 <2.4.5", // 小于1.0.0或者大于2.3.1且小于2.4.5
        "til": "~1.2.3", // ~ 匹配1.2.x的所有小版本,但不会匹配到1.3.x
        "elf": "^1.2.3", // 匹配1.x.x的所有大版本,但不会匹配2.x.x
        "two": "2.x", // 匹配所有2.x开头版本
        "thr": "3.3.x", // 匹配3.3.x版本
        "lat": "latest", // 最新版本
        "dyl": "file:../dyl" 
    } 
}

指定url的包

开发过程中,有可能你需要直接使用本地的包或者git仓库的包进行调试,又不希望频繁上传到npm包管理器这么麻烦。

<protocol>://[<user>[:<password>]@]<hostname>[:<port>][:][/]<path>[#<commit-ish> | #semver:<semver>]

可以根据version或者commit-ish来进行精确下载。

git示例

{ 
    "dependencies": {
        "bar": "git+ssh://[email protected]:npm/cli.git#v1.0.27",
        "foo": "git+ssh://[email protected]:npm/cli#semver:^5.0",
        "baz": "git+https://[email protected]/npm/cli.git",
        "boo": "git://github.com/npm/cli.git#v1.0.27"
    } 
}

本地文件示例

{ 
    "dependencies": {
        "bar": "file:../foo/bar" 
    } 
}

项目运行

scripts

scripts字段的作用

scripts 属性是一个字典,对象的属性名为可以通过 npm run 运行命令,属性值可执行命令。{"xxx": "vite"},在这里使用终端执行npm run xxx

如果你没有全局安装vite,直接去执行vite命令行,终端是会报错的。但这里通过npm run xxx执行命令并没有报错,是因为我们在安装依赖的时候,是通过npm i xxx 来执行的,例如 npm i vite,npm 在 安装这个依赖的时候,就会node_modules/.bin/ 目录中创建好vite 为名的几个可执行文件了(上面的bin也提到了)。

image.png

.bin 目录,这个目录不是任何一个 npm 包。而是一个脚本。所以我们执行scripts里面的命令时,虽然在全局找不到对应的可运行命令,但也可以通过.bin文件夹下找到对应的脚本。

自定义脚本的写法

可以通过自定义脚本直接运行一些命令行提高自己的开发效率,或者运行脚本来打包配置项目。

{
  "scripts": {
      "clean": "rm -rf dist",
      "update": "sh ./update.sh"
  }
}

项目规范

huskylint-staged

husky的作用

husky是一个可以给git hooks添加执行自定义脚本的工具。它可以在git事件触发时(commit, push, rebase等)自动执行我们所配置的脚本,从而实现lint校验,测试运行,构建打包等工作流程。

配合git事件触发脚本

husky的安装和配置也很简单,主要有以下几个步骤:

  1. 安装husky包:npm install husky --save-dev
  2. 在package.json中添加git hooks脚本,如:"pre-commit": "npm run lint"
  3. 添加husky配置到package.json,如:"husky": { "hooks": { "pre-commit": "npm run lint"} }
  4. git commit触发pre-commit钩子,从而自动执行npm run lint进行lint校验。

所以,husky是一个比较方便的git hooks工具,可以让我们的开发工作流变得更加自动化和标准化。理解husky的作用和配置方式,可以大大提高我们的前端工程化实践水平。

lint-staged的作用

lint-staged是一个在git暂存文件(staged files)上运行代码格式规范的工具。它的主要作用是:

  1. 只校验暂存文件的改动(diff),而不是整个项目。这样可以提高lint效率,并且避免提交未修改的文件产生的lint错误。
  2. 支持在git pre-commit钩子中使用,结合husky可以实现commit前自动lint校验。
  3. 支持多种文件类型(JavaScript, CSS, Markdown 等)和多个linters。如ESLint, Stylelint, Prettier等。4. 提供了简单的配置方式,可以轻松地在package.json中完成配置。

lint-staged配合husky

  1. 安装lint-staged和相关的代码规范工具:npm install lint-staged eslint prettier -D
  2. 在package.json中添加lint-staged配置:"lint-staged": {"*.js": "eslint --fix",}
  3. 安装husky并配置pre-commit hook:"husky": { "hooks": { "pre-commit": "npm run lint"} }
  4. git add 添加文件并commit,pre-commit钩子就会自动执行lint-staged lint校验。

所以,lint-staged是一个非常实用的工具,让我们的代码质量管理可以更加自动化。理解lint-staged的作用和配置方式,可以很好地提高我们的前端工程化水平。

types

项目如果是用TypeScript写的,则需要types字段,对外暴露相关的类型定义。

"types": "lib/index.d.ts",

项目打包配置

private

"private" 配置一个布尔值,当为true的时候,npm将会拒绝发布它。这个是防止私人储存库意外发布的情况。

sideEffects

"sideEffects" 用于告知打包工具(webpack),当前项目无副作用,可以使用tree shaking优化。

副作用 是指,该函数的调用过程中,是否对主函数(调用者)产生了附加影响,例如修改了函数外的变量或参数,我们就认为该函数是 有副作用 的函数。

"sideEffects": [
    "a.js",
    "b.js"
],

exports

"exports" 允许在使用模块请求时声明应该使用哪个模块。当指定exports字段时,只有这些模块请求可用,请求其他模块将报错。

{
  "exports": {
    ".": "./main.js",
    "./sub/path": "./secondary.js",
    "./prefix/": "./directory/",
    "./prefix/deep/": "./other-directory/",
    "./other-prefix/*": "./yet-another/*/*.js"
  }
}
// 示例:
import _ from 'my-project' // 将会指向./main.js
import path from 'my-project/sub/path' // 将会指向./secondary.js

files

"files" 用于保留项目在npm发布时的文件或文件夹,在node_modules/下将会只留下files声明的文件或文件夹。你也可以提供一个.npmignore文件,让npm发布的时候规定哪些文件被忽略,就像.gitignore一样。

"files": [
    "lib",
    "bin",
    "scripts"
],

package.jsonREADMELICENSE / LICENCE 无法被忽略。

Guess you like

Origin juejin.im/post/7233785645650264119