Heim  >  Artikel  >  Web-Frontend  >  Eine kurze Analyse der allgemeinen Attribute von package.json in NodeJS-Projekten

Eine kurze Analyse der allgemeinen Attribute von package.json in NodeJS-Projekten

青灯夜游
青灯夜游nach vorne
2022-05-20 19:40:093623Durchsuche

Dieser Artikel führt Sie durch die Konfigurationsdatei package.json im node-Projekt und spricht über einige allgemeine Konfigurationseigenschaften, umgebungsbezogene Eigenschaften, abhängigkeitsbezogene Eigenschaften und Eigenschaften von Drittanbietern in package.json wird für alle hilfreich sein!

Eine kurze Analyse der allgemeinen Attribute von package.json in NodeJS-Projekten

npm ist ein Paketverwaltungstool, das häufig von Front-End-Entwicklern verwendet wird. Im Projekt wird package.json verwendet, um die Konfiguration der npm-Pakete zu verwalten, von denen das Projekt abhängt. package.json ist eine JSON-Datei. Sie beschreibt nicht nur die Paketabhängigkeiten des Projekts, sondern ermöglicht uns auch die Verwendung von „semantischen Versionierungsregeln“, um die Versionen der abhängigen Pakete Ihres Projekts anzugeben, sodass Ihre Builds einfacher mit anderen Entwicklern geteilt werden können wiederverwenden. Dieser Artikel beginnt hauptsächlich mit der jüngsten Praxis, kombiniert mit den neuesten npm- und Node-Versionen, um einige gängige Konfigurationen in package.json vorzustellen und wie man ein standardisiertes package.json schreibt


1. package.json

1 . Einführung in package.json

In einem NodeJS-Projekt ist package.json eine Konfigurationsdatei, die seine Abhängigkeiten verwaltet. Wenn wir ein NodeJS-Projekt initialisieren, übergeben wir normalerweise:

npm init

Dann wird 3 in Ihrem Verzeichnis generiert Verzeichnisse/Dateien, node_modules, package.json und package.lock.json. Der Inhalt von package.json ist:

{
    "name": "Your project name",
    "version": "1.0.0",
    "description": "Your project description",
    "main": "app.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
    },
    "author": "Author name",
    "license": "ISC",
    "dependencies": {
        "dependency1": "^1.4.0",
        "dependency2": "^1.5.2"
    }
}

Wie aus dem Obigen ersichtlich ist, enthält package.json die Metadaten des Projekts selbst sowie die Unterabhängigkeitsinformationen des Projekts (z. B. Abhängigkeiten usw.).

2. package-lock.json

Wir haben festgestellt, dass während der npm-Init nicht nur die Datei package.json, sondern auch die Datei package-lock.json generiert wurde. Warum müssen wir also beim Löschen von package.json immer noch die Datei package-lock.json generieren? Im Wesentlichen dient die Datei „package-lock.json“ dazu, die in package.json angegebene Version des Sub-NPM-Pakets zu sperren: „^16.0.0“ bei der tatsächlichen Installation, solange die Version höher als „react“ ist erfüllt die Anforderungen von package.json. Dies bedeutet, dass laut derselben package.json-Datei die Konsistenz der zweimal installierten Unterabhängigkeitsversionen nicht garantiert werden kann.

Die Paketsperrdatei ist wie unten gezeigt, und die Unterabhängigkeit dependency1 gibt ihre Version im Detail an. Spielt die Rolle der Sperrversion.

{
    "name": "Your project name",
    "version": "1.0.0",
    "lockfileVersion": 1,
    "requires": true,
    "dependencies": {
        "dependency1": {
            "version": "1.4.0",
            "resolved": 
"https://registry.npmjs.org/dependency1/-/dependency1-1.4.0.tgz",
            "integrity": 
"sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
        },
        "dependency2": {
            "version": "1.5.2",
            "resolved": 
"https://registry.npmjs.org/dependency2/-/dependency2-1.5.2.tgz",
            "integrity": 
"sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ=="
        }
    }
}

2. Häufig verwendete Attribute von package.json

In diesem Kapitel werden häufig verwendete Konfigurationsattribute wie Name, Version usw. beschrieben eins. In diesem Kapitel werden hauptsächlich die Eigenschaften „script“, „bin“ und „workspaces“ vorgestellt.

2.1-Skript

Immer wenn npm run angegeben wird, wird automatisch ein Shell-Skript erstellt, das von npm run erstellt wird fügt das Unterverzeichnis node_modules/.bin des lokalen Verzeichnisses zur PATH-Variablen hinzu.

Das bedeutet, dass alle Skripte im Unterverzeichnis node_modules/.bin des aktuellen Verzeichnisses direkt mit dem Skriptnamen aufgerufen werden können, ohne einen Pfad hinzuzufügen. Wenn beispielsweise die Abhängigkeiten des aktuellen Projekts „esbuild“ umfassen, schreiben Sie einfach „esbuild xxx“ direkt.

{
  // ...
  "scripts": {
    "build": "esbuild index.js",
  }
}
{
  // ...
  "scripts": {
    "build": "./node_modules/.bin/esbuild index.js" 
  }
}

Die beiden oben genannten Schreibweisen sind gleichwertig.

2.2 bin

Das bin-Attribut wird zum Laden ausführbarer Dateien in die globale Umgebung verwendet. Das npm-Paket, das das bin-Feld angibt, wird in die globale Umgebung geladen, sobald es global installiert ist Führen Sie die Datei aus.

Zum Beispiel das npm-Paket von @bytepack/cli:

"bin": {
    "bytepack": "./bin/index.js"
 },

Sobald @bytepack/cli global installiert ist, können Sie den entsprechenden Befehl direkt über Bytepack ausführen, z. B.

bytepack -v
//显示1.11.0

Wenn es nicht global installiert ist, wird es ausgeführt automatisch mit dem Projekt im Verzeichnis node_module/.bin verbunden werden. In Übereinstimmung mit dem, was im zuvor eingeführten Skript-Tag gesagt wurde, kann es direkt mit Aliasen verwendet werden.

2.3 Arbeitsbereiche

Wenn das Projekt zu groß ist, erfreut sich Monorepo in letzter Zeit immer größerer Beliebtheit. Wenn es um Monorepo geht, vergessen Sie nicht, sich Arbeitsbereiche anzusehen. Früher verwendeten wir Garn-Arbeitsbereiche. Jetzt unterstützt npm offiziell Arbeitsbereiche. Workspaces löst das Problem, wie mehrere Unterpakete unter einem Root-Paket der obersten Ebene im lokalen Dateisystem verwaltet werden. Die Pakete im Workspaces-Deklarationsverzeichnis werden mit den node_modules des Root-Pakets der obersten Ebene verknüpft.

​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ ​​​​​​​​​​​​​​​​​​​​​​​​​​:

{
  "name": "my-project",
  "workspaces": [
    "packages/a"
  ]
}

In einem npm-Paket namens my-project gibt es ein Verzeichnis, das von Arbeitsbereichen konfiguriert wird.

.
+-- package.json
+-- index.js
`-- packages
   +-- a
   |  `-- package.json

Und das Root-Paket der obersten Ebene namens my-project hat ein Paket/ein Unterpaket. Wenn wir zu diesem Zeitpunkt npm installieren, verweist das in node_modules im Root-Paket installierte npm-Paket a auf das lokale Paket/a Kette

三、package.json环境相关属性

    常见的环境,基本上分为浏览器browser和node环境两大类,接下来我们来看看package.json中,跟环境相关的配置属性。环境的定义可以简单理解如下:

  • browser环境:比如存在一些只有在浏览器中才会存在的全局变量等,比如window,Document等
  • node环境: npm包的源文件中存在只有在node环境中才会有的一些变量和内置包,内置函数等。

3.1 type

    js的模块化规范包含了commonjs、CMD、UMD、AMD和ES module等,最早先在node中支持的仅仅是commonjs字段,但是从node13.2.0开始后,node正式支持了ES module规范,在package.json中可以通过type字段来声明npm包遵循的模块化规范。

//package.json
{
   name: "some package",
   type: "module"||"commonjs" 
}

需要注意的是:

  • 不指定type的时候,type的默认值是commonjs,不过建议npm包都指定一下type

  • 当type字段指定值为module则采用ESModule规范

  • 当type字段指定时,目录下的所有.js后缀结尾的文件,都遵循type所指定的模块化规范

  • 除了type可以指定模块化规范外,通过文件的后缀来指定文件所遵循的模块化规范,以.mjs结尾的文件就是使用的ESModule规范,以.cjs结尾的遵循的是commonjs规范

3.2 main & module & browser

    除了type外,package.json中还有main,module和browser 3个字段来定义npm包的入口文件。

  • main : 定义了 npm 包的入口文件,browser 环境和 node 环境均可使用
  • module : 定义 npm 包的 ESM 规范的入口文件,browser 环境和 node - 环境均可使用
  • browser : 定义 npm 包在 browser 环境下的入口文件

我们来看一下这3个字段的使用场景,以及同时存在这3个字段时的优先级。我们假设有一个npm包为demo1,

----- dist
   |-- index.browser.js
   |-- index.browser.mjs
   |-- index.js
   |-- index.mjs

其package.json中同时指定了main,module和browser这3个字段,

  "main": "dist/index.js",  // main 
  "module": "dist/index.mjs", // module

  // browser 可定义成和 main/module 字段一一对应的映射对象,也可以直接定义为字符串
  "browser": {
    "./dist/index.js": "./dist/index.browser.js", // browser+cjs
    "./dist/index.mjs": "./dist/index.browser.mjs"  // browser+mjs
  },

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

默认构建和使用,比如我们在项目中引用这个npm包:

import demo from 'demo'

通过构建工具构建上述代码后,模块的加载循序为:

browser+mjs > module > browser+cjs > main

这个加载顺序是大部分构建工具默认的加载顺序,比如webapck、esbuild等等。可以通过相应的配置修改这个加载顺序,不过大部分场景,我们还是会遵循默认的加载顺序。

3.3 exports

    如果在package.json中定义了exports字段,那么这个字段所定义的内容就是该npm包的真实和全部的导出,优先级会高于main和file等字段。

举例来说:

{
  "name": "pkg",
  "exports": {
    ".": "./main.mjs",
    "./foo": "./foo.js"
  }
}
import { something } from "pkg"; // from "pkg/main.mjs"
const { something } = require("pkg/foo"); // require("pkg/foo.js")

从上述的例子来看,exports可以定义不同path的导出。如果存在exports后,以前正常生效的file目录到处会失效,比如require('pkg/package.json'),因为在exports中没有指定,就会报错。

    exports还有一个最大的特点,就是条件引用,比如我们可以根据不同的引用方式或者模块化类型,来指定npm包引用不同的入口文件。

// package.json
{ 
  "name":"pkg",
  "main": "./main-require.cjs",
  "exports": {
    "import": "./main-module.js",
    "require": "./main-require.cjs"
  },
  "type": "module"
}

上述的例子中,如果我们通过

const p = require('pkg')

引用的就是"./main-require.cjs"。

如果通过:

import p from 'pkg'

引用的就是"./main-module.js"

最后需要注意的是 :如果存在exports属性,exports属性不仅优先级高于main,同时也高于module和browser字段。

三、package.json依赖相关属性

    package.json中跟依赖相关的配置属性包含了dependencies、devDependencies、peerDependencies和peerDependenciesMeta等。

   dependencies是项目的依赖,而devDependencies是开发所需要的模块,所以我们可以在开发过程中需要的安装上去,来提高我们的开发效率。这里需要注意的时,在自己的项目中尽量的规范使用,形如webpack、babel等是开发依赖,而不是项目本身的依赖,不要放在dependencies中。

   dependencies除了dependencies和devDependencies,本文重点介绍的是peerDependencies和peerDependenciesMeta。

3.1 peerDependencies

peerDependencies是package.json中的依赖项,可以解决核心库被下载多次,以及统一核心库版本的问题。

//package/pkg
----- node_modules
   |-- npm-a -> 依赖了react,react-dom
   |-- npm-b -> 依赖了react,react-dom
   |-- index.js

比如上述的例子中如果子npm包a,b都以来了react和react-dom,此时如果我们在子npm包a,b的package.json中声明了PeerDependicies后,相应的依赖就不会重新安装。

需要注意的有两点:

  • 对于子npm包a,在npm7中,如果单独安装子npm a,其peerDependicies中的包,会被安装下来。但是npm7之前是不会的。
  • 请规范和详细的指定PeerDependicies的配置,笔者在看到有些react组件库,不在PeerDependicies中指定react和react-dom,或者将react和react-dom放到了dependicies中,这两种不规范的指定都会存在一些问题。
  • 其二,正确的指定PeerDependicies中npm包的版本,react-focus-lock@2.8.1,peerDependicies指定的是:"react": "^16.8.0 || ^17.0.0 || ^18.0.0",但实际上,这个react-focus-lock并不支持18.x的react

3.2 peerDependenciesMeta

    看到“Meta”就有元数据的意思,这里的peerDependenciesMeta就是详细修饰了peerDependicies,比如在react-redux这个npm包中的package.json中有这么一段:

 "peerDependencies": {
    "react": "^16.8.3 || ^17 || ^18"
  },
 "peerDependenciesMeta": {
    "react-dom": {
      "optional": true
    },
    "react-native": {
      "optional": true
    }
  }

这里指定了"react-dom","react-native"在peerDependenciesMeta中,且为可选项,因此如果项目中检测没有安装"react-dom"和"react-native"都不会报错。

    值得注意的是,通过peerDependenciesMeta我们确实是取消了限制,但是这里经常存在非A即B的场景,比如上述例子中,我们需要的是“react-dom”和"react-native"需要安装一个,但是实际上通过上述的声明,我们实现不了这种提示。

四、package.json三方属性

    package.json中也存在很多三方属性,比如tsc中使用的types、构建工具中使用的sideEffects,git中使用的husky,eslint使用的eslintIgnore,这些扩展的配置,针对特定的开发工具是有意义的这里不一一举例。

更多node相关知识,请访问:nodejs 教程

Das obige ist der detaillierte Inhalt vonEine kurze Analyse der allgemeinen Attribute von package.json in NodeJS-Projekten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen