created: 2020-01-23T08:46:27.000Z

browserifyからwebpackに移行するときのエラー

browserifyのcommonjsと、webpackのcommonjsの違いにハマったときの話

経緯

browserifyからwebpackに移行するときに、ある古いライブラリが読み込み時エラーとなってしまった その古いライブラリはモジュール解決のロジックを以下のように行なっていた

	if ( typeof define === 'function' && define.amd ) {
		// AMD
		define( ['jquery'], function ( $ ) {
			return factory( $, window, document );
		} );
	}
	else if ( typeof exports === 'object' ) {
		// CommonJS
		module.exports = function (root, $) {

browserifyでモジュール解決をしていたときは名前空間に define がなかったため無事にcommonjsとしてモジュールを読み込めていたが、webpackでビルドすると名前空間に define が存在し、分岐の結果AMDとしてモジュールを読み込もうとしているようだった

これまでbrowserify(commonjs)でビルドしていたので、このファイルのみAMDで読み込むことになりエラーになった

commonjsとAMD

両方ともjsでモジュールを読み込むための仕様

commonjsはnodejsで使われており、AMDはブラウザ側で使うために作られた (クライアント側が通信してjsファイルを取ってくるといったことをする)

datatable.netはcommonjsとAMDを背反なものとして分岐させているが、実際にはcommonjsとAMDを同時に動作させるといったことも行われているようだ

参照

commonjsのwikiにAMDの仕様がPROPOSALであがっていたり

commonjsのwikiにメーリングリストにAMDを別口に分けようとするスレッドがあったりする

もともとこの辺りのスニペットをコピペしたライブラリなのかもしれない

解決方法

説明から遠回りしたが、今回の問題はつまるところ次の点に尽きる

  • browserifyのcommonjsではAMDが有効になっていないが
  • webpackのcommonjsではAMDが有効になっている
    • コンパイル時のグローバル名前空間に define 関数が存在している

なのでwebpackの設定でAMDを無効にした

module.exports = {
  module: {
    rules: [
      {
        parser: {
          amd: false, // disable AMD
        }
      }
    ]
  }
}

この設定でbrowserifyでビルドできていたときと同じ動作にすることができた

Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考
[ad] Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考
Tom Long, 秋勇紀 (単行本(ソフトカバー))