webpack-contrib/expose-loader

! vs |

aurels opened this issue · 14 comments

Documentation Is:

  • Missing
  • Needed
  • Confusing
  • Not Sure?

Please Explain in Detail...

Here in the docs :
https://github.com/webpack-contrib/expose-loader#inline

It's said that the separator is |. Then, just below, in the examples, it's a !.
Maybe I'm missing something but I think it's a typo.

Your Proposal for Changes

Use | in the examples. Unless it has another meaning ?

! is webpack syntax - https://webpack.js.org/concepts/loaders/#inline
| is loader syntax to provide multiple options

Mmhm. Thanks, still looks confusting. Would you give me an example of loading for example lodash, with override ?

import "expose-loader?exposes[]=_|lodash|true"
import "expose-loader?exposes[]=_|_|true!lodash"

I don't understand where the true goes.

import _ from "expose-loader?exposes=_!lodash";

should work

Nope, I get The "_" value exists in the global scope, it may not be safe to overwrite it, use the "override" option (at runtime). That's why I'm trying to use the override option from the README.

Why you want to override lodash existing in global scope, it can be unsafe in many cases

Good point. I'm investigating who's importing it at first place.

It looks like something specific to lodash. It seems to auto expose itself as _.
Doing import 'lodash' alone, makes it available everywhere I need it.

Not really clear to me since it wasn't the case before I updated expose-loader. Unless it was silently already doing this.

Thanks again.

Why you want to override lodash existing in global scope, it can be unsafe in many cases

@alexander-akait - Even I have similar use case. I was provided with a bundle that loads some React components based on some business logic that is processed within that bundle. So, when we expose React from the primary app , we wanted to ensure we use the same version of React across the app. So we tried using the expose-loader syntax, and eventually end up getting the error message
Uncaught Error: [exposes-loader] The "React" value exists in the global scope, it may not be safe to overwrite it, use the "override" option
Appreciate your inputs on this one. Thanks in advance !

But again, it is unsafe, you have react inside bundle and react into window, in your case I recommend to use external

But again, it is unsafe, you have react inside bundle and react into window, in your case I recommend to use external

Are you suggesting using external in the top level app and then load an external reference?

Here is my use case.

Main app has two bundles app.js and vendor.js(which is containing react). Now the third party bundle thirdparty.js which depends on react. Just so you are aware third bundle is from a different webpack and a different project and is directly loaded on the page. As suggested by you in this third party bundle we Ensured externals is enabled to ensure it doesn't load a different version of react. But when we load the app it fails stating react is undefined. So we thought expose loader can be used to make react global from vendor.js. But then we get a message stating override is required and unsafe. I hope this explanation summarizes my issue. Please advise with your inputs. Thanks

stam commented

Why you want to override lodash existing in global scope, it can be unsafe in many cases

Could you still answer the question about how to override in inline mode?
I'm working on a legacy project which would take months to refactor this properly.

And this doesn't work:
import "expose-loader?exposes=$|$|true,jQuery!../../lib/jquery/js/jquery-2.2.4.min.js";

@stam I think the correct syntax would be import 'expose-loader?exposes=$,jQuery|$,jQuery|true!jquery'; or import 'expose-loader?exposes=$|$|true,jQuery|jQuery|true!jquery'; which eliminates the errors from expose-loader but ultimately it does not expose jQuery as a global for me. Ref:

function resolveExposes(item) {

I think you'll have better luck adding expose rules to your Webpack config, ex:

            {
                test: require.resolve('jquery'),
                loader: 'expose-loader',
                options: {
                    exposes: [
                        {
                            globalName: '$',
                            override: true,
                        },
                        {
                            globalName: 'jQuery',
                            override: true,
                        },
                    ],
                },
            },