Webpack3 comes with the ModuleConcatenation
plugin that when used with the --display-optimization-bailout
flag will give you the reason for bailout.
The bailout messages not that easy to understand, and it's hard to understand why they happened to a specific module.
Here is my output for the webpack
command on a very simplified version of my project:
> webpack --bail --display-optimization-bailout
Hash: 4a9a55dc2883e82a017e
Version: webpack 3.4.1
Child client:
Hash: 4a9a55dc2883e82a017e
Time: 594ms
Asset Size Chunks Chunk Names
a.d3ade61d21d5cb8dd426.bundle.js 712 bytes 0 [emitted] a
a.d3ade61d21d5cb8dd426.bundle.js.map 6.57 kB 0 [emitted] a
manifest.json 102 bytes [emitted]
index.html 299 kB [emitted] [big]
[0] multi ./src/client/bootstrap/ErrorTrap.js 28 bytes {0} [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
[1] ./src/client/bootstrap/ErrorTrap.js 199 bytes {0} [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
I simplified the contents of ./src/client/bootstrap/ErrorTrap.js
as much as I could, and I still get the ModuleConcatenation bailout: Module is not an ECMAScript module
. Here are its contents:
class ErrorTrap {
}
export default ErrorTrap;
I looked into understanding this bailout message, and one of the reasons it happens is when the module doesn't have imports or exports, as seen at https://github.com/webpack/webpack/blob/93ac8e9c3699bf704068eaccaceec57b3dd45a14/lib/dependencies/HarmonyDetectionParserPlugin.js#L12-L14, but I don't know why it's not considering this module a ECMAScript
module.
.babelrc
{
"presets": [
"es2015"
]
}
webpack.config.js representation:
{ target: 'web',
devtool: 'source-map',
entry: { a: [ './src/client/bootstrap/ErrorTrap.js' ] },
output:
{ path: '/project/build/client/assets',
filename: '[name].[chunkhash].bundle.js',
chunkFilename: '[name].[chunkhash].chunk.js',
publicPath: '/assets/' },
module: { rules: [ [Object], [Object], [Object], [Object], [Object] ] },
resolve: { alias: { 'lodash.defaults': 'lodash' } },
plugins:
[ ModuleConcatenationPlugin { options: {} },
CommonsChunkPlugin {
chunkNames: [Object],
filenameTemplate: undefined,
minChunks: Infinity,
selectedChunks: undefined,
children: undefined,
async: undefined,
minSize: undefined,
ident: '/project/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js0' },
ManifestPlugin { opts: [Object] },
ChunkManifestPlugin {
manifestFilename: 'chunk-manifest.json',
manifestVariable: 'webpackManifest',
inlineManifest: false },
OccurrenceOrderPlugin { preferEntry: undefined },
DefinePlugin { definitions: [Object] },
VisualizerPlugin { opts: [Object] },
ExtractTextPlugin { filename: '[name].[contenthash].css', id: 1, options: {} },
UglifyJsPlugin { options: [Object] },
LoaderOptionsPlugin { options: [Object] } ],
name: 'client' }
You're using Babel to transpile your JavaScript files and by default the es2015
preset transforms ES modules (import
/export
) to CommonJS (what Node uses, require
). Webpack receives the CommonJS modules, but the ModuleConcatenationPlugin
relies on ES modules. You can configure Babel to not transform the modules with the modules
option.
{
"presets": [
["es2015", { "modules": false }]
]
}
Webpack 2+ supports ES modules out of the box and it's best to leave them to webpack, because it enables features such as Tree Shaking.