webpack: 2.2.0-rc.4's es6 modules' "module" usage detection seems to be broken

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

External modules (symbol-observable, moment) no longer compile with this release.

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

  1. Use webpack 2.2.0-rc.4
  2. Compile a script that requires moment or symbol-observable (or another module that triggers this problem)

What is the expected behavior?

Bundle compiles fine


It doesn’t appear that moment and symbol-observable modules actually use module.exports at the locations Webpack says there is an error.

For example, symbol-observable/es/index.js:

/* global window */
import ponyfill from './ponyfill';

var root;

if (typeof self !== 'undefined') {
  root = self;
} else if (typeof window !== 'undefined') {
  root = window;
} else if (typeof global !== 'undefined') {
  root = global;
} else if (typeof module !== 'undefined') {
  root = module;
} else {
  root = Function('return this')();
}

var result = ponyfill(root);
export default result;

Gives the error:

./~/symbol-observable/es/index.js
13:9-15 module is not allowed in EcmaScript module: This module was detected as EcmaScript module (import or export syntax was used). In such a module using 'module' is not allowed.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 34
  • Comments: 74 (34 by maintainers)

Commits related to this issue

Most upvoted comments

Thanks for all the feedback. I removed the error message and exports/define is now undefined in ESM. module.exports is read-only and undefined in ESM. I release another RC tomorrow to let you try this version.

@todd-richmond was this fixed for you?

I found this to be the culprit for babel-loader:

plugins: [ 'add-module-exports' ]

Thanks for the reports, fix is in CI, feel free to test against the commit (if you are really anxious for it 😄 ) while it’s being reviewed.

We are working on that as we speak!! Thank you for all the reports!

Adding to symbol-observable, it looks like lodash-es falls into this same bug.

import root from './_root.js';

/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

now I get the following error Uncaught ReferenceError: exports is not defined using Typescript

{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    ...
}

redux and redux-form both use lodash-es, which means they produce this same bug

FWIW lodash-es does work in the latest Safari Technical Preview, which supports type=module.

Tested @TheLarkInn’s commit, and it perfectly resolves the problem. Thanks a lot!

Before applying #3971: (“exports is not defined” error) Before

After applying #3971: (Works perfectly) After

RE:me

If possible, it would be better to detect assigning to the free variables in question:

Ah, that might still falsely trigger it for UMD juggling which is safe. Maybe instead of a hard error treat it as a warning? Or get fancy and only throw the warning if the exports or module.exports assignments are done outside of an if block.

selection_052

I’ll try to provide a repro

All good for me (fixes the redux-form issue)

EDIT: Scratch that. I’m now getting exports is not defined as well. I am not using typescript as the user above is.

Checking for the existence of a variable should not trigger the warning. It’s valid JavaScript regardless of context. If possible, it would be better to detect assigning to the free variables in question:

exports.foo = 1;
// or
module.exports = {};

@Stenvdb Didn’t want to keep polluting this issue; see my PR at https://github.com/Stenvdb/redux-test/pull/1. ✨

I tried webpack@2.2.0-rc.7 last night with typescript@2.2.0-dev.20170117 and all was well. Issue seems to be resolved for me.

@TheLarkInn: I tried the https://github.com/webpack/webpack/pull/3971 fix, and now get the runtime error: Uncaught TypeError: Cannot set property exports of #<Object> which has only a getter

As I assume that is the expected error, couldn’t a more helpful error message be displayed? I’m thinking something like: module.exports is readonly when using ES2015 modules. Do not mix import with module.exports.

I can confirm that the example given by @niieani above (Aurelia loader detecting NodeJS) is fixed by rc5.

@TheLarkInn if Webpack only ignores the typeof module construct, will the following code behave properly?:

if (typeof module !== 'undefined' && typeof module.require !== 'undefined') {
    var m = module.require('aurelia-loader-nodejs');
    // ...
}

Above, we are explicitly checking that both typeof module and typeof module.require are defined (i.e. this module is being run under NodeJS or Electron), and only then using module.require to load a module. Webpack should allow for usages of module as long as they are wrapped in code that will be stripped out.

Otherwise platform detection features like the one above will not work with Webpack, and this will be a regression. 😦

recent react-redux 5.0.2 update from 5.0.1 causes this exact lodash-es error to happen for me and the only fix was to hard-code the previous version. The new version included a large set of dependency updates so not sure which initiates the problem

… update. Our build server that does not cache anything failed with 5.0.1 and it seems like backing out to 5.0.1 is random. I cleared every cache a second and it now fails the same way so the work-around is not consistent