ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js のモジュール システムを理解する

Node.js のモジュール システムを理解する

青灯夜游
青灯夜游転載
2020-11-24 17:58:153189ブラウズ

Node.js のモジュール システムを理解する

関連する推奨事項: 「node js チュートリアル

Node.js モジュール

シンプルな JavaScript としてWeb ページにインタラクティブな機能を追加するためのスクリプト言語が登場しましたが、当初はモジュール システムが含まれていませんでした。JavaScript がますます複雑な問題を解決するにつれて、すべてのコードを 1 つのファイルに記述し、関数を使用して機能単位を区別することはできなくなりました。はい、ES6 では、ほとんどの高級言語で共通のクラスとモジュールが提供され、開発者がコードを整理しやすくなります

import _ from 'lodash';

class Fun {}

export default Fun;

上の 3 行のコードは、アプリケーションの 2 つの最も重要な要素を示しています。モジュール システム、インポートとエクスポート

  • export は、モジュール

  • ## の外部インターフェイスを指定するために使用されます。 #import は、他のモジュールによって提供される関数をインポートするために使用されます

ES6 より前には、多くのモジュール読み込みソリューションがコミュニティに登場しましたが、最も重要なものは CommonJS と AMD でした。 js は ES6 より前に誕生し、モジュール システムは CommonJS に似たものを使用しました。実装はいくつかの原則に従います。

  • ファイルはモジュールであり、ファイル内の変数のスコープはmodule

  • Use

    module.exports オブジェクト エクスポート モジュールの外部インターフェイス

  • 導入するには

    require を使用しますその他のモジュール

circle.js

const { PI } = Math;

module.exports = function area(r) {
  PI * r ** 2;
};
上記のコードは Node.js のモジュールを実装しています。このモジュールは他のモジュールに依存せず、円の面積を計算するメソッド

areaをエクスポートします

test.js

const area = require('./circle.js');
console.log(`半径为 4 的圆的面积是 ${area(4)}`);
モジュールはcircle.jsに依存しており、次を使用します円の面積を計算する公開面積メソッド

module.exports

モジュールの外部公開インターフェイスは module.exports を使用します。一般的な使用法は 2 つあります: 属性の追加


test.js

// 添加属性
module.exports.prop1 = xxx;
module.exports.funA = xxx;
module.exports.funB = xxx;

// 赋值到全新对象
module.exports = {
  prop1,
	funA,
  funB,
};
2 つの記述方法は Price と同じであり、

const mod = require('./test.js');

console.log(mod.prop1);
console.log(mod.funA());
を使用する場合には違いはありません。

exports オブジェクトを直接使用する別の方法もありますが、属性を追加することしかできず、新しいオブジェクトに割り当てることはできません。理由は後ほど説明します。

// 正确的写法:添加属性
exports.prop1 = xxx;
exports.funA = xxx;
exports.funB = xxx;

// 赋值到全新对象
module.exports = {
  prop1,
	funA,
  funB,
};
require( 'id')

モジュール タイプ

require の使用法は比較的単純で、id はモジュール名とファイル パスの 2 つのタイプをサポートします

モジュール名

const fs = require('fs');
const _ = require('lodash');

例の fs と lodash はどちらもモジュール名です。fs は Node.js の組み込みコア モジュールで、lodash は npm を介して

node_modules にインストールされるサードパーティ モジュールです。名前が重複する場合は、システムの組み込みモジュールの使用を優先する

プロジェクトには複数のnode_modulesフォルダーが含まれる可能性があるため(Node.jsの比較的失敗した設計)、サードパーティのモジュール検索プロセスは近接性の原則に従い、上位に進みます。

NODE_PATH 環境変数に従ってファイル システムのルート ディレクトリが見つかるまで、レイヤーごとに (特定の検索パスを表示するには、プログラム Print module.paths で見つけることができます)。特定のプロセスについては、公式ドキュメントを参照してください。

さらに、Node .js は次のグローバル ディレクトリ リストも検索します:

    $HOME/.node_modules
  • $HOME/.node_libraries
  • $PREFIX/lib/node

$HOME はユーザーのホーム ディレクトリ、$PREFIX はユーザーのホーム ディレクトリです。 node_prefix は Node.js で構成されます。すべての依存関係をローカルの node_modules ディレクトリに配置することを強くお勧めします。これにより、ロードが速くなり、信頼性が高くなります。

ファイル パス

モジュールは、ファイル パスを使用してロードすることもできます。これはプロジェクト A です。ディレクトリ内のカスタム モジュールの共通の読み込み方法。パス拡張子は省略できます。

'/'

のプレフィックスが付いたモジュールは、.js、.json、.node の順に試行されます。
  • ファイルの絶対パスです。システム パスに従ってモジュールを検索します。
  • プレフィックス
  • './' が付いているモジュールは、現在 require を呼び出しているファイルに対する相対パスです。
単一ロードと循環依存関係に影響を与えるには、

モジュールは

Module._cache にキャッシュされます。最初のロード後、毎回呼び出される場合 require('foo') が同じファイルに解析されると、同じオブジェクトが返されます。同時に複数回実行しても、モジュールのコードが複数回実行されることはありません。 Node.js は実際のファイル名に基づいてモジュールをキャッシュするため、異なるレベルのディレクトリから参照されたときに同じモジュールが 2 回読み込まれることはありません。 理解されたモジュールの単一読み込みメカニズムにより、モジュールの循環依存関係の現象の理解が容易になります

a.js


console.log('a 开始');
exports.done = false;
const b = require('./b.js');
console.log('在 a 中,b.done = %j', b.done);
exports.done = true;
console.log('a 结束');
b.js

console.log('b 开始');
exports.done = false;
const a = require('./a.js');
console.log('在 b 中,a.done = %j', a.done);
exports.done = true;
console.log('b 结束');
main.js:

console.log('main 开始');
const a = require('./a.js');
const b = require('./b.js');
console.log('在 main 中,a.done=%j,b.done=%j', a.done, b.done);
main.js が a.js をロードすると、a.js は b.js をロードします。このとき、b.js は Try します。 a.js をロードするため 無限ループを防ぐために、a.js

のエクスポート オブジェクトの

未完成のコピーが b.js モジュールに返され、次に b. js の読み込みが完了します。そして、exports オブジェクトを a.js モジュールに提供します。

したがって、例の出力は次のようになります。

main 开始
a 开始
b 开始
在 b 中,a.done = false
b 结束
在 a 中,b.done = true
a 结束
在 main 中,a.done=true,b.done=true

看不懂上面的过程也没关系,日常工作根本用不到,即使看懂了也不要在项目中使用循环依赖!

工作原理

Node.js 每个文件都是一个模块,模块内的变量都是局部变量,不会污染全局变量,在执行模块代码之前,Node.js 会使用一个如下的函数封装器将模块封装

(function(exports, require, module, __filename, __dirname) {
	// 模块的代码实际上在这里
});
  • __filename:当前模块文件的绝对路径
  • __dirname:当前模块文件据所在目录的绝对路径
  • module:当前的模块实例
  • require:加载其它模块的方法,module.require 的快捷方式
  • exports:导出模块接口的对象,module.exports 的快捷方式

回头看看最开始的问题,为什么 exports 对象不支持赋值为其它对象?把上面函数添加一句 exports 对象来源就很简单了

const exports = module.exports;
(function(exports, require, module, __filename, __dirname) {
	// 模块的代码实际上在这里
});

其它模块 require 到的肯定是模块的 module.exports 对象,如果吧 exports 对象赋值给其它对象,就和 module.exports 对象断开了连接,自然就没用了

在 Node.js 中使用 ES Module

随着 ES6 使用越来越广泛,Node.js 也支持了 ES6 Module,有几种方法

babel 构建

使用 babel 构建是在 v12 之前版本最简单、通用的方式,具体配置参考 @babel/preset-env(https://babeljs.io/docs/en/babel-preset-env)

.babelrc

{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "8.9.0",
        "esmodules": true
      }      
    }]
  ]
}

原生支持

在 v12 后可以使用原生方式支持 ES Module

  • 开启 --experimental-modules

  • 模块名修改为 .mjs (强烈不推荐使用)或者 package.json 中设置 "type": module

这样 Node.js 会把 js 文件都当做 ES Module 来处理,更多详情参考官方文档(https://nodejs.org/dist/latest-v13.x/docs/api/esm.html)

更多编程相关知识,请访问:编程视频!!

以上がNode.js のモジュール システムを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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