【概要】

Babelの設定。簡単と見せかけてTSとJSで挙動が違った。あれこれ調べたが、最終的な設定はこれだけでよい。

トランスパイル

JSもTSもwebpackのbabel-loaderで行う。

// webpack.common.jsmodule.exports = ({ outputFile, assetFile, envFilePath, assetPath }) => {
return {
... module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
use: 'eslint-loader',
exclude: /node_modules/,
},
{
test: /\.js$/,
// transpile
use: 'babel-loader',
exclude: /node_modules/,
},
...

babel-loaderを実行する前にeslint-loaderで構文チェックを行なっている。これはローカル開発環境でもビルド環境でも共通。pre-commitやpre-pushで構文チェックを行う設定はしていないので、ローカル開発で発生していたlintエラーに気がつかずに自動ビルドでこけることが予想出来るが、それでいいと思う。

browserslistで対応するブラウザを指定する

babelで対応ブラウザを指定することもできるが、browserslistに選定を一任することで、autoprefixerと合わせて対応ブラウザを決められる。シェア何%以上や、最新何バージョンなどの対応も出来るのでこれを使う。

// .browserslistrc# 対応するブラウザを指定する。bable(JSの構文変換), postcssでautoprefixer(cssの構文変換)で読み込まれている。
# 通常はdefaults。詳しくはhttps://github.com/browserslist/browserslist#best-practices
defaults# defaults以外を指定したい場合はこちらを参照。cover99.5%でダメなら多分コードを変えないとダメ。 https://github.com/browserslist/browserslist#full-list
# cover 99.5%

to C向けの案件あまりやらないのでそこまで気にすることはないが、パフォーマンスよりもとりあえず動くことが大事なので、お任せするに越したことはないという考え。

ほとんどのuserはdefaultsでいいでしょう。とされているので素直に従う。defaultsは > 0.5%, last 2 versions, Firefox ESR, not dead とのこと。

babelの設定

インストールしたモジュールは、

  • @babel/core バベル本体的な存在と思われる
  • @babel/preset-env こちらも必須とと思われる。babelの設定をまるっと行なってくれる。

の2つに加えて、
TSでは

JSでは

  • core-js バージョン3を使用。特定の構文変換で使用。

@babel/cli はいらないと思ったので入れなかった。

.babelrc の設定

browserslistとの連携はtargetsなどを個別に指定しなければ babel/preset-env が暗黙的に行なってくれる。 なのでここでは指定しない。

TSの場合はこれだけ。async/awaitで書いたコードが正常に動作する。

// .babelrc{
"presets": ["@babel/preset-typescript"]
}

JSの場合は corejs が必要。これがないと動かなかった。

{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": { "version": 3, "proposals": false }
}
]
]
}
  • useBuiltIns これがpolyfillをどう扱うかの設定。async/awaitの変換にはcore-jsが必要だった。
    version7.4からは@babel/polyfill を使わないことが推奨されているので注意。両方入れるとバグるらしい
    usage はそれぞれのファイルでポリフィルが使われる時に特定のポリフィルを使用する。jsのコードでインポートする必要はない。
    entry と指定する場合は、使用するファイルで core-js をインポートする必要がある。今回はとにかくコードだけを書けば実装を進められるのがコンセプトなので、迷わず usage を選択。

TSで使用している @babel/preset-typescript ではcore-jsについて何も明記されていないし、@babel/preset-typescript が包括している@babel/plugin-transform-typescript にも書いていないのでよくわからなかった。

【追記】

optional chainingを利用するためにはtype-scriptでもcore-jsが必要だった。

// .babelrc{
"presets": [
[
"
@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": { "version": 3, "proposals": false }
}
],

"@babel/preset-typescript"
]
}
document.addEventListener('DOMContentLoaded', () => {
const testGetButton = document.getElementById('testGet');
testGetButton?.addEventListener('click', async () => {
try {
const { data } = await commonApi.get(endPoints.testArray);
alert(JSON.stringify(data));
} catch (error) {
console.error(error);
}
});
...

TSの注意事項

@babel/plugin-transform-typescript に ある注意事項をいくつかピックアップする。

  • const enumはサポートしていないので、使う場合はbabel-plugin-const-enumが必要。
  • export =import = はES nextにコンパイル出来ないのでサポートしていない。
  • tsconfig.jsonの変更はバベルに反映されない。ビルドプロセスではisolatedModules がオンになるが、対処はできる。
  • export let, var はサポートしていない。

などなど書いてあった。

まとめ

  • browserslistで対応ブラウザを指定
  • babelの設定箇所ではブラウザを指定しない。(browserslistの設定を読みにいかなくなる。)
  • @babel/polyfill は古いので、今は使わない。core-jsを使う。
  • TypeScriptを使う時は注意が必要な箇所もある。

【感想】

babel polyfillは今は推奨されていない。とよく読むと書いてあるが、公式ドキュメントの中でpolyfillがサイドバーメニューにあったりでわかりにい部分があった。こちらもググって古い情報を見つけてしまうとややこしくなるので、時間をかけてドキュメントを読めてよかった。

--

--

Tatsuya Asami
Tatsuya Asami

Written by Tatsuya Asami

Front end engineer. React, TypeScript, Three.js

No responses yet