Jsモジュールパッケージのエクスポートの使用法と違いにはインポートが必要

Jsモジュールパッケージのエクスポートの使用法と違いにはインポートが必要

1. Commonjsのエクスポートとrequireの使用

Commonejs では、各ファイルがモジュールであると規定されています。スクリプト タグを介して JavaScript ファイルをページに直接導入することと、それを CommonJS モジュールにカプセル化することの最大の違いは、前者のトップレベル スコープがグローバル スコープであるため、変数や関数を宣言するときにグローバル環境が汚染されるのに対し、後者はモジュール自体に属するスコープを形成し、すべての変数と関数はモジュール自体からのみアクセスでき、外部からは見えなくなることです。

1.1 CommonJS エクスポート module.exports

エクスポートは、モジュールを外部に公開する唯一の方法です。 CommonJS では、次のように module.exports を通じてモジュールの内容をエクスポートできます。

モジュール.エクスポート = {
    名前: 'commonJS_exports.js',
    追加: 関数(a, b){
        a + b を返します。
    }
}

記述を簡単にするために、CommonJS はエクスポートを直接使用する別の簡略化されたエクスポート方法もサポートしています。効果は上記と同じです:

exports.name = 'commonJS_exports.js';
exports.add = 関数(a, b){
    a + b を返します。
}

注意: エクスポート時に module.exports と exports を混在させないでください。以下は誤った例です:

exports.add = 関数(a, b){
    a + b を返します。
}
モジュール.エクスポート = {
    名前: 'commonJS_exports.js'
}

上記のコードは、最初に exports を通じて add 属性をエクスポートし、次に module.exports を別のオブジェクトに再割り当てします。これにより、元々 add 属性を持っていたオブジェクトは失われ、名前のみがエクスポートされます。したがって、モジュール内のエクスポート メソッドでは module.exports を使用するか、exports を使用するかのいずれかを選択し、これらを混在させないようにすることをお勧めします。

実際の使用では、可読性を向上させるために、module.exports および exports ステートメントをモジュールの最後に配置する必要があります。

1.2 CommonJSのインポートが必要

CommonJS でモジュールをインポートするには require を使用します。 commonJS_exports.js エクスポート コード:

console.log('...こんにちは、commonJS_exports.jsです...開始します...')
//1. 最初の書き方 module.exports = {
    名前: 'commonJS_exports.js',
    追加: 関数(a, b){
        a + b を返します。
    }
}

PageModule.vue ページにコードをインポートします。

//1. CommonJSのエクスポートをテストし、requireする
var comObj = require('../api/module/commonJS_exports');
console.log('...名前: ', comObj.name);
試す{
      console.log('8 + 9 = ', comObj.add(8, 9));
}キャッチ(e){
      コンソールログ(e);
}

また、同じモジュールがページ内で複数回インポートされた場合、そのモジュールは最初のインポート時にのみ実行されます。それ以降のインポートは実行されませんが、最後の実行の結果が直接エクスポートされます。次に例を示します。

var comObj = require('../api/module/commonJS_exports');
                // インポートを再度呼び出すと、インポートされたモジュールは再度実行されず、最後の実行後に取得された結果が直接エクスポートされることがわかります。 require('../api/module/commonJS_exports');

console.log('...名前: ', comObj.name);
試す{
      console.log('8 + 9 = ', comObj.add(8, 9));
}キャッチ(e){
      コンソールログ(e);
}

次のコンソール出力結果が表示され、インポート モジュールは実際に 1 回だけ実行されています。

....CommonJS のインポートをテストします...

...名前: commonJS_exports.js

8 + 9 = 17

モジュール オブジェクトには、モジュールがロードされたかどうかを記録するために使用される loaded プロパティがあります。デフォルト値は false です。モジュールがロードされ、初めて実行されると、true に設定されます。後で再度ロードされ、module.loaded が true であることがチェックされると、モジュール コードは再度実行されません。
require 関数は式を受け取ることができます。この機能を使用すると、モジュールの読み込みパスを動的に指定できます。

モジュール名をconst ['foo.js', 'bar.js'] に変更します。
モジュール名.forEach(name=>{
   './' + 名前が必要です。
})

2. ES6モジュールのエクスポートとインポートの使用

モジュール機能は、2015 年 6 月に ES6 がリリースされるまで追加されませんでした。 ES6 モジュールも各ファイルをモジュールとして扱います。各モジュールには独自のスコープがあります。唯一の違いは、import ステートメントと export ステートメントです。 ES6 バージョンでは、import と export も予約キーワードとして追加されています (CommonJS の module はキーワードではありません)。

2.1 ES6 モジュールのエクスポート

ES6 モジュールでは、export コマンドを使用してモジュールをエクスポートします。エクスポート形式には次の 2 つがあります。

名前付きエクスポート

デフォルトのエクスポート

2.1.1 名前付きエクスポートを記述する方法は 2 つあります。

//最初のエクスポート方法: 名前付きエクスポート //1.1 名前付きエクスポートの最初の方法 export const name = 'es6_export.js';
エクスポートconst add = function(a, b) { return a + b; }

// //1.2 名前付きエクスポートを書く2番目の方法 // const name = 'es6_export.js'
// const add = function(a, b){ return a + b; }
// { name, add } をエクスポートします。

最初の方法は、変数を 1 行で宣言してエクスポートすることです。2 番目の方法は、最初に変数を宣言し、次に同じエクスポート ステートメントを使用してエクスポートすることです。どちらの書き方でも効果は同じです。名前付きエクスポートを使用する場合は、 as キーワードを使用して変数の名前を変更することもできます。のように:

定数名 = 'es6_export.js'
const add = function(a, b){ return a + b; }
export { name, add as getSum }; // インポート時の name と getSum

2.1.2 名前付きエクスポートとは異なり、モジュールにはデフォルト エクスポートを 1 つだけ設定できます。のように:

//2番目のエクスポート方法: default export export default{
    名前: 'es6_export',
    追加: 関数(a, b){
        a + b を返します。
    }
}

export default は default という名前の変数を外部にエクスポートするものと理解できるので、「named export」のように変数を宣言する必要はなく、直接エクスポートすることができます。

//エクスポート文字列 export default 'これは es6_export.js ファイルです'
 //クラスをエクスポート
 デフォルトクラスをエクスポートします {...}
 //匿名関数をエクスポートする export default function(){ ... }

2.2 ES6 モジュールのエクスポートとインポート

ES6 モジュールは、import 構文を使用してモジュールをインポートします。

2.2.1 名前付きエクスポートモジュールをインポートする方法を見てみましょう

定数名 = 'es6_export.js'
const add = function(a, b){ return a + b; }
エクスポート { 名前、追加 };
// import {name, add } from '../api/module/es6_export.js'; //名前付きエクスポートの最初のインポート メソッド // import * as esObj from '../api/module/es6_export.js'; //名前付きエクスポートの 2 番目のエイリアス全体のインポート メソッド import {name, add as getSum } from '../api/module/es6_export.js'; //名前付きエクスポートの 3 番目のエイリアスのインポート メソッド // //名前付きエクスポートの最初のインポート メソッド // console.log('name: ', name);
// console.log('12 + 21: ', add(12, 21));

// // 名前付きエクスポートの 2 番目のエイリアス インポート メソッド // console.log('name: ', esObj.name);
// console.log('12 + 21: ', esObj.add(12, 21));

                //名前付きエクスポート、3 番目のエイリアス インポート メソッド console.log('name: ', name);
                console.log('12 + 21: ', getSum(12, 21));

名前付きエクスポートを含むモジュールをロードする場合、インポートの後に中括弧のペアを付けてインポートされた変数名を囲む必要があり、これらの変数の名前はエクスポートされた変数と同じである必要があります。変数をインポートする効果は、現在のスコープでこれらの変数 (name および add) を宣言することと同等であり、変更することはできません。つまり、インポートされた変数はすべて読み取り専用です。

さらに、名前付きエクスポートと同様に、 as キーワードを使用してインポートされた変数の名前を変更できます。複数の変数をインポートする場合は、全体のインポート方法を使用することもできます。この import * as <myModule> インポート方法は、インポートされたすべての変数を属性として <myModule> オブジェクトに追加できるため、現在のスコープへの影響を軽減できます。

2.2.2 デフォルトのエクスポートのインポートを見てみましょう

//2番目のエクスポート方法: default export export default{
    名前: 'es6_export.js',
    追加: 関数(a, b){
        a + b を返します。
    }
}
'../api/module/es6_export.js' から esObj をインポートします。

// デフォルト名のテストをインポートします。export console.log('name: ', esObj.name);
console.log('12 + 21: ', esObj.add(12, 21));

デフォルトのエクスポートでは、import の直後に変数名が続き、この名前は自由に指定できます (この場合は esObj など)。これは、es6_export.js 内のデフォルトのエクスポート値を参照します。原則的には次のように理解できます。

'../api/module/es6_export' から { default を esObj として } インポートします。

注: カスタム変数名のデフォルトのエクスポートは、グローバル エイリアスの名前付きエクスポートに似ていますが、名前付きエクスポートのグローバル エイリアスは、インポート後にエイリアスとして * を続ける必要がありますが、デフォルトのエクスポートは、インポート後にカスタム変数名が直接続きます。

最後に、2 つのインポート方法を組み合わせた例を見てみましょう。

react をインポートし、{Component} を 'react' から取得します。

ここでの React はモジュールのデフォルトのエクスポートに対応し、Component はその名前付きエクスポート内の変数です。注意: React は中括弧の前に記述する必要があり、順序を逆にすることはできません。そうしないと、構文エラーが発生します。

2.2.3 複合語

プロジェクトでは、すべてのページまたはコンポーネントを収集するために特別に使用されるエントリ ファイルなど、モジュールをインポートした直後にエクスポートする必要がある場合があります。このとき、複合形を使用できます。

'../api/module/es6_export.js' から {name, add} をエクスポートします。

ただし、上記の複合記述は現在、「名前付きエクスポート」によって公開される変数のみをサポートしています。デフォルトのエクスポートには対応する複合形式がないため、インポートとエクスポートを別々に記述することしかできません。

'../api/module/es6_export.js' から esObj をインポートします。
デフォルトの esObj をエクスポートする

3. CommonJS と ES6 モジュールの違い

上記では、CommonJS と ES6 Module という 2 つの形式のモジュール定義を紹介しました。実際の開発では、この 2 つを混在させることがよくあります。それぞれの特徴を比較してみましょう。

3.1 動的と静的

CommonJS と ES6 モジュールの最も重要な違いは、前者はモジュールの依存関係を「動的に」解決するのに対し、後者は「静的に」解決することです。ここで、「動的」とは、モジュール依存関係の確立がコード実行フェーズ中に行われることを意味し、「静的」とは、モジュール依存関係の確立がコードコンパイルフェーズ中に行われることを意味します。

まず CommonJS の例を見てみましょう。

// 共通JSエクスポート.js
module.exports = { 名前: 'commonJS_exports' }
//ページモジュール.vue
const name = require('../api/module/commonJS_exports').name;

モジュール PageModule.vue がモジュール commonJS_exports.js をロードすると、commonJS_exports.js 内のコードが実行され、その module.exports オブジェクトが require 関数の戻り値として返されます。また、require のモジュール パスは動的に指定でき、式を渡すこともサポートされています。モジュールをロードするかどうかを決定するために、if ステートメントを使用することもできます。したがって、CommonJS モジュールが実行される前に明示的な依存関係を判断する方法はなく、モジュールのインポートとエクスポートはコードの実行時に行われます。
同じ例で、ES6 モジュールの書き方を比較してみましょう。

//es6_エクスポート.js
エクスポート const name = 'es6_export.js';
//ページモジュール.vue
'../api/module/es6_export.js' から { name } をインポートします。

ES6 モジュールの import および export ステートメントはすべて宣言的です。式としてのインポート パスはサポートされておらず、import および export ステートメントはモジュールの最上位スコープに配置する必要があります (たとえば、if ステートメント内に配置することはできません)。

したがって、ES6 モジュールは静的なモジュール構造であり、ES6 コードのコンパイル段階でモジュールの依存関係を分析できると言えます。 CommonJS に比べて次の利点があります。

  • 冗長コードの検出と除去。静的解析ツールを使用して、呼び出されていないモジュールを検出できます。たとえば、ツール ライブラリを導入する場合、プロジェクトではそのコンポーネントまたはインターフェイスの一部のみが使用されることがよくありますが、そのコード全体をロードすることは可能です。呼び出されないモジュール コードは実行されず、冗長コードになります。静的分析を使用すると、パッケージ化中に未使用のモジュールを削除して、パッケージ化されたリソースのサイズを縮小できます。
  • モジュール変数の型チェック。 JavaScript は動的に型付けされる言語であり、コードが実行される前に型エラー (文字列値に対する関数の呼び出しなど) をチェックしません。 ES6 モジュールの静的モジュール構造は、モジュール間で渡される値やインターフェース タイプが正しいことを保証するのに役立ちます。
  • コンパイラの最適化。 CommonJS などの動的モジュール システムでは、どの方法を使用しても、基本的にインポートされるのはオブジェクトですが、ES6 モジュールは変数の直接インポートをサポートしているため、参照レベルが削減され、プログラムの効率が向上します。

3.2 値のコピーと動的マッピング

モジュールをインポートすると、CommonJS はエクスポートされた値のコピーを取得します。ES6 モジュールでは、これは値の動的なマッピングであり、このマッピングは読み取り専用です。例:

//commonJS_exports.js
var カウント = 0;
モジュール.エクスポート = {
    カウント: カウント、
    追加: 関数(a, b){
         カウント+=1;
         a + b を返します。
    }
}
 //ページモジュール.vue
 var count = require('../api/module/commonJS_exports.js').count;
 var add = require('../api/module/commonJS_exports.js').add;
 console.log(count); //0 ここで count は commonJS_exports.js の count 値のコピーです。add(2, 3);
 console.log(count); //0 commonJS_exports.js の変数値を変更しても、ここでのコピー値には影響しません count += 1;
 console.log(count); //1 コピーされた値は変更可能です

PageModule.vue 内の count は commonJS_exports.js 内の count の値のコピーであるため、関数を呼び出すと、元の calculator.js 内の count の値は変更されますが、PageModule.vue にインポートしたときに作成されるコピーには影響しません。一方、CommonJS ではインポートされた値の変更が許可されます。 count を変更し、PageModule.vue に追加して新しい値を割り当てることができます。繰り返しになりますが、値がコピーされるため、これらの操作は calculator.js 自体には影響しません。

上記の例を ES6 モジュールを使用して書き直してみましょう。

//es6_エクスポート.js
count = 0 とします。
定数add = 関数(a, b){
    カウント += 1;
    a + b を返します。
}
エクスポート { count, add }
'../api/module/es6_export' から {name、add、count } をインポートします。

console.log(count); //0、es6_export.js の count 値のマッピング add(2, 3);
console.log(count); //1 は es6_export.js の count 値の変更をリアルタイムで反映します // count += 1; // 変更できません。ReferenceError: count is not defined がスローされます

上記の例は、ES6 モジュールにインポートされた変数が実際には元の値の動的なマッピングであることを示しています。 PageModule.vue の count は、calculator.js の count 値をリアルタイムで反映したものです。add 関数を呼び出して calculator.js の count 値を変更すると、PageModule.vue の count 値もそれに応じて変更されます。

ES6 モジュールによってインポートされた変数を変更することはできません。このマッピング関係はミラーとして理解できます。ミラーから元のオブジェクトをリアルタイムで観察することはできますが、ミラー内のイメージを操作することはできません。

3.3 循環依存関係

循環依存関係とは、モジュール A がモジュール B に依存し、モジュール B がモジュール A に依存する場合です。一般的に言えば、エンジニアリングにおいては循環依存関係はできる限り避けるべきです。ソフトウェア設計の観点からは、一方向の依存関係の方が明確ですが、循環依存関係は一定の複雑さをもたらすからです。実際の開発では、プロジェクトの複雑さが十分な規模にまで高まると、隠れた循環依存関係が現れる可能性があるため、気付かないうちに循環依存関係が発生することがあります。

簡単に言えば、モジュール A と B の間に直接的な循環依存関係があるかどうかを簡単に検出できます。しかし、実際の状況は、A が B に依存し、B が C に依存し、C が D に依存し、そして最後に、ぐるぐる回って D が再び A に依存する、ということがよくあります。中間モジュールが多すぎると、A と B の間に暗黙的な循環依存関係があることを見つけるのが難しくなります。

したがって、循環依存関係をどのように処理するかは、開発者が直面しなければならない問題です。

3.3.1 まず、CommonJS の循環依存問題の例を見てみましょう。

//バー.js
'./foo.js' を require します。
console.log('fooの値: ', foo);
module.exports = 'これは bar.js です';
//foo.js
const bar = require('./bar.js');
console.log('barの値: ', bar);
module.exports = 'これは foo.js です';
//ページモジュール.vue

'../api/module/foo.js' が必要です。
 /*
    結果を印刷:
    foo の値: {}
    barの値: これはbar.jsです
* */

foo の値が空のオブジェクトなのはなぜですか?コードの実際の実行シーケンスを最初から確認してみましょう。

1. PageModule.vue は foo.js をインポートし、foo.js 内のコード実行を開始します。

2. foo.js の最初の文は bar.js をインポートします。このとき、foo.js は下方向に実行を継続せず、bar.js の内部に入ります。

3. bar.js では foo.js が必要であり、循環依存関係が作成されます。ここで注意すべきは、foo.js に実行権が返されるのではなく、そのエクスポート値、つまり module.exports が直接取得されることです。ただし、foo.js は完了まで実行されていないため、この時点ではエクスポートされた値はデフォルトの空のオブジェクトです。そのため、bar.js が print ステートメントを実行すると、コンソールの foo の値は空のオブジェクトであることがわかります。

4. bar.js の実行後、実行権は foo.js に戻ります。

5. foo.jsはrequire文から実行を続け、コンソールにbarの値を出力します(この値は正しいです)。そして、プロセス全体が終了します。

上記から、循環的に依存するモジュールはすべて実行されているものの、モジュールによってインポートされる値は必要なものではないことがわかります。 webpack 実装の観点から見てみましょう。上記の例をパッケージ化した後、バンドルに次のコードを含めることが非常に重要です。

//require関数
関数__webpack_require__(モジュールID){
   if (インストールされたモジュール[モジュールID]) {
        インストールされたモジュール[モジュールID].exportsを返します。
   }
   //新しいモジュールを作成し、キャッシュに格納します
   var module = インストールされたモジュール[モジュールID] = {
        i: モジュールID、
        l: 偽、
        エクスポート: {}
   }
    //...
}

PageModule.vue が foo.js を参照する場合、それは __webpack_require__ 関数を実行し、モジュール オブジェクトを初期化して、それを installedModules に配置することと同じです。 bar.js が再び foo.js を参照すると、関数が再度実行されますが、今回は値が直接installedModules から取得されます。この時点では、module.exports は空のオブジェクトです。これは、上記のステップ 3 で見られる現象を説明しています。

3.3.2 次に、ES6 モジュールを使用して上記の問題の例を書き直します。

//bar_es6.js
'./foo_es6.js' から foo をインポートします。
console.log('fooの値: ', foo);
デフォルトをエクスポートします 'これは bar_es6.js です';
//foo_es6.js
'./bar_es6.js' から bar をインポートします。
console.log('barの値: ', bar);
エクスポート デフォルト 'これは foo_es6.js です';
//ページモジュール.vue
'../api/module/foo_es6.js' から foo_es6 をインポートします。

/* 結果を印刷:
    foo の値: 未定義
    barの値: これはbar_es6.jsです
* */

残念ながら、bar_es6.js も foo_es6.js の正しいエクスポート値を取得できません。唯一の違いは、デフォルトで空のオブジェクトをエクスポートする CommonJS とは異なり、ここで取得される値は未定義であることです。前述のように、モジュールをインポートする場合、CommonJSは値のコピーを取得しますが、ES6モジュールは動的マッピングです。

3.3.3 ES6 モジュールの機能を使用して循環依存関係をサポートしましょう (正しい例):

//bar_es6_2.js
'./foo_es6_2.js' から foo をインポートします。
呼び出された = false;
関数バー(呼び出し元){
    (!呼び出された場合){
        呼び出された = true;
        console.log(invoker + ' は bar_es6_2.js を呼び出します');
        'bar_es6_2.js' をコピーします。
    }
}
デフォルトバーをエクスポートします。
//foo_es6_2.js
'./bar_es6_2.js' から bar をインポートします。
関数foo(呼び出し元){
    console.log(invoker + ' は foo_es6_2.js を呼び出します');
    バー('foo_es6_2.js');
}
デフォルトの foo をエクスポートします。
'../api/module/foo_es6_2.js' から foo_es6_2 をインポートします。

foo_es6_2('PageModule.vue');
/* 結果を印刷:
    PageModule.vue は foo_es6_2.js を呼び出します。
    foo_es6_2.js は bar_es6_2.js を呼び出します。
    bar_es6_2.js は foo_es6_2.js を呼び出します。
* */

循環依存モジュール foo_es6_2.js と bar_es6_2.js は両方とも正しいエクスポート値を取得していることがわかります。コードの実行プロセスを分析してみましょう。

1. PageModule.vue はエントリ ポイントとして foo_es6_2.js をインポートし、foo_es6_2.js 内のコード実行を開始します。

2. foo_es6_2.js から bar_es6_2.js をインポートし、bar_es6_2.js に実行権限を付与します。

3. bar_es6_2.js を最後まで実行して、bar 関数の定義を完了します。この時点では、foo_es6_2.js はまだ実行されていないため、foo の値はまだ未定義であることに注意してください。

4. 実行は foo_es6_2.js に戻り、終了するまで継続され、foo 関数の定義が完了します。 ES6 モジュールの動的マッピング機能により、bar_es6_2.js の foo の値は undefined から定義した関数に変更されました。これが、循環依存関係を解決する際の CommonJS との本質的な違いです。CommonJS でインポートされたものはコピーされ、モジュール内の元の値が変更されても変更されません。

5. 実行は PageModule.vue に戻り、foo 関数を呼び出します。このとき、foo-->bar-->foo が順に実行され、コンソールに正しい値が表示されます。

上記の例からわかるように、ES6 モジュールの機能により、循環依存関係をより適切にサポートできます。インポートされた値を使用するときに正しいエクスポート値が設定されていることを確認するのは開発者の責任です。

4. モジュールパッケージの原則

プロジェクト内に数百または数千のモジュールがある場合、webpack はどのようにしてそれらを整然と整理し、期待どおりの順序でブラウザー上で実行するのでしょうか?以下ではその原理について説明します。

前の例を使ってみましょう:

//commonJS_exports.js
モジュール.エクスポート = {
    追加: 関数(a, b){
        a + b を返します。
    }
}
//ページモジュール.vue
const comObj = require('../api/module/commonJS_exports');
定数sum = comObj.add(2, 3);
console.log('合計: ', 合計);

上記のコードは、Webpack によってパッケージ化された後、次の形式になります (読みやすくするために、ここではコードの回答構造のみを示します)。

//無名関数をすぐに実行する (function(modules){
        //モジュール キャッシュ var installedModules = {};
        //requireを実装する
        関数__webpack_require__(モジュールID){
            //...
        }
        //エントリモジュールの読み込みを実行します return __webpack_require__(__webpack__require__.s == 0);
 })({
        //modules: パッケージ化されたすべてのモジュールをキーと値の形式で保存します0: function(module, exports, __webpack_require__){
            //パッケージエントリ module.exports = __webpack_require__("3qiv");
        },
        "3qiv": 関数(モジュール、エクスポート、__webpack_require__){
            //PageModule.vue コンテンツ},
        jkzz: 関数(モジュール、エクスポート){
            //commonJS_exports.js コンテンツ}
})

これは最も単純な Webpack バンドルですが、依存関係を持つモジュールをどのように接続するかを明確に示すことができます。上記のバンドルは次の部分に分かれています:

  • 最も外側の匿名関数は直ちに実行されます。バンドル全体をラップし、独自のスコープを構成するために使用されます。
  • installedModules オブジェクト。各モジュールは最初にロードされたときにのみ実行され、その後はエクスポートされた値がこのオブジェクトに保存されます。再度ロードされると、再実行されずにここから値が直接取得されます。
  • __webpack_require__ 関数。モジュールの読み込みの実装では、__webpack_require__(moduleId) を呼び出すことでブラウザ内でモジュールのインポートを完了できます。
  • モジュール オブジェクト。プロジェクト内で依存関係を持つすべてのモジュールは、キーと値の形式でここに配置されます。キーは、数値または非常に短いハッシュ文字列で構成されるモジュールの ID として理解できます。値は、匿名関数によってラップされたモジュール エンティティであり、匿名関数のパラメーターによって、各モジュールにエクスポートとインポートの機能が付与されます。

次に、ブラウザでバンドルがどのように実行されるかを見てみましょう。

1. ブラウザ実行環境は、モジュールの読み込みと実行の準備として、installedModules オブジェクトの定義、__webpack_require__ 関数などを含む最も外側の匿名関数で初期化されます。

2. エントリモジュールをロードします。各バンドルにはエントリ モジュールが 1 つだけあります。上記の例では、PageModule.vue がエントリ モジュールであり、ブラウザーはそこから実行を開始します。

3. モジュールコードを実行します。 module.exports を実行するとモジュールのエクスポート値が記録され、途中で require 関数 (正確には __webpack_require__) に遭遇すると、一時的に実行権が渡され、__webpack_require__ 関数の本体に入り、他のモジュールのロジックが読み込まれます。

4. __webpack_require__ では、ロードするモジュールがinstalledModulesに存在するかどうかを判断します。存在する場合は値を直接取得し、存在しない場合は手順 3 に戻り、モジュールのコードを実行してエクスポートされた値を取得します。

5. 依存モジュールがすべて実行され、最終的に実行権がエントリ モジュールに戻ります。エントリ モジュールのコードが最後まで実行されると、バンドル全体が終了したことを意味します。

ステップ 3 と 4 が再帰的なプロセスであることは、簡単にわかります。Webpack は、各モジュールがモジュールをエクスポートおよびインポートするための環境を作成しますが、本質的にはコードの実行ロジックを変更しません。したがって、コードの実行順序は、モジュールのロード順序とまったく同じです。これが、Webpack モジュール パッケージングの秘密です。

上記は、Js モジュール パッケージのエクスポートとインポートの違いの使用方法と違いの詳細な内容です。Js モジュール パッケージの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • vue-cli3.0 での CSS、JS、画像のパッケージ パスのカスタマイズの詳細な説明
  • BlueShow v1.0 リリース 画像ブラウザ(ライトボックスに類似) blueshow.js パッケージのダウンロード
  • vue.config.js パッケージ最適化構成
  • video.js をコンパイルしてパッケージ化する方法を段階的に説明します
  • nuxt.jsは、プロジェクトのパッケージ環境操作を区別するために環境変数を追加します。
  • vue は uglifyjs-webpack-plugin パッケージング エラーの問題を解決します
  • Vue.js をパッケージ化後に容量を圧縮する方法のまとめ(Vue.js はパッケージ化後容量が大きすぎる)
  • Vue パッケージ化後に vendor.js ファイルが大きくなりすぎる問題を解決する
  • js は複数の画像を zip にパッケージ化します

<<:  MySQL の一般的な日付比較および計算関数

>>:  Docker実践: Pythonアプリケーションのコンテナ化

推薦する

LambdaProbe を使用して Tomcat を監視する方法

導入: Lambda Probe (旧称 Tomcat Probe) は、Apache Tomcat...

この記事ではJavaScriptの基本であるディープコピーとシャローコピーについて説明します。

目次浅いコピーディープコピー補充する要約するコピー(クローン、複製などとも呼ばれる)ですが、ディープ...

Linux Centos7 に mysql8 をインストールするチュートリアル

1. RPMバージョンのインストールデータベースの他のバージョンがあるかどうかを確認し、ある場合は完...

JavaScript の new 演算子を自分で実装する方法

目次コンストラクタ新しいオペレーター自分で新しいものを実装するコンストラクタnew を導入する前に、...

よく使われる HTML 形式のタグ_Powernode Java Academy

1. タイトルHTML では、<h1></h1> から <h6>...

Ubuntu 16.04 64ビット版を3つのステップで32ビットプログラムと互換性を持たせる

ステップ1: システムのアーキテクチャを確認する dpkg --print-architecture...

スクロール時に選択領域のフォント色を暗くするために CSS を使用するサンプルコード

日付ピッカーをカプセル化する場合、選択時にフォントの色を暗くする必要があります。実装後の効果を見てみ...

Linux クラウド サーバーに新しいディスクをマウントする方法

背景社内に新しいサーバーが追加され、2Tのハードディスクがマウントされました。sshでログイン後、マ...

MySQLのデフォルトのソートルールに基づく落とし穴

MySQL のデフォルトの varchar 型は大文字と小文字を区別しません (insensitiv...

JavaScript で判決文をエレガントに記述する例

目次序文1. モナドの判断1.1 例1.2 オブジェクトに入れる1.3 マップに載せる2. 複数の判...

MySQL学習データベース操作DML初心者向け詳細解説

目次1. ステートメントを挿入する1.1 行を挿入する1.2 複数行を挿入する1.3 クエリステート...

Robots.txtの詳細な紹介

Robots.txt はプレーンテキスト ファイルであり、Web サイト管理者は、ロボットによるアク...

オペレーターが知っておくべき 18 個の Nginx プロキシ キャッシュ構成のヒント (どれを知っていますか?)

アプリケーションや Web サイトのパフォーマンスが成功の重要な要素であることは誰もが知っています。...

Win10にmysql8.0.15 winx64をインストールしてサーバーに接続する際に問題が発生しました

1. mysql-8.0.15をダウンロード、インストール、設定する1. 公式サイト (https:...

Apacheドメイン名設定の落とし穴の詳細な説明

私はApacheを使ったことがありません。仕事を始めてからはずっとnginxを使っていました(運用保...