Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webpack no longer supports define correctly #5316

Closed
davidschwegler opened this issue Jul 18, 2017 · 16 comments
Closed

Webpack no longer supports define correctly #5316

davidschwegler opened this issue Jul 18, 2017 · 16 comments

Comments

@davidschwegler
Copy link

Do 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.

  1. 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",
       ...
    });
});)
  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.

@davidschwegler davidschwegler changed the title Webpack no longer appears to support define correctly Webpack no longer supports define correctly Jul 18, 2017
@sokra
Copy link
Member

sokra commented Jul 19, 2017

yep this is a problem...

@alexander-akait
Copy link
Member

/cc @davidschwegler problem still exists in webpack@4?

@sverweij
Copy link

Hi @evilebottnawi I've retried today using webpack 4.8.3 and can confirm the issue with requirejs/ amdefine still exists.

@sverweij
Copy link

@evilebottnawi Looking through the issue it looks like a minimal reproduction example is lacking. Would it be helpful if I provided one?

@hayesmaker
Copy link

*rips out webpack and switches to browserify

@alexander-akait
Copy link
Member

/cc @ooflorent

@ooflorent ooflorent self-assigned this Jun 8, 2018
@ooflorent
Copy link
Member

@sverweij Absolutely. Any simple repro would be appreciated.

@ooflorent
Copy link
Member

ooflorent commented Jun 8, 2018

I've found the issue. Problem is that define is redefined and shadows global.define. If you replace remove var 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 shadows global.define which breaks the build.

@alexander-akait
Copy link
Member

@ooflorent some old libraries can contain this code, it is not always possible to remove it

@ooflorent
Copy link
Member

@evilebottnawi I understand but this is not a webpack bug. webpack fixed a bug that broke existing libraries because they were doing broken things.

@ooflorent
Copy link
Member

ooflorent commented Jun 8, 2018

A fix would be to ignore the redefinition of define but that would break code that requires define to be shadowed.

@alexander-akait
Copy link
Member

alexander-akait commented Jun 8, 2018

@ooflorent looks like we can close issue here, but @sokra add bug labels, maybe he have idea how solve this without break code

@sverweij
Copy link

sverweij commented Jun 8, 2018

If this cannot be solved without breaking (t.b.c.) it might be useful to document any known workarounds for anyone bumping into this (I can help).

@ooflorent seeing you found the root cause: still interested in a simple repro?

@ooflorent
Copy link
Member

ooflorent commented Jun 8, 2018

@sverweij no, thank you. I was able to create a repro to analyze what was going on 👍

@webpack-bot
Copy link
Contributor

This issue had no activity for at least half a year.

It's subject to automatic issue closing if there is no activity in the next 15 days.

@webpack-bot
Copy link
Contributor

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

janpaul123 pushed a commit to cruise-automation/webviz that referenced this issue Jan 9, 2020
We already proved that compressjs works as a bz2 decoder in the rosbag.js tests: https://github.com/cruise-automation/rosbag.js/blob/68526faa242bb76943b6e42fa452f1eadb6cbc73/src/bag.test.js#L175-L178 But it wasn't imported in webviz, so bz2-compressed bags (such as the ones at https://vision.in.tum.de/data/datasets/rgbd-dataset/download#freiburg3_cabinet) didn't work by default.

It was almost very straightforward to add, except that a webpack/AMD module issue (webpack/webpack#5316) prevents us from actually using compressjs in our webpack build. I worked around it by using a string-replace-loader to just remove the offending line. It's a pretty horrible hack, but it works...let me know if you have any better suggestions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants