ホームページ ウェブフロントエンド jsチュートリアル Webpack モジュールの基本原理の詳細な説明

Webpack モジュールの基本原理の詳細な説明

May 31, 2018 pm 01:58 PM
web webpack 基本

この記事では主に webpack 組織モジュールの原理を紹介し、参考にさせていただきます。

現在では、Webpack を使用してフロントエンドで JS やその他のファイルをパッケージ化することが主流になり、Node の普及と相まって、フロントエンドのエンジニアリング手法はますますバックエンドに似てきています。すべてはモジュール化され、最終的にはまとめてコンパイルされます。 Webpack のバージョンは常に更新され、さまざまな複雑な設定オプションがあるため、使用中に不可解なエラーが発生し、人々が混乱することがよくあります。したがって、Webpack がコンパイルされたモジュールをどのように編成し、生成されたコードがどのように実行されるかを理解することは非常に有益です。そうでないと、常にブラック ボックスになります。もちろん私はフロントエンドの初心者で、最近 Webpack の原理を勉強し始めたばかりなので、ここでいくつかメモしておきます。

コンパイルされたモジュール

「コンパイル」という言葉は非常にハイテクに聞こえ、生成されたコードは理解できないものが入り乱れていることが多いため、人々を怖がらせてしまうことがよくありますが、実際には、内部の中心原則は「コンパイルとは何か」ではありません。難しい。 Webpack のいわゆるコンパイルは、実際には、Webpack がソース コードを分析し、それに特定の変更を加えた後、すべてのソース コードを 1 つのファイルに編成するだけです。最後に、大きなバンドル JS ファイルが生成され、ブラウザまたは他の Javascript エンジンによって実行され、結果が返されます。

ここでは、Webpack パッケージ化モジュールの原理を説明するための簡単なケースを示します。例えば、mA.js

var aa = 1;

function getDate() {
 return new Date();
}

module.exports = {
 aa: aa,
 getDate: getDate
}
ログイン後にコピー

というモジュールがあるので、変数aaと関数getDateを適当に定義して、CommonJSを使った書き方を紹介します。

次に、CommonJS スタイルのまま、app.js をメイン ファイルとして定義します。

var mA = require('./mA.js');

console.log('mA.aa =' + mA.aa);
mA.getDate();
ログイン後にコピー

これで、Webpack を使用してパッケージ化された 2 つのモジュールができました。エントリ ファイルは app.js で、モジュール mA.js に依存します。 , Webpack やるべきことがいくつかあります:

  1. エントリーモジュールapp.jsから開始し、すべてのモジュールの依存関係を分析し、使用されているすべてのモジュールを読み込みます。

  2. 各モジュールのソースコードは、すぐに実行される関数にまとめられます。

  3. モジュールコード内のrequireとexportに関連する構文と、それらに対応する参照変数を書き換えます。

  4. 最終的に生成されたバンドル ファイル内にモジュール管理システムを確立します。これにより、使用されるモジュールを実行時に動的にロードできます。

Webpack パッケージ化の結果である上記の例を見てみましょう。最終的なバンドル ファイルは通常、すぐに実行される大きな関数であり、組織レベルは比較的複雑で、多くの名前が比較的わかりにくいため、ここでいくつかの書き直しと変更を加えて、できるだけシンプルで理解しやすいものにしました。可能。

まず、使用されているすべてのモジュールをリストし、そのファイル名 (通常はフルパス) を ID として使用してテーブルを作成します:

var modules = {
 './mA.js': generated_mA,
 './app.js': generated_app
}
ログイン後にコピー
ログイン後にコピー

重要なのは、上記の generated_xxx とは何かということです。各モジュールのソースコードを内部にラップしてローカルスコープにし、内部変数が露出しないようにし、実際に各モジュールを実行関数にする関数です。その定義は一般に次のようになります:

function generated_module(module, exports, webpack_require) {
  // 模块的具体代码。
  // ...
}
ログイン後にコピー

ここでのモジュールの特定のコードは、Webpack が生成コードと呼ぶ、生成されたコードを指します。たとえば、mA を書き換えると、結果は次のようになります。

function generated_mA(module, exports, webpack_require) {
 var aa = 1;
 
 function getDate() {
  return new Date();
 }

 module.exports = {
  aa: aa,
  getDate: getDate
 }
}
ログイン後にコピー

一見すると、ソースコードとまったく同じように見えます。確かに、mA は他のモジュールを必要としたりインポートしたりする必要がなく、エクスポートでも従来の CommonJS スタイルを使用するため、生成されたコードに変更はありません。ただし、最後の module.exports = ... であることは注目に値します。ここでのモジュールは外部から渡されるパラメーター module であり、実際には、この関数が実行されるとモジュール mA のソース コードが実行されることがわかります。そして最後に、エクスポートする必要のあるコンテンツが外部に保存されます。これで mA のロードが完了しました。外部のものは、実際には後で説明するモジュール管理システムです。

次に、app.js の生成されたコードを見てみましょう:

function generated_app(module, exports, webpack_require) {
 var mA_imported_module = webpack_require('./mA.js');
 
 console.log('mA.aa =' + mA_imported_module['aa']);
 mA_imported_module['getDate']();
}
ログイン後にコピー

インポートされたモジュール mA に関して app.js のソース コードが変更されていることがわかります。これは、それが require/exports であるか、ES6 スタイルのインポートであるかに関係なく、 /export は、JavaScript インタプリタによって直接実行することはできません。これらの抽象キーワードを具体化するには、モジュール管理システムに依存する必要があります。つまり、webpack_require は require の特定の実装であり、モジュール mA を動的にロードして結果をアプリに返すことができます。

この時点で、モジュール管理システムのアイデアが徐々に頭の中に構築されているかもしれません。webpack_require の実装を見てみましょう:

// 加载完毕的所有模块。
var installedModules = {};

function webpack_require(moduleId) {
 // 如果模块已经加载过了,直接从Cache中读取。
 if (installedModules[moduleId]) {
  return installedModules[moduleId].exports;
 }

 // 创建新模块并添加到installedModules。
 var module = installedModules[moduleId] = {
  id: moduleId,
  exports: {}
 };
 
 // 加载模块,即运行模块的生成代码,
 modules[moduleId].call(
  module.exports, module, module.exports, webpack_require);
 
 return module.exports;
}
ログイン後にコピー

最後から 2 番目の文のモジュールがすべてのモジュールに対して生成されることに注意してください。以前に定義したコード:

var modules = {
 './mA.js': generated_mA,
 './app.js': generated_app
}
ログイン後にコピー
ログイン後にコピー

webpack_require のロジックは非常に明確に記述されています。まず、モジュールがロードされているかどうかを確認し、ロードされている場合は、モジュールのエクスポート結果をキャッシュから直接返します。新しいモジュールの場合は、対応するデータ構造モジュールを作成し、このモジュールの生成されたコードを実行します。この関数が渡すのは、作成したモジュール オブジェクトとそのエクスポート フィールドです。これは、実際には CommonJS のエクスポート フィールドとエクスポート フィールドです。 . モジュールの起源。この関数を実行すると、モジュールがロードされ、エクスポートする必要がある結果がモジュール オブジェクトに保存されます。

所以我们看到所谓的模块管理系统,原理其实非常简单,只要耐心将它们抽丝剥茧理清楚了,根本没有什么深奥的东西,就是由这三个部分组成:

// 所有模块的生成代码
var modules;
// 所有已经加载的模块,作为缓存表
var installedModules;
// 加载模块的函数
function webpack_require(moduleId);
ログイン後にコピー

当然以上一切代码,在整个编译后的bundle文件中,都被包在一个大的立即执行的匿名函数中,最后返回的就是这么一句话:

return webpack_require(‘./app.js');
ログイン後にコピー

即加载入口模块app.js,后面所有的依赖都会动态地、递归地在runtime加载。当然Webpack真正生成的代码略有不同,它在结构上大致是这样:

(function(modules) {
 var installedModules = {};
 
 function webpack_require(moduleId) {
   // ...
 }

 return webpack_require('./app.js');
}) ({
 './mA.js': generated_mA,
 './app.js': generated_app
});
ログイン後にコピー

可以看到它是直接把modules作为立即执行函数的参数传进去的而不是另外定义的,当然这和上面的写法没什么本质不同,我做这样的改写是为了解释起来更清楚。

ES6的import和export

以上的例子里都是用传统的CommonJS的写法,现在更通用的ES6风格是用import和export关键词,在使用上也略有一些不同。不过对于Webpack或者其它模块管理系统而言,这些新特性应该只被视为语法糖,它们本质上还是和require/exports一样的,例如export:

export aa
// 等价于:
module.exports['aa'] = aa

export default bb
// 等价于:
module.exports['default'] = bb
ログイン後にコピー

而对于import:

import {aa} from './mA.js'
// 等价于
var aa = require('./mA.js')['aa']
ログイン後にコピー

比较特殊的是这样的:

import m from './m.js'
ログイン後にコピー

情况会稍微复杂一点,它需要载入模块m的default export,而模块m可能并非是由ES6的export来写的,也可能根本没有export default,所以Webpack在为模块生成generated code的时候,会判断它是不是ES6风格的export,例如我们定义模块mB.js:

let x = 3;

let printX = () => {
 console.log('x = ' + x);
}

export {printX}
export default x
ログイン後にコピー

它使用了ES6的export,那么Webpack在mB的generated code就会加上一句话:

function generated_mB(module, exports, webpack_require) {
 Object.defineProperty(module.exports, '__esModule', {value: true});
 // mB的具体代码
 // ....
}
ログイン後にコピー

也就是说,它给mB的export标注了一个__esModule,说明它是ES6风格的export。这样在其它模块中,当一个依赖模块以类似import m from './m.js'这样的方式加载时,会首先判断得到的是不是一个ES6 export出来的模块。如果是,则返回它的default,如果不是,则返回整个export对象。例如上面的mA是传统CommonJS的,mB是ES6风格的:

// mA is CommonJS module
import mA from './mA.js'
console.log(mA);

// mB is ES6 module
import mB from './mB.js'
console.log(mB);
ログイン後にコピー

我们定义get_export_default函数:

function get_export_default(module) {
 return module && module.__esModule? module['default'] : module;
}
ログイン後にコピー

这样generated code运行后在mA和mB上会得到不同的结果:

var mA_imported_module = webpack_require('./mA.js');
// 打印完整的 mA_imported_module
console.log(get_export_default(mA_imported_module));

var mB_imported_module = webpack_require('./mB.js');
// 打印 mB_imported_module['default']
console.log(get_export_default(mB_imported_module));
ログイン後にコピー

这就是在ES6的import上,Webpack需要做一些特殊处理的地方。不过总体而言,ES6的import/export在本质上和CommonJS没有区别,而且Webpack最后生成的generated code也还是基于CommonJS的module/exports这一套机制来实现模块的加载的。

模块管理系统

以上就是Webpack如何打包组织模块,实现runtime模块加载的解读,其实它的原理并不难,核心的思想就是建立模块的管理系统,而这样的做法也是具有普遍性的,如果你读过Node.js的Module部分的源代码,就会发现其实用的是类似的方法。这里有一篇文章可以参考。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

vue iview组件表格 render函数的使用方法详解

微信小程序实现换肤功能

nodejs实现解析xml字符串为对象的方法示例

以上がWebpack モジュールの基本原理の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

VUE3 入門チュートリアル: Webpack を使用したパッケージ化とビルド VUE3 入門チュートリアル: Webpack を使用したパッケージ化とビルド Jun 15, 2023 pm 06:17 PM

Vue は、インタラクティブで効率的な Web アプリケーションを迅速に構築するのに役立つ優れた JavaScript フレームワークです。 Vue3 は、多くの新機能が導入された Vue の最新バージョンです。 Webpack は現在最も人気のある JavaScript モジュール パッケージャーおよびビルド ツールの 1 つで、プロジェクト内のさまざまなリソースの管理に役立ちます。この記事では、Webpack を使用して Vue3 アプリケーションをパッケージ化してビルドする方法を紹介します。 1.Webpackをインストールする

Java API開発におけるWebサーバー処理にJetty7を使用する Java API開発におけるWebサーバー処理にJetty7を使用する Jun 18, 2023 am 10:42 AM

JavaAPI 開発における Web サーバー処理に Jetty7 を使用する インターネットの発展に伴い、Web サーバーはアプリケーション開発の中核部分となり、多くの企業でも注目を集めています。増大するビジネス ニーズを満たすために、多くの開発者が Web サーバー開発に Jetty の使用を選択しており、その柔軟性と拡張性は広く認識されています。この記事では、JavaAPI 開発における Jetty7 の使用方法を紹介します。

ウェブ上の顔面ブロック攻撃に対するリアルタイム保護 (機械学習に基づく) ウェブ上の顔面ブロック攻撃に対するリアルタイム保護 (機械学習に基づく) Jun 10, 2023 pm 01:03 PM

顔面遮蔽弾幕とは、映像内の人物を遮ることなく大量の弾幕が浮遊し、人物の背後から浮遊しているように見せることです。機械学習は数年前から普及していますが、これらの機能がブラウザでも実行できることは多くの人に知られていません。この記事では、ビデオ連発における実際的な最適化プロセスを紹介します。記事の最後に、適用可能なシナリオをいくつか示します。このソリューションを開くことを望んでいます。いくつかのアイデアがあります。 mediapipeDemo (https://google.github.io/mediapipe/) は、顔ブロック弾幕のオンデマンドアップアップロードの主流の実装原理を示していますサーバーのバックグラウンド計算により、ビデオ画面内のポートレート領域を抽出し、SVG ストレージに変換しますクライアントがビデオを再生している間、サーバーから SVG をダウンロードし、弾幕、ポートレートと組み合わせる

FRPS サーバーと Web がポート 80 を共有するように nginx を設定する方法 FRPS サーバーと Web がポート 80 を共有するように nginx を設定する方法 Jun 03, 2023 am 08:19 AM

まず、frpって何?という疑問があると思います。簡単に言うと、frp はイントラネット侵入ツールであり、クライアントを設定すると、サーバー経由でイントラネットにアクセスできるようになります。現在、私のサーバーは Web サイトとして nginx を使用しており、ポート 80 が 1 つだけあります。では、FRP サーバーもポート 80 を使用したい場合はどうすればよいでしょうか?クエリ後、nginx のリバース プロキシを使用してこれを実現できます。追加: frps はサーバー、frpc はクライアントです。ステップ 1: サーバーの nginx.conf 構成ファイルを変更し、次のパラメータを nginx.conf の http{} に追加します。server{listen80

Golang を使用して Web アプリケーションのフォーム検証を実装する方法 Golang を使用して Web アプリケーションのフォーム検証を実装する方法 Jun 24, 2023 am 09:08 AM

フォーム検証は Web アプリケーション開発において非常に重要なリンクであり、フォーム データを送信する前にデータの有効性をチェックして、アプリケーションのセキュリティ脆弱性やデータ エラーを回避できます。 Web アプリケーションのフォーム検証は、Golang を使用すると簡単に実装できます。この記事では、Golang を使用して Web アプリケーションのフォーム検証を実装する方法を紹介します。 1. フォーム検証の基本要素 フォーム検証の実装方法を紹介する前に、フォーム検証の基本要素が何であるかを知る必要があります。フォーム要素: フォーム要素は

コックピット Web UI から管理アクセスを有効にする方法 コックピット Web UI から管理アクセスを有効にする方法 Mar 20, 2024 pm 06:56 PM

Cockpit は、Linux サーバー用の Web ベースのグラフィカル インターフェイスです。これは主に、初心者/熟練ユーザーにとって Linux サーバーの管理を容易にすることを目的としています。この記事では、Cockpit アクセス モードと、CockpitWebUI から Cockpit への管理アクセスを切り替える方法について説明します。コンテンツ トピック: コックピット エントリ モード 現在のコックピット アクセス モードの確認 CockpitWebUI からコックピットへの管理アクセスを有効にする CockpitWebUI からコックピットへの管理アクセスを無効にする まとめ コックピット エントリ モード コックピットには 2 つのアクセス モードがあります。 制限付きアクセス: これは、コックピット アクセス モードのデフォルトです。このアクセス モードでは、コックピットから Web ユーザーにアクセスできません。

ウェブ標準とは何ですか? ウェブ標準とは何ですか? Oct 18, 2023 pm 05:24 PM

Web 標準は、W3C およびその他の関連組織によって策定された一連の仕様とガイドラインです。HTML、CSS、JavaScript、DOM、Web アクセシビリティおよびパフォーマンスの最適化の標準化が含まれます。これらの標準に従うことで、ページの互換性を向上させることができます。 、メンテナンス性とパフォーマンス。 Web 標準の目標は、Web コンテンツをさまざまなプラットフォーム、ブラウザー、デバイス上で一貫して表示および操作できるようにして、より優れたユーザー エクスペリエンスと開発効率を提供することです。

ウェブってどういう意味ですか ウェブってどういう意味ですか Jan 09, 2024 pm 04:50 PM

Web は、ワールド ワイド ウェブとしても知られるグローバル ワイド エリア ネットワークであり、インターネットのアプリケーション形式です。 Web はハイパーテキストとハイパーメディアに基づいた情報システムであり、ユーザーはハイパーリンクを通じて異なる Web ページ間を移動することにより、情報を閲覧したり入手したりすることができます。 Web の基礎はインターネットであり、統一および標準化されたプロトコルと言語を使用して、異なるコンピューター間でのデータ交換と情報共有を可能にします。

See all articles