Babel と tsc どっちがいいのか気になったので調べて見たメモ
結論から言うと基本的には tsc で良い
目次
確認環境
Env | Ver |
---|---|
@babel/cli | 7.14.5 |
@babel/core | 7.14.6 |
@babel/preset-env | 7.14.7 |
@babel/preset-typescript | 7.14.5 |
typescript | 4.3.2 |
Babel とは何か?
What is Babel? より Babel とは JavaScript のコンパイラと説明されている
Babel がしてくれること
- 構文の変換
- corejs を使った Polyfill
- ソースコードの変換(codemods
- その他色々
基本的には ES6+を ES6 にしてくれると考えれば良さそうです
でもそれって別に tsc でもいいいよねって思う
Babel の導入
基本はこれ
npm i -D @babel/core @babel/cli @babel/preset-env
Babel の設定
.babelrc
を作ってその中に JSON 書いていく
こんな感じ
{ "presets": [ [ "@babel/preset-env", { "targets": { "edge": "17", "ie": "11", "safari": "11.1" }, "useBuiltIns": "usage", "corejs": 3 } ] ]
}
Babel の機能について
コンポーネント
@babel/cli
Babel の CLI、これがないと始まらない
@babel/core
Babel 本体、CLI がよしなにしてくれる
@babel/preset-env
構文の変換や Polyfill を設定できる
@babel/preset-typescript
TS をトランスパイルしてくれる
Babel と Browserlist
Babel は Browserlist の設定を認識して自動で Polyfill を挿入してくれます
なお、Babel 7.4.0 以前では設定方法が異なる可能性があります
サンプルコード
IE11 をターゲットにした設定のサンプルです
以下のコマンドを流せば Polyfill された JS が出ることを確認できますnpx babel src -d dest --extensions ".ts"
.babelrc
{ "presets": [ ["@babel/preset-env", { "corejs": 3, "useBuiltIns": "usage" }], ["@babel/preset-typescript"] ]
}
.browserlist
ie 11
Babel と tsc でトランスパイルしてみる
割と違うコードが出てきます
元のソース
const sp = new URLSearchParams('?aaa=bbb&ccc');
console.log(sp);
const prm = new Promise((res) => res(true));
console.log(prm);
[...Array(10)].forEach((_, i) => console.log(i));
console.log(globalThis.Date());
export {};
Babel
.babelrc
{ "presets": [["@babel/preset-env"], ["@babel/preset-typescript"]]
}
ビルド結果
"use strict";
Object.defineProperty(exports, "__esModule", { value: true,
});
function _toConsumableArray(arr) { return ( _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread() );
}
function _nonIterableSpread() { throw new TypeError( "Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." );
}
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _iterableToArray(iter) { if ( (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null) || iter["@@iterator"] != null ) return Array.from(iter);
}
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2;
}
var sp = new URLSearchParams("?aaa=bbb&ccc");
console.log(sp);
var prm = new Promise(function (res) { return res(true);
});
console.log(prm);
_toConsumableArray(Array(10)).forEach(function (_, i) { return console.log(i);
});
console.log(globalThis.Date());
tsc
tsconfig.json
{ "compilerOptions": { "target": "es5", "module": "commonjs", "allowJs": true, "checkJs": true, "sourceMap": true, "outDir": "./dist", "strict": true, "noImplicitAny": true, "moduleResolution": "node", "isolatedModules": true, "baseUrl": ".", "allowSyntheticDefaultImports": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true }, "include": ["src/**/*"]
}
ビルド結果
"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to;
};
Object.defineProperty(exports, "__esModule", { value: true });
var sp = new URLSearchParams('?aaa=bbb&ccc');
console.log(sp);
var prm = new Promise(function (res) { return res(true); });
console.log(prm);
__spreadArray([], Array(10)).forEach(function (_, i) { return console.log(i); });
console.log(globalThis.Date());
//# sourceMappingURL=index.js.map
結論
tsc で問題ない
tsc の方が綺麗なコードが出てきてるので、Polyfill 要らなければ tsc で問題ないです
因みに ES6+を ES5 にするのもできるので JS のトランスパイルにも使えます
core-js を使うなら Babel
ちょいちょい触ってて Babel の利点は core-js
があれば .browserlist
を使えるので、そこでターゲットを指定してやれば Polyfill を勝手に差し込んでくれるところですね
但し CRA では Babel に対する .browserlist はほぼ無価値
あとは Create React App はビルドに Babel を採用しているので、FW 側でビルドパイプラインがあるときには採用したほうが楽です
(態々書き換える意味もないので)
ただ react-scripts 4.0.3
には core-js
が入っていないので、基本的に .browserlist
を書いたところで Polyfill は入らないため、あんまり存在感はないです