question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Async chunk loading breaks complex expressions in globalObject option

See original GitHub issue

Bug report

What is the current behavior?

// webpack.config.js
  output: {
    library: 'myLib',
    libraryTarget: 'umd',
    globalObject: 'typeof self !== \'undefined\' ? self : this',
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 1,
    }
  }

// index.js
  await import('./chunk')

generates code

var chunkLoadingGlobal = typeof self !== 'undefined' ? self : this["webpackChunkmyLib"] = typeof self !== 'undefined' ? self : this["webpackChunkmyLib"] || [];
/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));

The ternary expression for globalObject isn’t protected as an expression, but gets mixed with the surrounding code. In case the condition is true (typeof self !== 'undefined') and consequent path is taken, the result of this expression ends up being the equivalent of

var chunkLoadingGlobal = self

which then throws in the next line

Uncaught TypeError: chunkLoadingGlobal.forEach is not a function

Similar code also gets generated to the async chunk

typeof self !== 'undefined' ? self : this["webpackChunkmyLib"] = 

which would also fail if the execution ever got that far.

If the current behavior is a bug, please provide the steps to reproduce. Full minimal reproducible example in noppa/webpack-global-object-issue-repro.

What is the expected behavior? The code in globalObject option should be treated as an arbitrary expression and either lifted to a variable or wrapped in parenthesis

var root = typeof self !== 'undefined' ? self : this
var chunkLoadingGlobal = root["webpackChunkmyLib"] = root["webpackChunkmyLib"] || [];

The problem is easily enough fixed on the user’s side:

-     globalObject: 'typeof self !== \'undefined\' ? self : this',
+     globalObject: '(typeof self !== \'undefined\' ? self : this)',

and I get that this issue could end up closed as “working as intended”. However, I think that this limitation should then at least be mentioned in the docs and/or some kind of warning should be given. The nasty thing about the current behavior is that the code only breaks under very specific conditions:

  1. The app must contain async chunks. Without them, globalObject is only used in expression
```  
     })(typeof self !== 'undefined' ? self : this, function() {
```
which doesn't break the way the `chunkLoadingGlobal` code does. Simply adding `/* webpackMode: "eager" */ ` to the import will "fix" the issue.
  1. The condition in ternary must be true, as the RHS of the ternary actually works fine. In practice this means that the app crashes in browser (where self is defined) but not in Node.

Thus, the broken globalObject code is already widely used in the wild: grep.app search for unparenthesized ternaries in globalObject option.

I believe that at least these issues could be caused by this:

Other relevant information: webpack version: 5.26.3 and 4.46.0 Node.js version: 15.6.0 Operating System: Additional tools:

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
alexander-akaitcommented, Mar 18, 2021

To be honestly using () is always good, because it is always protect your code, but yes we can fix it

0reactions
vankopcommented, Nov 23, 2021

@alexander-akait I think better to add notes to docs. I think from option name is expected to get an identifier or member expression at least (not conditional expression) at runtime ok, I rethink… lets fix it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React Router Webpack async chunk loading - Stack Overflow
I think you can try using the bundle-loader. const loadContainerAsync = bundle => (location, cb) => { bundle(component => { cb(null, ...
Read more >
Update Webpack core packages to v5 (major) (!104336) · Merge ...
An error occurred while fetching the assigned milestone of the selected merge_request. Update Webpack core packages to v5 (major).
Read more >
Webpack 5 release (2020-10-10)
In webpack 4 multiple webpack runtimes could conflict on the same HTML page, because they use the same global variable for chunk loading....
Read more >
Tutorial - A Guide to Module Federation for Enterprise
Module Federation allows a JavaScript application to dynamically load code from another application and in the process, share dependencies.
Read more >
Strict mode - JavaScript - MDN Web Docs
Fixes mistakes that make it difficult for JavaScript engines to perform ... a new property on the global object and continues to "work"....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found