ホームページ  >  記事  >  ウェブフロントエンド  >  Node のモジュールのメカニズムについて詳しく学び、モジュールの実装プロセスについて説明します。

Node のモジュールのメカニズムについて詳しく学び、モジュールの実装プロセスについて説明します。

青灯夜游
青灯夜游転載
2022-05-25 21:12:502052ブラウズ

この記事では、CommonJs の仕様と Node のモジュールの仕組みを理解し、CommonJs の仕様を実装する Node の基本的なプロセスを紹介します。

Node のモジュールのメカニズムについて詳しく学び、モジュールの実装プロセスについて説明します。

CommonJs 仕様が提案される前、JavaScript にはモジュール システムがありませんでした。つまり、コードの構成が複雑で大規模なアプリケーションを開発することが困難でした。もっと難しいでしょう。

CommonJs 仕様とは


まず、CommonJS は Node に固有のものではなく、モジュールの参照方法とエクスポート方法を定義するモジュール仕様です。 Nodejs この仕様を実装するだけです CommonJS モジュール仕様は主に、モジュール参照、モジュール定義、モジュール識別の 3 つの部分に分かれています。

モジュール リファレンス

モジュール リファレンスとは、require を通じて他のモジュールを導入できることを意味します。

const { add } = require('./add');
const result = add(1 ,2);

モジュール定義

ファイルはモジュールであり、モジュールは 2 つの変数、つまり module とexports を提供します。 module は現在のモジュール自体、exports はエクスポートされるコンテンツ、exports はモジュールの属性です。つまり、exports は module.exports です。 require を通じて他のモジュールによってインポートされたコンテンツは、module.exports のコンテンツです。

// add.js
exports.add = (a, b) => {
    return a + b;
}

モジュール識別

モジュール識別は、require('./add')# などの require の内容です。 # #、モジュール ID は ./add です。

CommonJS を通じて構築されたモジュールのインポートおよびエクスポート メカニズムにより、ユーザーは変数汚染を考慮することなく、大規模なアプリケーションを簡単に構築できます。

Node のモジュール実装


Node は CommonJs 仕様を実装し、必要な機能をいくつか追加します。 Node は CommonJs 仕様を実装するために主に次の 3 つのことを行います:


  • パス分析

  • ファイルの配置

  • コンパイルと実行

パス解析

require() が実行されると、require が受信します。パラメータはモジュール識別子であり、ノードはモジュール識別子を介してパス解析を実行します。パス分析の目的は、モジュール識別子を通じてこのモジュールが配置されているパスを見つけることです。まず、ノード モジュールは、コア モジュールとファイル モジュールの 2 つのカテゴリに分類されます。コアモジュールはノードに付属するモジュールで、ファイルモジュールはユーザーが作成したモジュールです。同時に、ファイルモジュールは、相対パス形式のファイルモジュール、絶対パス形式のファイルモジュール、および非パス形式(エクスプレスなど)のファイルモジュールに分割されます。

Node のモジュールのメカニズムについて詳しく学び、モジュールの実装プロセスについて説明します。

ノードがファイル モジュールを見つけると、そのモジュールをコンパイル、実行、キャッシュします。一般原則として、モジュールのフル パスをキーとして使用し、コンパイルされたコンテンツを値として取得する場合、このモジュールを 2 回目に導入する場合、パス分析、ファイルの場所、コンパイル、実行の手順を実行する必要はなく、コンパイルされたコンテンツをキャッシュから直接読み取ることができます。

// 缓存的模块示意:
const cachedModule = {
    '/Usr/file/src/add.js': 'add.js编译后的内容',
    'http': 'Node自带的http模块编译后的内容',
    'express': '非路径形式自定义文件模块express编译后的内容'
    // ...
}

require でインポートしたモジュールを探したい場合、モジュールを探す順序としては、まずモジュールがキャッシュにあるかどうかを確認し、キャッシュにない場合はコアを確認します。 module を選択し、ファイル module を探します。このうち、パス形式のファイル モジュールは見つけやすく、相対パスまたは絶対パスに基づいて完全なファイル パスを取得できます。パス形式以外のカスタム ファイル モジュールを見つけるのは比較的面倒ですが、ノードは、node_modules フォルダーからファイルを検索します。

node_modules ディレクトリはどこですか? たとえば、現在実行しているファイルは /Usr/file/index.js です;

/** 
* /Usr/file/index.js;
*/

const { add } = require('add');
const result = add(1, 2);

このモジュールでは、追加モジュールを導入しました。コアモジュールでもパス形式のファイルモジュールでもないので、この時の追加モジュールの探し方。

モジュールには paths 属性があります。追加モジュールを見つけるためのパスは paths 属性にあります。この属性を入力して確認できます:

/** 
* /Usr/file/index.js;
*/

console.log(module.paths);

ファイル ディレクトリでノード インデックスを実行します.js はパスの値を出力できます。

[
'/Usr/file/node_modules',
'/Usr/node_modules',
'/node_modules',
]

つまり、ノードは上記のディレクトリから追加モジュールが含まれているかどうかを順番に検索し、その原理はプロトタイプチェーンと同様です。まず、現在実行しているファイルと同階層のディレクトリにあるnode_modulesフォルダ内を検索し、node_modulesディレクトリが見つからない、または存在しない場合は、上位階層まで検索を続けます。

ファイルの位置決め

パス分析とファイルの位置決めは一緒に使用されます。ファイル識別子にはサフィックスを付けないことも、パスを渡すこともできます。分析ではディレクトリまたはパッケージが検出されますが、現時点では、特定のファイルを見つけるには追加の処理が必要です。

ファイル拡張子の分析

const { add } = require('./add');

比如上面这段代码,文件标识符是不带扩展名的,这个时候node会依次查找是否存在.js、.json、.node文件。

目录和包分析

同样是上面这段代码,通过./add查找到的可能不是一个文件,可能是一个目录或者包(通过判断add文件夹下是否有package.json文件来判断是目录还是包)。这个时候文件定位的步骤是这样的:

  • 查看是否有package.json文件
      • 读取package.json里的main字段的值作为文件
    • 没有
      • 寻找目录下的index作为文件(依次查找index.js、index.json、index.node)

如果package.json里没有main字段,那么也会将index作为文件,然后进行扩展名分析找到对应后缀的文件。

模块编译

我们开发中主要遇到的模块为json模块和js模块。

json模块编译

当我们require一个json模块的时候,实际上Node会帮我们使用fs.readFilcSync去读取对应的json文件,得到json字符串,然后调用JSON.parse解析得到json对象,再赋值给module.exports,然后给到require。

js模块编译

当我们require一个js模块的时候,比如

// index.js
const { add } = require('./add');
// add.js
exports.add = (a, b) => {
    return a + b;
}

这个时候发生了什么呢,为什么我们可以直接在模块里使用module、exports、require这些变量。这是因为Node在编译js模块的时候对模块的内容进行了首尾的包装。

比如add.js这个模块,实际编译的时候是会被包装成类似这样的结构:

(function(require, exports, module) {
  exports.add = (a, b) => {
    return a + b;
  }
  return module.exports;
})(require, module.exports, module)

即我们编写的js文件是会被包装成一个函数,我们编写的只是这个函数里的内容,Node后续的包装的过程对我们隐藏了。这个函数支持传入一些参数,其中就包括require、exports和module。

当编译完js文件后,就会执行这个文件,node会将对应的参数传给这个函数然后执行,并且返回module.exports值给到require函数。

以上就是Node实现CommonJs规范的基本流程。

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

以上がNode のモジュールのメカニズムについて詳しく学び、モジュールの実装プロセスについて説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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