21

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' }
fabiomcosta
  • 1,105
  • 1
  • 8
  • 10

3 Answers3

25

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.

Michael Jungo
  • 31,583
  • 3
  • 91
  • 84
  • This seems to be where the problem is. I'll have to do more changes to make everything work but at least this gives me a path forward with optimized modules. Thank you very much! – fabiomcosta Jul 29 '17 at 01:42
  • 7
    I've done this and still get the bailout. I wonder if it's how my modules are structured. – Scott L Aug 01 '17 at 22:54
  • @ScottLeonard did you add the option to your `webpack.config.js` or to your `.babelrc`? I found that it only works in the Webpack config. – Atav32 Jan 23 '18 at 22:47
  • When I try to add that to `webpack.config.js` I get `Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema. - configuration has an unknown property 'presets'`. webpack version 4.44.2 – Mikko Rantalainen Oct 02 '20 at 07:43
  • 1
    'presets' must be inside of the 'options' for the webpack babel loader – bikeman868 Oct 05 '20 at 22:46
9

For those who use modern @babel/preset-env:

{
  "presets": [
    ["@babel/preset-env",{
      "targets": {
        ...
      },
      "modules": false
    }],
    "@babel/preset-react"
  ],
  "plugins": [...
}

But bad things (but not critical) that after that I can't use ES modules in my webpack config files as before, so in webpack.config.babel.js:

import webpack from 'webpack';

should be changed to:

const webpack = require('webpack');
Rahiel Kasim
  • 370
  • 3
  • 8
basil
  • 3,482
  • 2
  • 22
  • 20
  • 2
    Sadly this does not work for me. The error I get is: ``` Entrypoint mini-css-extract-plugin = * chunk {0} * (mini-css-extract-plugin) 497 KiB [entry] [rendered] > !!/Us.....gin [0] ./node_modules/css-loader/dist/cjs.js??ref--6-1!./node_modules/postcss-loader/src??postcss!./node_modules/sass-loader/lib/loader.js??ref--6-3!./source/scss/main.scss 495 KiB {0} [depth 0] [built] ModuleConcatenation bailout: Module is not an ECMAScript module single entry !!/Use...ce/scss/main.scss mini-css-extract-plugin ``` – muuvmuuv Feb 26 '19 at 15:44
0

I just recently faced a very similar issue with Ionic and Angular. I had imported a custom component into app.module.ts and then inserted it into entryComponents, later decided I wanted to go a different route. I removed the import and forgot the entryComponents entry. And I had the same error.

ModuleConcatenation bailout: Module is not an ECMAScript module

Then it pointed to my variable.scss path, followed by the following line

ERROR in Cannot read property 'members' of undefined

So to anyone with a similar issue (most probably using Ionic and or Angular), you might have to make sure you are not trying to use a component in a page where it's not actually imported, but still has a trailing point in the page.module.ts entryComponents.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Wylie
  • 350
  • 3
  • 12