Skip to content

Option to ignore not found modules/URLs #455

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

Closed
Aleksanderis opened this issue Mar 14, 2017 · 14 comments
Closed

Option to ignore not found modules/URLs #455

Aleksanderis opened this issue Mar 14, 2017 · 14 comments
Assignees

Comments

@Aleksanderis
Copy link

Do you want to request a feature or report a bug?
It would be good to have an option to skip not found URLs instead of throwing "Module not found" errors.
It might be just a warning instead of critical error, or just skipped.
Ignoring all URLs and @imports, which is already supported - is not an option, since it's too global.

What is the current behavior?
When URL is not found it throws the error in following format:

ERROR in ./~/css-loader!./src/css/site.css
Module not found: Error: Can't resolve '../../node_modules/somelibrary/not-existing.gif'

This error eventually fails the whole webpack build.

What is the expected behavior?
If some options is enabled, such error becomes not critical and build is not marked as failed.

If this is a feature request, what is motivation or use case for changing the behavior?
Motivation is that when you rely on third-party library you cannot be sure they will include all files referenced in their vendor.css. We are forced (corporate branding stuff) to rely on some internal (but still third-party library - i.e. different team responsibility), which works following some strange bureaucracy workflow and bad publishing practices. So not including all referenced files - is a common case..

Please mention other relevant information such as your webpack version, Node.js version and Operating System.
Would it be possible to implement such feature or are there any blockers why it wasn't made already so?
Or maybe there are other ways to achieve same thing?

@michael-ciniawsky
Copy link
Member

@Aleksanderis It's depending on general usage, if it is possible to just display warnings and the build succees and works this would be a good idea. On the oher hand we already have a ton of url and @import releated issues because of the ambiguity of the resolver and trying to make it saner in the upcoming v1.0.0 release. I'm not against this feature by any means but the architecture and possible edge cases, where this might even break other code must be well thought of beforehand. If you have something in mind please send a PR for discussion (doesn't need to be perfect)

@Aleksanderis
Copy link
Author

Aleksanderis commented Mar 18, 2017

@michael-ciniawsky , sorry I'm quite new to webpack itself, and completely know-nothing yet in terms how webpack plugins/loaders are written inside. I didn't want to blame anyone, just was curious how easy it could be or couldn't be at all implemented.;)

But.. are you saying that it's actually not css-loader issue, but common way how webpack loaders work (or how third-party libraries, common for webpack loaders, are working)?
You mentioned something about resolver, and I reviewed Module not found error stack trace and found out that error comes from enhanced-resolve\lib\Resolver.js (which is not part of css-loader). Is it same resolver you were referencing?

Do I understand correctly how it works: css-loader just parses "url", "@import" and stuff like that, and just collects all potential "modules". After it - it's given to resolver (or webpack itself) to resolve these modules, and css-loader basically doesn't have control over it. So to implement what I'm asking, css-loader would need to try resolving everything additionally (which is of course potential performance drawbacks, and possible other issues). Did I get it correctly, or is it a little bit more complicated? ;)

@michael-ciniawsky
Copy link
Member

michael-ciniawsky commented Mar 18, 2017

But.. are you saying that it's actually not css-loader issue

@Aleksanderis Yes and no 😛

entry.js

import lib from 'lib' // Parser => Resolver => Tapable(Core Plugins, Plugins)
import css from './style.css' // Parser => Resolver => Tapable(Core Plugins(e.g Loader(s)), Plugins)
import component from './component' // Parser => Resolver => Tapable(Core Plugins, Plugins)

...

loader.js

module.exports = function (source, map) {
   console.log(this) // ~.context, ~.resource, ~.resourcePath ~.resolve => Resolver + others

   ...transform(source, map)

   return this.async(Error, source, map)
}

You mentioned something about resolver, and I reviewed Module not found error stack trace and found out that error comes from enhanced-resolve\lib\Resolver.js

Yep right this is the webpack Resolver I was referring to. It will provide metadata for webpack Loaders after resolving the module (see above)

Do I understand correctly how it works: css-loader just parses "url", "@import" and stuff like that, and just collects all potential "modules". After it - it's given to resolver (or webpack itself) to resolve these modules, and css-loader basically doesn't have control over it. So to implement what I'm asking, css-loader would need to try resolving everything additionally (which is of course potential performance drawbacks, and possible other issues). Did I get it correctly, or is it a little bit more complicated? ;)

The webpack Resolver and mainly a Core Plugin called Module Factory, first resolves the path in the parsed import/require statements and depending on the file extensions ({ test: /\.extname$/ }) try to call the appropiate loader (via loader-runner) for it when file.extname !== .js && module.rules.use[index].test

webpack.config.js

{
   module: { // => Settings for Parser, Resolver, Module Factory
     rules: [ 
          {
             test: /\.css$/,
             use: { loader: 'css-loader' } 
          }
     ]
}

css-loader has control over the transform and what is provided via this (Loader API), but it is basically a function called when the rule it was set on matches 😛 . There should be a this.outputPath on the API aswell, but with the ocean of usecases your feature request may or may not break some of them or have other side effects, it is complicated when it comes to that, since many maybe(s) need to be evaluated beforehand. But that doesn't mean it isn't possible or taken into regard so any proposal / demo repo / futher investigation you can provide are highly welcome and we will see what is possible :). Also note that my explanations are only a Loaders Author 101 at best and maybe not 💯 appropiated when it comes to webpack Core architecture in detail :D

@Astridax
Copy link

I'm also facing this issue. Currently what I'm planning to do is resolve it by making a dummy image and using the alias function to resolve to the dummy image.

Maybe this could either be a feature where it simply warns about unresolved files, or even where you can specify the URLs to ignore as per the alias syntax?

@petermikitsh
Copy link

Motivation is that when you rely on third-party library you cannot be sure they will include all files referenced in their vendor.css. We are forced (corporate branding stuff) to rely on some internal (but still third-party library - i.e. different team responsibility), which works following some strange bureaucracy workflow and bad publishing practices. So not including all referenced files - is a common case..

I don't think I could state it better. This feature would be great -- I have the exact same use case. I would prefer if Webpack handled the situation gracefully. Instead of exploding, just don't resolve the imports, and create a CSS file I can use. In this particular case, the fact that modules don't resolve does not matter.

@petermikitsh
Copy link

To anyone who might still be looking for a workaround, instead of processing these 'bad' CSS files (ones that have url()'s referencing missing files, etc), I'm using the raw-loader like so:

const Styles = require('!raw-loader!mystyles.css');

// later in my React component implementation

<style dangerouslySetInnerHTML={{__html: Styles}} />

It doesn't achieve the same goal as this issue (e.g., if you're extracting your CSS, this CSS will end up instead in your JS bundle), but it gets the job done.

@stereokai
Copy link

Would love a solution for this.

@tomasdev
Copy link

tomasdev commented Nov 5, 2017

Alternatively, what would be a resolver-for-not-founds-loader look like? all I found in docs, is mapping requests filenames to different filenames, not to sources themselves (meaning one could do module.exports = '';)

@michael-ciniawsky
Copy link
Member

#655

@Grohden
Copy link

Grohden commented Apr 18, 2018

@michael-ciniawsky when the fix will be released?

@terremoth
Copy link

I need this fix too

@olytv
Copy link

olytv commented Sep 10, 2019

@tomasdev thanks for tip! Now my solution is next:

const fs = require('fs');

...

module: {
    rules: [{
        test: /\.css$/,
        use: [
            {
                loader: 'css-loader',
                options: {
                    url (url) {
                        return fs.existsSync(url)
                    }
                }
            }
        ]
    }
}

It`s works brilliant for me)

@richardeschloss
Copy link

richardeschloss commented May 24, 2020

Hi, I found that using Webpack's ignorePlugin was even easier to use. However, I was sort of hoping that my conditional checks for dependencies would be respected:

try {
  await import ('/some/missing/but/optional/dep')
} catch (err) {
  // catch err
}

Sometimes I list dependencies as optional, so they won't always be packaged. Currently, webpack will throw an error and won't let my code be the one to handle it. Is it possible that I'm missing something or perhaps my design approach is flawed?

@kendagriff
Copy link

In case anyone else needs a variant on @olytv's solution:

    {
      test: function(url) {
        var path = 'file.js'
        if (fs.existsSync(path)) {
          return require.resolve(path)
        } else {
          return false
        }
      },
      use: 'imports-loader?this=>window'
    },

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