Webpack no longer supports define correctly
See original GitHub issueDo you want to request a feature or report a bug? Bug
What is the current behavior? Webpack no longer appears to support define correctly.
If the current behavior is a bug, please provide the steps to reproduce. We upgraded from webpack 2.2.1 to 2.6.1. In 2.2.1 everything works, but in 2.6.1 it doesn’t.
- Include the
compressjs
module, which uses define like so (see https://github.com/cscott/compressjs/blob/master/main.js)
if (typeof define !== 'function') { var define = require('amdefine')(module); }
define([...], function(...) {
'use strict';
return freeze({
version: "0.0.1",
...
});
});)
- At runtime, you will get an error saying
Uncaught Error: define cannot be used indirect
at e.exports (vendor.ac2023d….js:sourcemap:1)
at Object.<anonymous> (vendor.ac2023d….js:sourcemap:1)
at Object.<anonymous> (vendor.ac2023d….js:sourcemap:1)
at n (commons.1a4acdd….js:sourcemap:1)
at Object.<anonymous> (logos.42ff4f3….js:sourcemap:1)
at Object.<anonymous> (logos.42ff4f3….js:sourcemap:1)
at n (commons.1a4acdd….js:sourcemap:1)
at Object.<anonymous> (logos.42ff4f3….js:sourcemap:1)
at n (commons.1a4acdd….js:sourcemap:1)
at Object.<anonymous> (logos.42ff4f3….js:sourcemap:1)
Attempted workarounds I have tried excluding the module from webpack via noParse (though the docs say not to exclude anything that uses define or require):
module: {
noParse: /(compressjs)/
At runtime, this results in a different error:
main.js:1 Uncaught ReferenceError: require is not defined
at Object.module.exports (main.js:1)
at __webpack_require__ (bootstrap 596e1b2…:54)
at Object.<anonymous> (expander.tsx:61)
at Object.<anonymous> (util.js:57)
at __webpack_require__ (bootstrap 596e1b2…:54)
at Object.<anonymous> (errors.ts:21)
at __webpack_require__ (bootstrap 596e1b2…:54)
at Object.<anonymous> (shortcut-icon.jsx:16)
at __webpack_require__ (bootstrap 596e1b2…:54)
at Object.__webpack_exports__.LogoTabIcon (auth-policy.tenant.client.js:9)
I have tried additionally adding an alias:
resolve: {
alias: {
compressjs: path.join(projectRoot, 'node_modules/compressjs/main.js')
Offending webpack code
It appears the webpack code in Parser.js no longer returns a value for the define expression. In 2.2.1, parser returned a BasicEvaluatedExpression, but as of 2.6.1 it returns nothing, because the “define” definition has been pushed onto the scope for some reason. this.scope.definitions
contains ‘define’ now, whereas it was previously empty.
this.plugin("evaluate Identifier", function(expr) {
const name = this.scope.renames["$" + expr.name] || expr.name;
if(this.scope.definitions.indexOf(expr.name) === -1) { // <-- HERE
const result = this.applyPluginsBailResult1("evaluate Identifier " + name, expr);
if(result) return result;
return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range);
} else {
return this.applyPluginsBailResult1("evaluate defined Identifier " + name, expr);
}
});
I’m guessing this is due to the prewalking that was introduced starting in 2.4.0 here.
What is the expected behavior? Modules such as this runs without errors.
If this is a feature request, what is motivation or use case for changing the behavior?
Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System. Testing using the latest Chrome version.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:4
- Comments:16 (12 by maintainers)
*rips out webpack and switches to browserify
I’ve found the issue. Problem is that
define
is redefined and shadowsglobal.define
. If you replace removevar
in the source, then it works as expected. I’m not sure webpack can do anything about this.tl;dr:
var define
is hoisted and shadowsglobal.define
which breaks the build.