Can’t name a variable “module” when devtool is “source-map”

Bug report

What is the current behavior?
Having a variable/const declaration with name “module” in an ES6 module causes a runtime error because of a conflicting webpack helper variable.

If the current behavior is a bug, please provide the steps to reproduce.

Here’s a repo with an easy to reproduce setup: https://github.com/noppa/webpack-module-var-name-issue. It also contains an example that uses Babel to first transpile the same ES6 module to a CommonJS syntax for comparison.

The gist of it is that the following module and config:

// index.js
const module = 'Hello World'
console.log(module)

// webpack.config.js
module.exports = {
    devtool: 'source-map',
    target: 'web',
    entry: path.join(__dirname, 'index.js'),
    output: {
      filename: '[name].bundle.js',
      path: __dirname
    },
    mode: 'development'
}

gets compiled to something like this (parts of the output boilerplate omitted):

/***/ (function(module, exports) {

const module = 'Hello World'
console.log(module)

/***/ })

which causes a runtime exeption SyntaxError: Identifier 'module' has already been declared. This doesn’t happen when devtool is one of the eval-based options.

What is the expected behavior?
Compiling the example and running it in the browser (or Node) should print “Hello World” without errors.
The use of a variable name “module” isn’t restricted when using ES6 modules natively in the browser.

The example in the repo can also be tested with native ES6 modules in Chrome without any compilation or with Babel compilation from ES6 modules to CommonJS before giving it to webpack. Both of these examples work as expected. This is actually how we run into this issue: we used to compile the modules to CommonJS with Babel, but disabled it because we wanted to experiment with some of the webpack’s ES6-modules only -features like tree shaking. Babel renames the local variable to _module. Adding an IIFE around the user-defined code or renaming/obfuscating the module argument that webpack uses could also work.

Other relevant information:
webpack version: 4.8.3, although the same thing seems to happen with versions 2 and 3, too
Node.js version: 9.11.1
Operating System: Arch Linux
Additional tools: The Babel-example in the demo repo uses transform-es2015-modules-commonjs Babel plugin to do the ES6 –> CommonJS transpilation and variable renaming.

Author: Fantashit

3 thoughts on “Can’t name a variable “module” when devtool is “source-map”

  1. @sokra I don’t quite follow why this is correct behaviour.

    Webpack supports a few different targets, one of which is web, described as Compile for usage in a browser-like environment (default).

    In the example above the target is set to web. But even if it wasn’t, it would default to web anyway.

    In the browser, the provided code is valid. I tried it in the Chrome devtools:

    image

    I don’t understand why it is correct that the web target should be subject to the limitations of node.js (which I assume is the node target). This looks like a bug to me.

  2. What makes this particularily difficult to deal with is that top level variable module is allowed when devtool is some of the eval-based options, so things will work in development but break on production (at runtime, not at compile time).

    I ended up making a simple Babel plugin that changes those problematic top-level variables to something else. We are using that as a workaround, because just avoiding “module” as a variable name and trusting that everyone remembers to avoid it doesn’t sound very good idea in the long term.

  3. I’ve just hit the same issue with latest Webpack in the exactly analogous scenario as what @filipesilva mentioned above – configuring a TS modern build for using with a differential loading approach.

    I don’t understand why the issue is closed. Webpack bundles correctly written modules in a way that breaks them; quite an obvious bug in Webpack, not in user code.

Comments are closed.