前提
- babel6以降
- babel-plugin-transform-runtime をつかってポリフィルしている
- webpack2以降
自分がこういう構成なので…ほかにもなにか条件下あるかもしれない
エラー内容
Cannot assign to read only property ‘exports’ of object ‘#<Object>’
webpackのコンパイルはちゃんと通って、ファイルも生成される。されるのだけど、そのJSファイルをブラウザで実行するとうまく動かなくて、Chromeのdevツールとかでコンソールエラーを見ると上記のようなエラーメッセージが出ている。
状況下
babel module(策定されたESMっぽいけどESMではないbabel独自のimport/export構文)を使ってモジュールを用いている状況下で、CJS(CommonJS)形式のexports構文を使うと、いわゆるmixed moduleな状態ということになって解釈できなくなるっぽい。
// foo.js const sample = (num = 1) => { const a = 1 return a + num } module.exports = sample // script.js import foo from 'foo' foo()
みたいな状況。
この記事はちょっと思い出しながら書いているので、上記サンプルコードではPromiseオブジェクトを返すような関数ではないけど、もしかするとこの記事のエラーは『Promiseオブジェクトを返すモジュール』のときだけ起こるのだったかもしれない。ちょっと記憶が曖昧。
解決方法
ともあれこのエラーの解決方法としては
- CJS形式のモジュールを使わない(export構文でモジュール化する)
- transform-es2015-modules-commonjs プラグインを使う
どちらかがある。
こいつを使うと、どうやらすべてをCJS形式にして解釈するような挙動になる?みたいで、うまくいく。
ただtransform-es2015-modules-commonjsを使うとESM形式もCJS形式に変換されるっぽいのでwebpackのtree-shakingが効かなくなる。一長一短かもしれない。tree-shakingにはESM形式である必要がある。
issue情報
実は今件、webpackのリポジトリにissueが上がっている。webpack2からmodule.exports
はRead-onlyプロパティになったらしく、それが原因っぽい。がメインコントリビューターの人がバッサリ「import
とmodule.exports
の混在はNG」と言ってるのでそういうものかもしれない。
結局のところ
今件はこういうことかもしれない.
以下は想像で書いている&過去にメモ書きしたやつなので解釈が大きく間違っているかもしれない…が一応書いておく。
webpackでTree-shakingするようにconfigを書いている
- Tree-shakingのためにbabelrcに
module: false
記述している- import/export構文がbebelでトランスパイル対象にされない
- babelが解釈しなくてもwebpack2はimport/exportの解釈が可能になっているので
module: false
してるとモジュール解釈はwebpackが行う- でもwebpackで
import
とmodule.exports
が混在しているプロジェクトはそもそも取り扱えないrequire/module.exports
かimport/require/export
かimport/export
のどれかの組み合わせのファイルに変換しないと解釈できない
- でもwebpackで
module.exports
するオブジェクトでpromise使ってるとtransform-runtimeの対象外になってしまうtransform-es2015-modules-commonjs
を使うと importを全部require形式に変換してCJSの世界 にしてくれる- 全てがなんとかなり解釈できるようになる = しかしESM構文(import/export構文)じゃないのでTree-shakingが効かなくなる
なんていうか疲れますね。
babel moduleの世界にCJS moduleを突っ込もうとしているのがそもそも悪いのかもしれない、という気持ちがある。
ESM策定されたのでCommonJSはCommonJS形式で持つ、babel moduleは捨てて来たる.mjs
に備えるというときが将来来そうなのだけど、こんなに疲れるのは困る、嫌すぎる。その頃にはwebpackもbabelもそもそもないかもしれないけど、それにしても既に現状のこれら構成が負債になりつつある気がする。
こちらからは以上です。