状況
iOS 9 や IE などの ES6 未対応のブラウザで、const
や Arrow function といった ES6 の構文が解釈できずに JavaScript が動作しない問題が発生した。
具体的には、あるプロジェクトで re-bulma を使っていて、このパッケージを import していると、ES6 未対応ブラウザで以下のように ES6 の構文が解釈できず、エラーを吐かれる。
[Error] SyntaxError: Unexpected keyword 'const'. Const declarations are not supported in strict mode.
今回のプロジェクトでは、webpack の設定で Babel に node_modules
下のディレクトリは対象外 (exclude) とするようにしているため、例えば依存パッケージが ES6+ で書かれていても、ES5 向けにはトランスパイルしない。
その ES6+ で書かれた依存パッケージだけ exclude しない (トランスパイル対象とする) という解決策がひとつあるが、理想的ではない。
原因
re-bulma の package.json
は、エントリーポイントを指定している部分を抜粋すると、以下のようになっている。
{
...
"main": "lib/index.js",
"module": "lib-es/index.js"
...
}
lib-es/index.js
は ES6 向け、lib/index.js
は ES5 向けにトランスパイルされてビルドされたものになっている。
ここで、webpack が依存解決時に lib/index.js
ではなく lib-es/index.js
を参照していることが原因であった。
解決法
webpack では、依存パッケージを解決するとき、resolve.mainFields
の値を参照する。
このデフォルト値は ["browser", "module", "main"]
となっているため1、ES5 をサポートしたい場合、module
フィールドの優先度を main
フィールドよりも下げる必要がある2。
今回は以下のように設定した。
const config = {
// ...
resolve: {
extensions: ['.js', '.jsx'],
modules: [
pathLib.resolve(__dirname, './app'),
pathLib.resolve(__dirname, './node_modules'),
],
mainFields: ['browser', 'main'],
},
// ...
}
module.exports = config
参考
-
https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js#L93-L98 ↩
-
今回の場合は
main
フィールドが ES5 向けだったため優先度を上げたが、そうでない場合は優先度を変える必要がある。 ↩