ホームページ >ウェブフロントエンド >jsチュートリアル >この記事は、npm の原理を理解するのに役立ちます。

この記事は、npm の原理を理解するのに役立ちます。

青灯夜游
青灯夜游転載
2022-08-09 09:23:023140ブラウズ

npm は JavaScript の世界におけるパッケージ管理ツールであり、Node.js プラットフォームのデフォルトのパッケージ管理ツールです。 npm を通じて、コードのインストール、共有、配布、プロジェクトの依存関係の管理を行うことができます。この記事では npm の原則について説明します。お役に立てれば幸いです。

この記事は、npm の原理を理解するのに役立ちます。

#npm の原理

npm は世界最大のパッケージマネージャーと言われていますが、その理由は本当に使いやすさだけなのでしょうか?

1. npm init

は、単純な package.json ファイルを初期化するために使用されます。 package.json ファイルは、パッケージ説明ファイルを定義するために使用されます。

1.

npm init 実行のデフォルト動作

Execution

npm init --yes、すべてデフォルト値を使用します。

2. カスタマイズ

npm init動作

npm initコマンドの原理は、スクリプトを呼び出し、初期化された package.json ファイルを出力することです。 。

prompt() メソッドを使用してユーザー入力を取得します。

2. 依存関係パッケージのインストール

npm の中核機能である依存関係管理。

npm i を実行して、package.json の依存関係と devDependency から現在のディレクトリの node_modules フォルダーに依存関係パッケージをインストールします。

2.1. パッケージ定義

npm i はパッケージをインストールできます。通常、package はインストールする必要があるパッケージの名前です。デフォルト設定では、npm はデフォルトのソース (レジストリ) からパッケージ名に対応するパッケージ アドレスを検索し、ダウンロードしてインストールします。有効なパッケージ名を指す http url/git url/フォルダー パスも使用できます。

パッケージの正確な定義は、次の a) ~ g) のいずれかの条件を満たしており、それはパッケージです:

この記事は、npm の原理を理解するのに役立ちます。

パッケージの正確な定義

2.2. ローカル パッケージ/リモート git ウェアハウス パッケージのインストール##共有依存関係パッケージを使用するために npm ソースに公開する必要はありません。

1)、シナリオ 1: ローカル モジュール参照

開発中、モジュール間の呼び出しは避けられません。開発中、頻繁に呼び出される構成モジュールをルート ディレクトリに配置します。多くのレベルのディレクトリ、およびその後の参照

const config = require(''../../../../..config)

このようなパス参照は、コードのリファクタリングには役立ちません。現時点では、他のモジュールが共有できるようにこのモジュールを分離することを検討する必要があります。たとえば、config.js をパッケージにカプセル化して、node_modules ディレクトリに配置できます。

Node_modules ディレクトリへのソフト接続を手動でコピーしたり作成したりする必要はありません。npm には独自のソリューションがあります:

ソリューション:

1. 新しい config フォルダーを追加し、 config.js をフォルダーに追加し、名前を Index.js に変更し、config パッケージ

{ 
    "name": "config", 
    "main": "index.js", 
    "version": "0.1.0" 
}

2 を定義する package.json を作成します。プロジェクトの package.json に依存関係を追加し、npm i を実行します。

{ 
  "dependencies": { 
    "config":"file: ./config" 
  } 
}

node_modules ディレクトリを見ると、上部の config/ フォルダを指す config という名前の追加のソフト リンクが見つかります。これは、npm が file: プロトコルの URL を認識し、このパッケージをファイル システムから直接取得する必要があることを学習し、node_modules へのソフト リンクを自動的に作成して「インストール」プロセスを完了するためです。

2)、シナリオ 2: プライベート git 共有パッケージ

チーム内には、チーム内のさまざまなプロジェクト間で共有する必要があるコード/パブリック ライブラリがいくつかありますが、機密情報が含まれている可能性があります。コンテンツ。

依存パッケージをプライベート git リポジトリでホストし、git URL を依存関係に保存するだけです。 npm はシステムの git コマンドを直接呼び出して、パッケージの内容を git ウェアハウスから node_modules にプルします。

npm でサポートされる Git URL 形式:

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

git パスの後に # を使用して特定の git ブランチ/コミット/タグを指定するか、#semver: を使用して特定の semver 範囲を指定できます。

例:

git+ssh://git@github.com:npm/npm.git#v1.0.27 
git+ssh://git@github.com:npm/npm#semver:^5.0 
git+https://isaacs@github.com/npm/npm.git 
git://github.com/npm/npm.git#v1.0.27

3)、シナリオ 3: オープンソース パッケージの問題の修復

現時点では、node_modules ディレクトリに手動で入力して、対応するパッケージのコンテンツを変更できます。コード行を変更して問題を解決する可能性があります。しかし、このアプローチは非常に賢明ではありません!

計画:

元の作成者の git ライブラリをフォークし、独自のリポジトリで問題を修正し、依存関係内の対応する依存関係を独自の修復されたバージョンの git に変更します。 URL で問題を解決できます。

3. npm install の仕組み

npm i を実行すると、すべての依存パッケージが node_modules に表示されます。開発者は、node_modules フォルダーの構造の詳細には注意を払いませんが、ビジネス コード内で参照される依存関係パッケージに注目します。

node_modules 構造を理解することは、npm がどのように機能するかをより深く理解するのに役立ちます。 npm2 から npm5 への変更と改善。

3.1 npm2

npm2 は、依存パッケージをインストールするときに、単純な再帰インストール方法を使用します。各パッケージには独自の依存関係パッケージがあり、各パッケージの依存関係は独自のノードモジュールにインストールされます。依存関係は層ごとに進行して、依存関係ツリー全体を形成します。この依存関係ツリーは、次のファイル構造ツリーと 1 対 1 で対応します。ファイルシステム。

ツリーに依存する最も便利な方法は、ルート ディレクトリで

npm ls

を実行することです。 利点:

    階層構造は明白で、愚かな管理にとっても簡単です。
  • 欠点:
  • 複雑なプロジェクトの場合、ディレクトリ構造が深すぎる可能性があり、深いファイル パスが長すぎるため、ウィンドウ ファイル システムのファイル パスが 260 文字を超えることができないようになります。

  • 複数のパッケージに依存する一部のパッケージは、多くの場所に繰り返しインストールされるため、多くの冗長性が生じます。

3.2 npm3

npm3 の node_modules ディレクトリは、よりフラットな階層構造に変更されました。 npm3 は、インストール中に依存関係ツリー全体を走査し、最も合理的なフォルダー インストール方法を計算します。繰り返し依存するパッケージはすべて再インストールできます。

npm の場合、同じ名前でバージョンの異なるパッケージは 2 つの独立したパッケージです。

npm3 の依存関係ツリー構造はフォルダー階層と 1 対 1 に対応しなくなりました。

3.3 npm5

npm3 のフラットな依存関係パッケージのインストール方法に従います。最大の変更は、package-lock.json ファイルの追加です。

Package-lock.json 関数: 依存関係のインストール構造をロックし、node_modules ディレクトリ ファイル階層が json 構造と 1 対 1 対応していることを確認します。

npm5 は、npm i の実行後にデフォルトで package-lock.json ファイルを生成し、git/svn コード ベースに送信します。

アップグレードするには、バージョン 5.0 を使用しないでください。

注: npm 5.0 では、package-lock ファイルがすでに存在する場合、依存関係を package.json ファイルに手動で追加してから npm install を実行すると、新しい依存関係は node_modules 、 package にインストールされません。 -lock.json はそれに応じて更新されません。

4. 依存関係パッケージのバージョン管理

依存関係パッケージのアップグレード管理に関する知識を紹介します。

4.1 セマンティック バージョン semver

npm 依存関係管理の重要な機能は、バージョン管理ソリューションとしてセマンティック バージョン (semver) 仕様を採用しています。

セマンティック バージョン番号には、major.minor.patch の形式で 3 つの数字が含まれている必要があります。これは、メジャー バージョン番号、マイナー バージョン番号、変更されたバージョン番号を意味します。

依存関係で semver 規則を使用して、必要な依存関係パッケージのバージョン番号または範囲を指定する必要があります。

一般的に使用されるルールは次のとおりです:

この記事は、npm の原理を理解するのに役立ちます。

#semver semantic version

1. 任意の 2 つのルールは、スペースで接続されて表されます。 「AND」ロジックは 2 つのルールの共通部分です。

たとえば、>=2.3.1 =2.3.1 および

  • として解釈できます。 2.3.1、2.4.5、2.8.0
  • と一致可能 ただし、1.0.0、2.3.0、2.8.1、3.0.0

2 には一致しません。任意の 2 つのルールを || で接続して、2 つのルールである「OR」ロジックを表現します。 . ルールの結合。

例: ^2 >=2.3.1 || ^3 >3.2

  • 2.3.1、2,8.1、3.3.1
  • と一致可能 ただし、1.0.0、2.2.0、3.1.0、4.0.0

3. バージョン番号の範囲を表現するより直感的な方法

  • or x はすべてのメジャー バージョンに一致します
  • 1 または 1.x は、メジャー バージョン番号 1
  • を持つすべてのバージョンと一致します。 1.2 または 1.2.x は、バージョン番号 1.2

4 で始まるすべてのバージョンに一致します。MAJOR.MINOR.PATCH の後に追加 - ドット区切りのタグが続き、通常はプレリリース バージョンのタグと見なされます。バージョンは不安定なので、運用環境での使用はお勧めできません。

  • 1.0.0-アルファ
  • 1.0.0-beta.1
  • 1.0.0-rc.3

4.2 依存関係のバージョンのアップグレード

依存関係パッケージをインストールすると、新しいバージョンがリリースされます。バージョンアップについて?

  • npm i または npm update を使用しますが、npm バージョン、package.json および package-lock.json ファイルが異なると、インストールとアップグレードのパフォーマンスが異なります。

npm3 の使用の結論:

  • ローカルのnode_modulesがすでにインストールされている場合、installを再度実行してもパッケージのバージョンは更新されませんが、updateを実行すると更新され、ローカルのnode_modulesが空の場合、install/updateを実行すると更新パッケージが直接インストールされます。
  • npm update は常に、package.json で指定された semver に一致する最新のバージョン番号にパッケージを更新します。この例では、^1.8.0 に一致する最新バージョンは 1.15.0
  • です。 package.json が指定されると、後で npm install または update が実行されるかに関係なく、package.json 内の webpack バージョンは最初から頑固に変更されません ^1.8.0

npm5 を使用した結論:

  • install が実行されるたびに、npm は package-lock で指定されたバージョンに従って webpack のインストールを優先します。npm 3 テーブルの b) 状況を回避します;
  • インストール/更新が完了すると、パッケージ ロック ファイルは常に、node_modules で更新されます - (したがって、パッケージ ロック ファイルは、node_modules の JSON 表現とみなすことができます)
  • node_modules のインストール後に npm update を実行すると、package.json のバージョン番号も ^1.15.0

#4.3 ベスト プラクティス # に変更されます。私がよく使用するノードは 8.11.x、npm は 5.6.0 です。

  •     使用npm >= 5.1 版本,保持package-lock.json文件默认开启配置。
  •     初始化,npm i 安装依赖包,默认保存^X.Y.Z,项目提交package.json和package-lock.json。
  •     不要手动修改package-lock.json

升级依赖包:

  •     升级小版本,执行npm update升级到新的小版本。
  •     升级大版本,执行npm install @ 升级到新的大版本。
  •     手动修改package.json中的版本号,然后npm i。
  •     本地验证升级新版本后没有问题,提交新的package.json和package-lock.json文件。

降级依赖包:

  •     正确:npm i @验证没有问题后,提交package.json和package-lock.json文件。
  •     错误:修改package.json中的版本号,执行npm i不会生效。因为package-lock.json锁定了版本。

删除依赖包:

  •     A计划:npm uninstall 。提交package.json和package-lock.json。
  •     B计划:在package.json中删除对应的包,然后执行npm i,提交package.json和package-lock.json。

五、npm的sctipts

5.1 基本使用

npm scripts是npm的一个重要的特性。在package.json中scripts字段定义一个脚本。

比如:

{ 
    "scripts": { 
        "echo": "echo HELLO WORLD" 
    } 
}

我们可以通过npm run echo 命令执行这段脚本,就像shell中执行echo HELLO WOLRD,终端是可以看到输出的。

总结如下:

  •     npm run 命令执行时,会把./node_modules/.bin目录添加到执行环境的PATH变量中。全局的没有安装的包,在node_modules中安装了,通过npm run 可以调用该命令。
  •     执行npm 脚本时要传入参数,需要在命令后加 -- 表明,比如 npm run test -- --grep="pattern" 可以将--grep="pattern"参数传给test命令。
  •     npm 还提供了pre和post两种钩子的机制,可以定义某个脚本前后的执行脚本。
  •     运行时变量:npm run 的脚本执行环境内,可以通过环境变量的方式获取更多的运行相关的信息。可以通过process.env对象访问获得:
  •     npm_lifecycle_event:正在运行的脚本名称
  •     npm_package_:获取当前package.json中某一个字段的匹配值:如包名npm_package_name
  •     npm_package__:package中的嵌套字段。

5.2 node_modules/.bin目录

保存了依赖目录中所安装的可供调用的命令行包。本质是一个可执行文件到指定文件源的映射。

例如 webpack 就属于一个命令行包。如果我们在安装 webpack 时添加 --global 参数,就可以在终端直接输入 webpack 进行调用。

上一节所说,npm run 命令在执行时会把 ./node_modules/.bin 加入到 PATH 中,使我们可直接调用所有提供了命令行调用接口的依赖包。所以这里就引出了一个最佳实践:

•将项目依赖的命令行工具安装到项目依赖文件夹中,然后通过 npm scripts 调用;而非全局安装

于是 npm 从5.2 开始自带了一个新的工具 npx.

5.3 npx

npx 的使用很简单,就是执行 npx 即可,这里的 默认就是 ./node_modules 目录中安装的可执行脚本名。例如上面本地安装好的 webpack 包,我们可以直接使用 npx webpack 执行即可。

5.4 用法

1、传入参数

"scripts": { 
  "serve": "vue-cli-service serve", 
  "serve1": "vue-cli-service --serve1", 
  "serve2": "vue-cli-service -serve2", 
  "serve3": "vue-cli-service serve --mode=dev --mobile -config build/example.js" 
}

除了第一个可执行的命令,以空格分割的任何字符串都是参数,并且都能通过process.argv属性访问。

比如执行npm run serve3命令,process.argv的具体内容为:

[ &#39;/usr/local/Cellar/node/7.7.1_1/bin/node&#39;, 
  &#39;/Users/mac/Vue-projects/hao-cli/node_modules/.bin/vue-cli-service&#39;, 
  &#39;serve&#39;, 
  &#39;--mode=dev&#39;, 
  &#39;--mobile&#39;, 
  &#39;-config&#39;, 
  &#39;build/example.js&#39; 
]

2、多命令运行 在启动时可能需要同时执行多个任务,多个任务的执行顺序决定了项目的表现。

1)串行执行

串行执行,要求前一个任务执行成功之后才能执行下一个任务。使用 && 服务来连接。

npm run scipt1 && npm run script2

串行执行命令,只要一个命令执行失败,整个脚本会中止的。

2)并行执行

并行执行,就是多个命令同时平行执行,使用 & 符号来连接。

npm run script1 & npm run script2

3、env 环境变量 在执行npm run脚本时,npm会设置一些特殊的env环境变量。其中package.json中的所有字段,都会被设置为以npm_package_ 开头的环境变量。

4、指令钩子 在执行npm scripts命令(无论是自定义还是内置)时,都经历了pre和post两个钩子,在这两个钩子中可以定义某个命令执行前后的命令。比如在执行npm run serve命令时,会依次执行npm run preserve、npm run serve、npm run postserve,所以可以在这两个钩子中自定义一些动作:

"scripts": { 
  "preserve": "xxxxx", 
  "serve": "cross-env NODE_ENV=production webpack", 
  "postserve": "xxxxxx" 
}

5、常用脚本示例

// 删除目录 
"clean": "rimraf dist/*", 

// 本地搭建一个http服务 
"server": "http-server -p 9090 dist/", 

// 打开浏览器 
"open:dev": "opener http://localhost:9090", 

// 实时刷新 
"livereload": "live-reload --port 9091 dist/", 

// 构建 HTML 文件 
"build:html": "jade index.jade > dist/index.html", 

// 只要 CSS 文件有变动,就重新执行构建 
"watch:css": "watch &#39;npm run build:css&#39; assets/styles/", 

// 只要 HTML 文件有变动,就重新执行构建 
"watch:html": "watch &#39;npm run build:html&#39; assets/html", 

// 部署到 Amazon S3 
"deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/", 

// 构建 favicon 
"build:favicon": "node scripts/favicon.js",

六.npm配置

6.1 npm config

  •     通过npm config ls -l 可查看npm 的所有配置,包括默认配置。
  •     通过npm config set ,常见配置:
  •     proxy,https-proxy:指定npm使用的代理
  •     registry:指定npm下载安装包时的源,默认是https://registry.npmjs.org。可以指定私有的registry源。
  •     package-lock.json:指定是否默认生成package-lock.json,建议保持默认true。
  •     save :true/false指定是否在npm i之后保存包为dependencies,npm5开始默认为true。
  •     通过npm config delete 删除指定的配置项。

6.2 npmrc文件

可以通过删除npm config命令修改配置,还可以通过npmrc文件直接修改配置。

npmrc文件优先级由高到低,包括:

  •     工程内配置文件:项目根目录下的.npmrc文件
  •     用户级配置文件:用户配置里
  •     全局配置文件
  •     npm内置配置文件 我们可以在自己的团队中在根目录下创建一个.npmrc文件来共享需要在团队中共享的npm运行相关配置。

比如:我们在公司内网下需要代理才能访问默认源:https://registry.npmjs.org源;或者访问内网的registry,就可以在工作项目下新增.npmrc文件并提交代码库。

示例配置:

proxy = http://proxy.example.com/ 
https-proxy = http://proxy.example.com/ 
registry = http://registry.example.com/

这种在工程内配置文件的优先级最高,作用域在这个项目下,可以很好的隔离公司项目和学习研究的项目两种不同环境。

将这个功能与 ~/.npm-init.js 配置相结合,可以将特定配置的 .npmrc 跟 .gitignore, README 之类文件一起做到 npm init 脚手架中,进一步减少手动配置。

6.3 node版本约束

一个团队中共享了相同的代码,但是每个人开发机器不一致,使用的node版本也不一致,服务端可能与开发环境不一致。

  •     这就带来了不一致的因素----方案:声明式约束+脚本限制。
  •     声明:通过package.json的engines属性声明应用运行所需的版本要求。例如我呢项目中使用了async,await特性,得知node查阅兼容表格[1]得知最低支持版本是7.6.0.因此指定engines配置为:
{ 
  "engines": {"node": ">=7.6.0"} 
}
  •     强约束(可选):需要添加强约束,需要自己写脚本钩子,读取并解析engines字段的semver range并与运行环境做比对校验并适当提醒。

总结

  •     npm init初始化新项目
  •     统一项目配置:需要团队共享npm config配置项,固化到.npmrc文件中
  •     统一运行环境:统一package.json,统一package-lock.json文件。
  •     合理使用多样化的源安装依赖包
  •     使用npm版本:>= 5.2版本
  •     使用npm scripts和npx管理相应脚本
  •     安全漏洞检查:npm audit fix修复安全漏洞的依赖包(本质:自动更新到兼容的安全版本)

引用链接

[1] node查阅兼容表格: https://node.green/

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

以上がこの記事は、npm の原理を理解するのに役立ちます。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はzzvips.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。