Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix modules with "ModuleConcatenation bailout: Module is not an ECMAScript module" bailout message?

Tags:

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' }
like image 324
fabiomcosta Avatar asked Jul 29 '17 00:07

fabiomcosta


2 Answers

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.

like image 182
Michael Jungo Avatar answered Sep 17 '22 14:09

Michael Jungo


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');
like image 20
basil Avatar answered Sep 18 '22 14:09

basil