regenerator-runtime を少し調べてみた
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ import 時の /runtime はあってもなくても同じファイルをロードしてる
◆ グローバルの定義とモジュールへのエクスポートは常に両方してる
◆ ロードの仕方が用途ごとに 2 パターン書いてるけどどっちでも良いと思う
◆ グローバルの定義とモジュールへのエクスポートは常に両方してる
◆ ロードの仕方が用途ごとに 2 パターン書いてるけどどっちでも良いと思う
@babel/polyfill の代わりに core-js と regenerator-runtime を使うことになって core-js の方はいろいろ見てみましたが regenerator-runtime のほうは触れてませんでした
ジェネレータや非同期関数のランタイムで変換時に各所に埋め込むよりライブラリとして 1 回ロードのほうが無駄が少ないので別にわかれてるのでしたっけ
まぁ そういう babel での変換の一部みたいな印象なので特に気にしてませんでした
ただ せっかくなので軽く見てみることにしました
https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime
メタ的なファイルを除けば path.js と runtime.js の 2 ファイルだけです
それも path.js は runtime.js の絶対パスの文字列をエクスポートするだけというものです
path.js にアクセスできてる時点でその情報がどこで必要なのかイマイチイメージできません
runtime.js の方は 700 行以上で結構長めです
さすがに変換時に ジェネレータや非同期関数を使う各ファイルに埋め込むのは無駄が多すぎます
何するものかわかっているし流し見だけして そういうものね と 流そうかと思ってたら気になるところを見つけました
また グローバルに regeneratorRuntime を定義するならこう書けば良いようです
実際にこれを自分で使うわけではなく babel が変換したコードが使用するわけなのでモジュールとして変数に持っていても仕方ないのでグローバルに定義する一番下の方法を使っています
core-js や babel のドキュメントの例もこれでしたし
ただ package.json を見てみると main が runtime.js です
それだと regenerator-runtime を指定するのも regenerator-runtime/runtime を指定するのも同じになってると思います
regenerator-runtime だとモジュールで regenerator-runtime/runtime だとグローバルに定義という書き方なので 別々のファイルをロードしていて /runtime がある方ではグローバルに定義する処理が追加なのかなと思ったのですがそうではないようです
実際に runtime.js のコードをみてもこうなってました
コメントや中身を略してますが module がオブジェクトなら module.exports を引数で渡してそこにいろいろプロパティを追加しているのでエクスポートするモジュールのプロパティにも機能は入っていますし 最後にグローバルの regeneratorRuntime に代入してるのでグローバル変数にも存在します
つまり エクスポートもするし グローバル変数に代入もするのでどっちでもいいということです
実際 import 時の runtime ありなしも結局同じファイルをロードしてますし
昔の名残なんでしょうかね
ところで グローバル変数への代入が var なし代入で strict mode だと失敗するので Function で関数作って strict モード外で実行というけっこう珍しい方法です
window や global や globalThis で存在するグローバルオブジェクトに対してプロパティ追加がよく見るやつなので特別な理由あるのかと考えましたが特に思いつきませんでした
単に var なしが一番ラクだからそうやっていたのに strict mode で動かされることがあったから元のをベースに strict mode でも動くように簡単に修正した結果なんでしょうか
ジェネレータや非同期関数のランタイムで変換時に各所に埋め込むよりライブラリとして 1 回ロードのほうが無駄が少ないので別にわかれてるのでしたっけ
まぁ そういう babel での変換の一部みたいな印象なので特に気にしてませんでした
ただ せっかくなので軽く見てみることにしました
https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime
メタ的なファイルを除けば path.js と runtime.js の 2 ファイルだけです
それも path.js は runtime.js の絶対パスの文字列をエクスポートするだけというものです
path.js にアクセスできてる時点でその情報がどこで必要なのかイマイチイメージできません
runtime.js の方は 700 行以上で結構長めです
さすがに変換時に ジェネレータや非同期関数を使う各ファイルに埋め込むのは無駄が多すぎます
何するものかわかっているし流し見だけして そういうものね と 流そうかと思ってたら気になるところを見つけました
ロード方法
README.md を見てみると モジュールとしてランタイムをインポートするならこう書けばよくて これが推奨のようです// CommonJS
const regeneratorRuntime = require("regenerator-runtime");
// ECMAScript 2015
import regeneratorRuntime from "regenerator-runtime";
また グローバルに regeneratorRuntime を定義するならこう書けば良いようです
// CommonJS
require("regenerator-runtime/runtime");
// ECMAScript 2015
import "regenerator-runtime/runtime";
実際にこれを自分で使うわけではなく babel が変換したコードが使用するわけなのでモジュールとして変数に持っていても仕方ないのでグローバルに定義する一番下の方法を使っています
import "regenerator-runtime/runtime";
core-js や babel のドキュメントの例もこれでしたし
ただ package.json を見てみると main が runtime.js です
それだと regenerator-runtime を指定するのも regenerator-runtime/runtime を指定するのも同じになってると思います
regenerator-runtime だとモジュールで regenerator-runtime/runtime だとグローバルに定義という書き方なので 別々のファイルをロードしていて /runtime がある方ではグローバルに定義する処理が追加なのかなと思ったのですがそうではないようです
実際に runtime.js のコードをみてもこうなってました
var runtime = (function (exports) {
// 略
return exports
}(
typeof module === "object" ? module.exports : {}
))
try {
regeneratorRuntime = runtime;
} catch (accidentalStrictMode) {
Function("r", "regeneratorRuntime = r")(runtime);
}
コメントや中身を略してますが module がオブジェクトなら module.exports を引数で渡してそこにいろいろプロパティを追加しているのでエクスポートするモジュールのプロパティにも機能は入っていますし 最後にグローバルの regeneratorRuntime に代入してるのでグローバル変数にも存在します
つまり エクスポートもするし グローバル変数に代入もするのでどっちでもいいということです
実際 import 時の runtime ありなしも結局同じファイルをロードしてますし
昔の名残なんでしょうかね
ところで グローバル変数への代入が var なし代入で strict mode だと失敗するので Function で関数作って strict モード外で実行というけっこう珍しい方法です
window や global や globalThis で存在するグローバルオブジェクトに対してプロパティ追加がよく見るやつなので特別な理由あるのかと考えましたが特に思いつきませんでした
単に var なしが一番ラクだからそうやっていたのに strict mode で動かされることがあったから元のをベースに strict mode でも動くように簡単に修正した結果なんでしょうか