この記事では、CommonJs の仕様と Node のモジュールの仕組みを理解し、CommonJs の仕様を実装する Node の基本的なプロセスを紹介します。
CommonJs 仕様が提案される前、JavaScript にはモジュール システムがありませんでした。つまり、コードの構成が複雑で大規模なアプリケーションを開発することが困難でした。もっと難しいでしょう。
まず、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 です。
Node のモジュール実装
パス解析
require() が実行されると、require が受信します。パラメータはモジュール識別子であり、ノードはモジュール識別子を介してパス解析を実行します。パス分析の目的は、モジュール識別子を通じてこのモジュールが配置されているパスを見つけることです。まず、ノード モジュールは、コア モジュールとファイル モジュールの 2 つのカテゴリに分類されます。コアモジュールはノードに付属するモジュールで、ファイルモジュールはユーザーが作成したモジュールです。同時に、ファイルモジュールは、相対パス形式のファイルモジュール、絶対パス形式のファイルモジュール、および非パス形式(エクスプレスなど)のファイルモジュールに分割されます。 ノードがファイル モジュールを見つけると、そのモジュールをコンパイル、実行、キャッシュします。一般原則として、モジュールのフル パスをキーとして使用し、コンパイルされたコンテンツを値として取得する場合、このモジュールを 2 回目に導入する場合、パス分析、ファイルの場所、コンパイル、実行の手順を実行する必要はなく、コンパイルされたコンテンツをキャッシュから直接読み取ることができます。// 缓存的模块示意: const cachedModule = { '/Usr/file/src/add.js': 'add.js编译后的内容', 'http': 'Node自带的http模块编译后的内容', 'express': '非路径形式自定义文件模块express编译后的内容' // ... }
/** * /Usr/file/index.js; */ const { add } = require('add'); const result = add(1, 2);
/** * /Usr/file/index.js; */ console.log(module.paths);
[ '/Usr/file/node_modules', '/Usr/node_modules', '/node_modules', ]
ファイルの位置決め
パス分析とファイルの位置決めは一緒に使用されます。ファイル識別子にはサフィックスを付けないことも、パスを渡すこともできます。分析ではディレクトリまたはパッケージが検出されますが、現時点では、特定のファイルを見つけるには追加の処理が必要です。ファイル拡張子の分析
const { add } = require('./add');
比如上面这段代码,文件标识符是不带扩展名的,这个时候node会依次查找是否存在.js、.json、.node文件。
目录和包分析
同样是上面这段代码,通过./add
查找到的可能不是一个文件,可能是一个目录或者包(通过判断add文件夹下是否有package.json文件来判断是目录还是包)。这个时候文件定位的步骤是这样的:
如果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 サイトの他の関連記事を参照してください。