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

Bug: webpack's UMD global detection is incompatible with strict mode JavaScript #5843

Closed
cdata opened this issue Oct 17, 2017 · 1 comment
Closed

Comments

@cdata
Copy link
Contributor

cdata commented Oct 17, 2017

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

This is a bug.

What is the current behavior?
Please consider the following contrived webpack config:

module.exports = {
  entry: './my-lib.js',
  output: {
    filename: './my-bundle.js',
    libraryTarget: 'umd'
  }
};

When webpack creates my-bundle.js, it wraps the contents of my-lib.js in a UMD template. The template used by webpack is out of date, and uses an obsolete technique to detect the global object.

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

  1. Clone the example project at https://github.com/cdata/webpack-example.
  2. npm install
  3. webpack
  4. Review the contents of the generated my-bundle.js artifact

The current technique for global object detection in use by webpack is visible on line 10 of my-bundle.js:

/*  1 */ (function webpackUniversalModuleDefinition(root, factory) {
/*  2 */         if(typeof exports === 'object' && typeof module === 'object')
/*  3 */                 module.exports = factory();
/*  4 */         else if(typeof define === 'function' && define.amd)
/*  5 */                 define([], factory);
/*  6 */         else {
/*  7 */                 var a = factory();
/*  8 */                 for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
/*  9 */         }
/* 10 */ })(this, function() {
//          ^--- obsolete global object detection

What is the expected behavior?

The UMD template used to wrap my-lib.js should use the global object detection technique used in the most up-to-date UMD reference templates. For example, the webpack UMD wrapper around my-bundle.js should look like:

/*  1 */ (function webpackUniversalModuleDefinition(root, factory) {
/*  2 */         if(typeof exports === 'object' && typeof module === 'object')
/*  3 */                 module.exports = factory();
/*  4 */         else if(typeof define === 'function' && define.amd)
/*  5 */                 define([], factory);
/*  6 */         else {
/*  7 */                 var a = factory();
/*  8 */                 for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
/*  9 */         }
/* 10 */ })(typeof self !== 'undefined' ? self : this, function() {
//          ^--- correct global object detection

If this is a feature request, what is motivation or use case for changing the behavior?

The old UMD wrapper template used by webpack is not compatible with strict mode JavaScript.

Historically, it was not possible to load non-strict JavaScript as strict mode JavaScript without the script deliberately using the "use strict"; pragma. However, it is now possible to do this in browsers with <script type="module" src="my-bundle.js>.

UMD cannot dynamically import and export via ECMAScript Modules (ESM). However, it is still possible and useful to import UMD-wrapped libraries as leaf-nodes in an ESM dependency graph (accepting that they will probably export their modules to the detected global object). This is particularly helpful during the current transitional period, where the broader JavaScript ecosystem begins to adopt the new language-native module syntax.

The change required to make UMD-wrapped bundles compatible with strict mode is very small and is known to be compatible with a wide variety of scenarios. If webpack were to use the latest UMD templates, it would unlock authors to make use of a significant number of existing JavaScript libraries as leaf nodes in an ESM dependency graph without modification.

Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System.

I tested the example project mentioned above with:

  • Node.js v8.6.0
  • webpack v3.0.0-rc.2
  • OSX v10.12.6
@sokra
Copy link
Member

sokra commented Oct 18, 2017

Yep, send a PR.

cdata pushed a commit to cdata/webpack that referenced this issue Oct 18, 2017
@cdata cdata mentioned this issue Oct 18, 2017
@sokra sokra closed this as completed in 9a1034f Nov 28, 2017
sokra added a commit that referenced this issue Nov 28, 2017
microbit-matt-hillsdon added a commit to microbit-matt-hillsdon/react-carousel that referenced this issue Mar 16, 2020
See e.g. webpack/webpack#6522 /
webpack/webpack#5843
and the docs at
https://webpack.js.org/configuration/output/#outputglobalobject

This was broken by the Webpack 4 upgrade in brainhubeu#273.
This fix effectively reinstates Webpack 3 behaviour in the browser.

Note the component still doesn't really support SSR, but
its calls to Browser APIs are in componentDidMount and similar
so are delayed until client side.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants