webpackの仕組みについて、見ていきます。
前回↓
前回は、webpackがexportやmodule.exportsをどのように変換するかについて見てみました。
今回は、モジュールのimportやrequireがどのように処理されるかを見てみます。
まず、このようなファイルを作りました。(./modules/greet.js)
ES6 import
これをindex.jsからimportして一部を実行してみます。
すると、変換ファイルがこのとおり。
モジュール定義が2つになりました!
2つ目のモジュールについては、前回見たとおりですね。1つ目のモジュールについて詳しく見ていきます。
まず、関数の引数が増えていますね。第三引数として__webpack_require__が渡されています。どうやらimportを行うモジュールには、これが渡されるようですね。
そして、さっそく__webpack_require__(1)という記述が。
これはgreet.jsモジュールをロードしてますね。ロードした結果、module.exportsが返るので、_greet変数にはgreet.jsで定義したモジュールへの全参照が含まれます。
その次はこんな感じ。
_interopRequireDefaultという関数が使われていますね。引数にオブジェクトを取り、オブジェクトを返します。
オブジェクトが存在しており、__esModuleキーがtrueかどうかで、オブジェクトそのものを返すか、{ default: obj }を返すかを判定していますね。なるほど。
最後にimportしたモジュールの実行を行います。
むむ、、見慣れない記法ですね。
_greet2.default()じゃあダメなんですかね…?謎です。変換前のJavaScriptが複雑化してきたら意味を持つんですかね。ひとまず今はスルーします。
CommonJS require
次はrequireを使った場合について見てみます。
まず、greet.jsをCommonJS式に書き換えます。
次にindex.jsでの読み込みをrequireに変更。
このように変換されます。
なるほど!わかりやすいですね。
__webpack_require__が2度呼ばれていますね。ここでモジュールキャッシュが効いてくるんですね。(第一回を参照)
ES6 import * as hoge
再びES6式に戻って、import * as ~ 形式を試してみます。
greet.jsをES6のexportに書き戻しておきます。
import側はこんな感じ。
変換後のbundle.jsのうち、index.jsの部分はこんな感じ。
むむ。
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関数を抜き出してみました。
まずは、受け取ったオブジェクトのesModuleプロパティがtrueかどうか判定していますね。
trueではない場合には、オブジェクトをそのままreturnせずに新しいオブジェクトを生成してreturnしています。
というわけで、今回はimport / requireがどのように変換されるのか挙動について見てみました。これで、webpackがimportとexportをどのように扱うかを知ることができました。
次回は、複数バンドルについて見ていきます。