最近、Vue.jsを利用する機会が増えてきました。概念もなんとなく理解してきましたが、「じゃあ実際どうやって動いているの?」と聞かれるとわからないですよね。
ということで、Vue.jsのファイルを読み解いてみようと思います。
今回は、CDNで提供されている、下記のソースを使います。
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
即時関数だ!
今回は全体の構造を眺めていきましょう。
スクリプトの出だしはこのようになっています。
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.Vue = factory());
}(this, function () { 'use strict';
// ...(省略)
}))
うお、長え!と思うかもしれませんが、単純化するとこうなっています。
(function (global, factory){
a===b && c!==d ? E : f===g && h ? I : (j=k || l, m=o)
}(this, function () {
// ...(省略)
}))
(function(a, b){
// 関数の中身
})(c, d)
という形は即時関数の形式です。
http://analogic.jp/immediate-function/
vue.jsが読み込まれた際に function(a, b)
が実行されます。そして、引数 a
, b
にはc
, d
がそれぞれ代入されます。
今回の場合、global
にthis
、そしてfactory
に1万行を超えるvue.jsの関数がそれぞれ代入されるわけですね!
ちなみに、this
にはブラウザで実行した場合、Window
オブジェクトが入ります。
条件分岐がたくさん
さて、ではglobal
, factory
はそれぞれどのような処理がされるのでしょうか?
それが、次の三項演算子パラダイスの即時関数の中身です。
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.Vue = factory());
ここで、三項演算子を簡単におさらいしましょう。
(true or false) ? 'trueだった場合の処理' : 'falseだった場合の処理'
これに基づいて、分類をしてみます。
1 typeof exports === 'object' && typeof module !== 'undefined'
2 ? module.exports = factory()
3 : typeof define === 'function' && define.amd
4 ? define(factory)
5 : (global = global || self, global.Vue = factory());
1行目は丸々条件式です。
true
になる条件は「 exports
がオブジェクト型で、かつ module
が存在する」です。
true
だった場合、module.exports に factory()
がセットされます。
つまり、Node上だったらモジュールとして機能する、ということですね!
false
だった場合、さらに条件分岐が続きます。
3行目がtrueになる条件は「define
が関数で、かつdefine.amd
が存在するとき」です。
true
だった場合、define
にfactory
がぶち込まれます。
これは、AMD(Asynchronous Module Definition)を使う際の処理です。
false
だった場合、
global
には global
, もしくは self
が代入されます。
この論理演算子 ||
についてはこちらを参照のこと。
https://qiita.com/Imamotty/items/bc659569239379dded55
global
はthis
, つまり window
オブジェクトのことでしたね。
そして最後に、そのglobal
のVue
にfactory()
を突っ込んでいる、というわけです。
つまり、ここでの処理は、AMDかNodeJSかそれ以外(ブラウザ)かによって、factory()
(Vueの本体)を読み込ませる処理の方法を分岐させていたんですね!
ちなみに、global
, factory
を引数にもつ即時関数を用意し、内部でそれぞれの環境に応じて処理を分岐させる手法は、 UMD (Universal Module Definition) と呼ばれています!
ここら辺のリンクに詳細があります。
https://www.davidbcalhoun.com/2014/what-is-amd-commonjs-and-umd/
https://qiita.com/chuck0523/items/1868a4c04ab4d8cdfb23
今回はここまでにします。
メソッド単位でちょこちょこ記事が書けたらいいな、と思っています!