コンパイラかく語りき

import { Fun } from 'programming'

webpackはどのように動いているのか(3)

webpackの仕組みについて、見ていきます。

前回↓ 

chuckwebtips.hatenablog.com

 

前回は、webpackがexportやmodule.exportsをどのように変換するかについて見てみました。

今回は、モジュールのimportやrequireがどのように処理されるかを見てみます。

 

まず、このようなファイルを作りました。(./modules/greet.js)

gist.github.com

 

ES6 import

これをindex.jsからimportして一部を実行してみます。

 

gist.github.com

 

すると、変換ファイルがこのとおり。

gist.github.com

 

モジュール定義が2つになりました!

2つ目のモジュールについては、前回見たとおりですね。1つ目のモジュールについて詳しく見ていきます。

 

gist.github.com

 

まず、関数の引数が増えていますね。第三引数として__webpack_require__が渡されています。どうやらimportを行うモジュールには、これが渡されるようですね。

 

そして、さっそく__webpack_require__(1)という記述が。

これはgreet.jsモジュールをロードしてますね。ロードした結果、module.exportsが返るので、_greet変数にはgreet.jsで定義したモジュールへの全参照が含まれます。

 

gist.github.com

 

その次はこんな感じ。

 

gist.github.com

 

_interopRequireDefaultという関数が使われていますね。引数にオブジェクトを取り、オブジェクトを返します。

オブジェクトが存在しており、__esModuleキーがtrueかどうかで、オブジェクトそのものを返すか、{ default: obj }を返すかを判定していますね。なるほど。

 

最後にimportしたモジュールの実行を行います。

 

gist.github.com

 

むむ、、見慣れない記法ですね。

_greet2.default()じゃあダメなんですかね…?謎です。変換前のJavaScriptが複雑化してきたら意味を持つんですかね。ひとまず今はスルーします。

 

CommonJS require

次はrequireを使った場合について見てみます。

 

まず、greet.jsをCommonJS式に書き換えます。

 

gist.github.com

 

次にindex.jsでの読み込みをrequireに変更。

 

gist.github.com

 

このように変換されます。

 

gist.github.com

 

なるほど!わかりやすいですね。

__webpack_require__が2度呼ばれていますね。ここでモジュールキャッシュが効いてくるんですね。(第一回を参照)

 

 

ES6 import * as hoge

再びES6式に戻って、import * as ~ 形式を試してみます。

greet.jsをES6のexportに書き戻しておきます。

 

gist.github.com

 

import側はこんな感じ。

 

gist.github.com

 

変換後のbundle.jsのうち、index.jsの部分はこんな感じ。

 

gist.github.com

 

むむ。

export defaultの時は、_interopRequireDefaultが呼ばれましたが、今回は、_interopRequireWildcardが呼ばれていますね。

 

ここはBabelの機能のようですね。importの種類によって、異なる関数を生成します。

export hoge & import hoge from 'hoge' -> __webpack_require__のみ

 

export default hoge & import hoge from 'hoge' -> __webpack_require__ + _interopRequireDefault

 

import * as hoge from 'hoge' -> __webpack_require__ + _interopRequireWildcard

 

ざっくりと。

 

_interopRequireWildcard関数を抜き出してみました。

 

gist.github.com

 

まずは、受け取ったオブジェクトのesModuleプロパティがtrueかどうか判定していますね。

 trueではない場合には、オブジェクトをそのままreturnせずに新しいオブジェクトを生成してreturnしています。

 

 

というわけで、今回はimport / requireがどのように変換されるのか挙動について見てみました。これで、webpackがimportとexportをどのように扱うかを知ることができました。

 

次回は、複数バンドルについて見ていきます。