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

ProviderPlugin should have feature to skip files #6226

Closed
NN--- opened this issue Jan 3, 2018 · 17 comments
Closed

ProviderPlugin should have feature to skip files #6226

NN--- opened this issue Jan 3, 2018 · 17 comments
Labels

Comments

@NN---
Copy link

NN--- commented Jan 3, 2018

Do you want to request a feature or report a bug?
Feature if it doesn't exist.

What is the current behavior?
Currently ProviderPlugin goes over all files and makes changes.
The problem arises with modules which use default object if provided.
For instance:

var json = window.JSON ? window.JSON : JSONPolyfill;

Using ProviderPlugin as:

ProviderPlugin("window.JSON" : "JSONPolyfill")

Then the output is:

var json = JSONPolyfill ? JSONPolyfill : JSONPolyfill;

What is the expected behavior?
I would like to have exclude list for provider plugin so that (pseudocode) will not touch JSONPolyfill.js .

ProviderPlugin("window.JSON" : "JSONPolyfill", exclude: ['JSONPolyfill'] )

If this is a feature request, what is motivation or use case for changing the behavior?
This is needed to support old browsers.

@jacobdfriedmann
Copy link

Typically, the result of executing a polyfill is that the global method it is designed to polyfill will be defined, even in browsers that don't natively support it (in this case window.JSON). Rather than using the ProvidePlugin to replace references to the global method, you probably just need to make sure that the polyfill is executed before your application code. You can do this by making it the first item in the entry array.

For instance, here is the recommended use of the babel-polyfill, which polyfills Array.from, Object.assign among many other things:

module.exports = {
  entry: ["babel-polyfill", "./app/js"]
};

More: https://babeljs.io/docs/usage/polyfill/#usage-in-node-browserify-webpack

@NN---
Copy link
Author

NN--- commented Jan 16, 2018

@jacobdfriedmann I need something that doesn't change global object and using ProviderPlugin was simplest working solution.
It just lacks one small feature.

@jrschumacher
Copy link

@NN--- I've added this feature in PR #9420

@webpack-bot
Copy link
Contributor

This issue had no activity for at least three months.

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.

@fregante
Copy link

fregante commented Nov 1, 2020

Inactive but still needed. Currently it's impossible to use ProvidePlugin with polyfills unless they specifically watch out for this this gotcha, which isn't always possible.

Webpack issues get closed because of inactivity while issues still remain. Related: #5828

@alexander-akait
Copy link
Member

@fregante What do you mean?

@fregante
Copy link

fregante commented Nov 2, 2020

ProvidePlugin inexplicably tries to provide a module to itself, breaking any feature detection inside it: typeof something === 'undefined' will not be true inside it, so the polyfill won't run.

Currently, the only way to avoid this is to have the polyfill check for, say window.something or 'something' in window while using new ProvidePlugin({something: 'something-polyfill'}). Not every polyfill maintainer is willing to change a perfectly-valid detection for no good reason.

@alexander-akait
Copy link
Member

@fregante you can re-send PR, staled #9420

@fregante
Copy link

fregante commented Nov 2, 2020

I think that while that PR would probably fix it and extend the functionality, it'd require more configuration. My suggestion would be to exclude self automatically since I can't think of a situation where a module would basically require itself.

@alexander-akait
Copy link
Member

But here edge case when you can use if (something) { something = code; } inside module

@fregante
Copy link

fregante commented Nov 2, 2020

The module itself is something, why would it check for itself? ProvidePlugin currently transforms that code to:

if (require('something')) { something = code; }

No 'something' module would do that

@alexander-akait
Copy link
Member

alexander-akait commented Nov 2, 2020

What about?

something = require('something') || variable;

@fregante
Copy link

fregante commented Nov 2, 2020

I don't think we're on the same page. ProvidePlugin is about not using require in the code. This is the module injected by ProvidePlugin:

if (typeof something === 'undefined') something = {}

and it's transformed to:

const something = __webpack_require__(this same module);
if (typeof something === 'undefined') something = {}

The injected module should not be altered. Not by Webpack, not by the owner (only to improve webpack compatibility)


If I have to use your suggested code, this proves my point:

Currently it's impossible to use ProvidePlugin with polyfills unless they specifically watch out for this this gotcha, which isn't always possible.

@alexander-akait
Copy link
Member

I see... to be honest, this plugin was not designed for polyfills, the problem is that different polyfills need to be configured in completely different ways, and to be honest again it's not even safe, but yes it work in simple cases, why do you want using this plugin for polyflling? Maybe you can provide example of code, want to ivnestigate deeply, maybe you can find good approach and improve our docs/code for this

@jrschumacher
Copy link

@fregante that was my experience as well, but at this point the change would be breaking so I don't think a "fix" is a good idea. The impact on existing usecases could be large. IMO the solution is to extend it to allow for exclusion.


The usecase which I have for the provide plugin is to override native functions (i.e. XHRHttpRequest) without impacting the sites where my library is used. Specifically, my library uses other libraries which use Axios so without major refactoring I can't capture the requests. The challenge I had was that my override included the XHRHttpRequest.

// overrideXHRHttpRequest.js
const nativeXHRHttpRequest = window.XHRHttpRequest;
const overrideXHRHttpRequest; //.... override
module.exports = overrideXHRHttpRequest;

At this point there is a circular dependency because the provide plugin will wrap override file.

@fregante
Copy link

fregante commented Nov 3, 2020

IMO the solution is to extend it to allow for exclusion

Yeah, it could still be an optional behavior like includeSelf: true rather than having to specify the same module twice like #9420 would allow.

why do you want using this plugin for polyflling

Context: mozilla/webextension-polyfill#156

This polyfill-ish uses UMD, so if I load it directly it will act as a proper polyfill, but if I ask webpack to include it (via whichever method) it won't set the global, forcing me to do that manually before anything else runs.

Currently the solution that requires the least configuration is via CopyFilePlugin but this requires loading/handling the file separately (and also having a separate plugin)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants