bholloway / resolve-url-loader

Webpack loader that resolves relative paths in url() statements based on the original source file
563 stars 70 forks source link

How do I use this with laravel-mix and import-glob-loader? #125

Closed fiskhandlarn closed 5 years ago

fiskhandlarn commented 5 years ago

Is there any documentation how to add the option removeCR when using import-glob-loader? Current rule in my webpack.mix.js:

  {
    test: /\.scss$/,
    loader: 'import-glob-loader',
  },

(As previously asked in https://github.com/bholloway/resolve-url-loader/issues/107)

bholloway commented 5 years ago

@fiskhandlarn where are you using resolve-url-loader?

All I see is import-glob-loader. Do you have resolve-url-loader in this loader chain or is implied by import-glob-loader? In fact, do you have any sass loader/compilation happening?

fiskhandlarn commented 5 years ago

@bholloway I'm not specifying resolve-url-loader in my webpack.mix.js. I'm not an expert on webpack/laravel, but it seems to me that these are the places where sass/scss is loaded/compilated:

mix.webpackConfig({
  module: {
    rules: [
      {
        test: /\.scss$/,
        loader: 'import-glob-loader',
      },

[...]

mix.sass('resources/assets/styles/app.scss', 'styles', {
  includePaths: ['node_modules'],
});

Adding this (from https://github.com/bholloway/resolve-url-loader/issues/107#issuecomment-475184600) before or after import-glob-loader does nothing:

      {
        test: /\.scss$/,
        loader: 'resolve-url-loader',
        options: { removeCR: true }
      },
fiskhandlarn commented 5 years ago

import-glob-loader doesn't seem to be able to pass options to resolve-url-loader: https://www.npmjs.com/package/import-glob-loader#options :(

bholloway commented 5 years ago

@fiskhandlarn webpack loaders don't work that way. The loaders are each specified with their options. They don't pass options to each other, only transformed code (and source-map).

So looking at laravel-mix I can see it is using an old version of resolve-url-loader. The removeCR option doesn't exist. But more importantly it doesn't need to since AFAIK this older version doesn't have a problem with orphan CRs.

What is the actual error you are getting?

bholloway commented 5 years ago

The actual config is here it is hard coded anyhow.

fiskhandlarn commented 5 years ago

So looking at laravel-mix I can see it is using an old version of resolve-url-loader. The removeCR option doesn't exist. But more importantly it doesn't need to since AFAIK this older version doesn't have a problem with orphan CRs.

I'm explicitly requiring resolve-url-loader v3.1.0 in my project's package.json.

What is the actual error you are getting?

ERROR in ./resources/assets/styles/app.scss
Module build failed (from ./node_modules/css-loader/index.js):
ModuleNotFoundError: Module not found: Error: Can't resolve '../../../../images/favicons/favicon.svg' in 'D:\dokument\projekt\oskar\privat\wordplate\lorica\resources\assets\styles'
    at factory.create (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\lib\Compilation.js:823:10)
    at factory (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\lib\NormalModuleFactory.js:397:22)
    at resolver (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\lib\NormalModuleFactory.js:130:21)
    at asyncLib.parallel (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\lib\NormalModuleFactory.js:224:22)
    at D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\neo-async\async.js:2825:7
    at D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\neo-async\async.js:6886:13
    at normalResolver.resolve (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\lib\NormalModuleFactory.js:214:25)
    at doResolve (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:184:12)
    at hook.callAsync (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn0 (eval at create (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
    at resolver.doResolve (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\UnsafeCachePlugin.js:37:5)
    at hook.callAsync (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn0 (eval at create (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
    at hook.callAsync (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn0 (eval at create (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:27:1)
    at resolver.doResolve (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\DescriptionFilePlugin.js:42:38)
    at hook.callAsync (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn43 (eval at create (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:16:1)
    at hook.callAsync (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn1 (eval at create (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:16:1)
    at hook.callAsync (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn1 (eval at create (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:16:1)
    at hook.callAsync (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn0 (eval at create (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
    at fs.stat (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\DirectoryExistsPlugin.js:22:13)
    at process.nextTick (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:73:15)
    at process._tickCallback (internal/process/next_tick.js:61:11)
 @ ./resources/assets/styles/app.scss

ERROR in ./resources/assets/styles/app.scss (./node_modules/css-loader??ref--5-2!./node_modules/postcss-loader/src??postcss0!./node_modules/resolve-url-loader??ref--5-4!./node_modules/sass-loader/lib/loader.js??ref--5-5!./node_modules/import-glob-loader!./resources/assets/styles/app.scss)
Module not found: Error: Can't resolve '../../../../images/favicons/favicon.svg' in 'D:\dokument\projekt\oskar\privat\wordplate\lorica\resources\assets\styles'
 @ ./resources/assets/styles/app.scss (./node_modules/css-loader??ref--5-2!./node_modules/postcss-loader/src??postcss0!./node_modules/resolve-url-loader??ref--5-4!./node_modules/sass-loader/lib/loader.js??ref--5-5!./node_modules/import-glob-loader!./resources/assets/styles/app.scss) 7:310901-310951
 @ ./resources/assets/styles/app.scss
fiskhandlarn commented 5 years ago

The actual config is here it is hard coded anyhow.

Thanks for the find! Maybe I should ask laravel-mix to add options: { removeCR: true } or give us the option to pass options to resolve-url-loader ..?

bholloway commented 5 years ago

I'm explicitly requiring resolve-url-loader....

So resolve-url-loader@2.3.1 is a transitive dependency of laravel-mix. 🤔 I'm presuming that you are using yarn resolutions to get the later version? Otherwise I don't see how this works.

(aside: you may not need the latest version. I think the main reason would be if you are using more modern css that engine:rework cannot support. Anyhow I leave that to you.)

Maybe I should ask laravel-mix...

Before doing that I think you would want to confirm that any changes actually solve your problem.

If you need changes to options you would first want to hack on the source code in node_modules/larabel-mix/.. and make it work.

Looking at your error it is not clearly a case of orphan CR. Maybe you have some other evidence of extra CRs in your sass compile on windows?

I would suggest using the debug:true option so that you can see what the resolve-url-loader is trying to do. In fact, you might want to setup a number of options by hacking that laravel-mix file.

bholloway commented 5 years ago

Further to the orphan CR. There are steps to diagnose here. But as you can see the error is different in your case.

bholloway commented 5 years ago

^ renaming

fiskhandlarn commented 5 years ago

I'm explicitly requiring resolve-url-loader....

So resolve-url-loader@2.3.1 is a transitive dependency of laravel-mix. 🤔 I'm presuming that you are using yarn resolutions to get the later version? Otherwise I don't see how this works.

I'm not using yarn. But if I use v2.3.1/2.3.2 I get no errors, so I'm guessing laravel-mix is using v3.1.0 after all?

(aside: you may not need the latest version. I think the main reason would be if you are using more modern css that engine:rework cannot support. Anyhow I leave that to you.)

Agreed. I just like having the latest versions. :)

Maybe I should ask laravel-mix...

Before doing that I think you would want to confirm that any changes actually solve your problem.

If you need changes to options you would first want to hack on the source code in node_modules/larabel-mix/.. and make it work.

I'll look into that, thanks!

Looking at your error it is not clearly a case of orphan CR. Maybe you have some other evidence of extra CRs in your sass compile on windows?

The file with the css that it chokes on is formatted as utf-8-unix.

I would suggest using the debug:true option so that you can see what the resolve-url-loader is trying to do. In fact, you might want to setup a number of options by hacking that laravel-mix file.

I'm not sure how to set debug: true. If that was possible I could set removeCR: true in the first place. X)

fiskhandlarn commented 5 years ago

When I try setting linefeed (as suggested in https://github.com/bholloway/resolve-url-loader/blob/master/packages/resolve-url-loader/README.md#windows-line-breaks) like this:

mix.sass('resources/assets/styles/app.scss', 'styles', {
  includePaths: ['node_modules'],
  linefeed: 'cr',
});

... I get another type of error:

ERROR in ./resources/assets/styles/app.scss
Module build failed (from ./node_modules/css-loader/index.js):
ModuleBuildError: Module build failed (from ./node_modules/resolve-url-loader/index.js):
Error: resolve-url-loader: CSS error
  source-map information is not available at url() declaration (found orphan CR, try removeCR option)
  at file://D:\dokument\projekt\oskar\privat\wordplate\lorica\resources\assets\styles\app.scss:14579:3
    at encodeError (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\resolve-url-loader\index.js:219:12)
    at onFailure (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\resolve-url-loader\index.js:176:14)
    at runLoaders (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\lib\NormalModule.js:301:20)
    at D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\loader-runner\lib\LoaderRunner.js:367:11
    at D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\loader-runner\lib\LoaderRunner.js:233:18
    at context.callback (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\loader-runner\lib\LoaderRunner.js:111:13)
    at onFailure (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\resolve-url-loader\index.js:176:5)
 @ ./resources/assets/styles/app.scss

When I follow the steps under "Diagnosis" I find multiple occurences of 0A, but none of 0DOA or 0D.

fiskhandlarn commented 5 years ago

When I remove the linefeed option and remove all linebreaks in my scss file I get this error instead:

ERROR in ./resources/assets/styles/app.scss
Module build failed (from ./node_modules/css-loader/index.js):
ModuleBuildError: Module build failed (from ./node_modules/resolve-url-loader/index.js):
Error: resolve-url-loader: CSS error
  predicate must return an absolute path or the result of calling next()
  at file://D:\dokument\projekt\oskar\privat\wordplate\lorica\resources\assets\styles\app.scss:2:3
    at encodeError (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\resolve-url-loader\index.js:219:12)
    at onFailure (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\resolve-url-loader\index.js:176:14)
    at runLoaders (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\webpack\lib\NormalModule.js:301:20)
    at D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\loader-runner\lib\LoaderRunner.js:367:11
    at D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\loader-runner\lib\LoaderRunner.js:233:18
    at context.callback (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\loader-runner\lib\LoaderRunner.js:111:13)
    at onFailure (D:\dokument\projekt\oskar\privat\wordplate\lorica\node_modules\resolve-url-loader\index.js:176:5)
 @ ./resources/assets/styles/app.scss
fiskhandlarn commented 5 years ago

It seems to be that the lookup path is a bit off.

With an absolute URL:

  background: url('/resources/assets/images/favicons/favicon.svg') 50% no-repeat fixed;

... I get this error:

ModuleNotFoundError: Module not found: Error: Can't resolve '../../../node_modules/resources/assets/images/favicons/favicon.svg' in 'D:\dokument\projekt\oskar\privat\wordplate\lorica\resources\assets\styles'

And with a relative URL:

  background: url('../images/favicons/favicon.svg') 50% no-repeat fixed;

... I get this error:

ModuleNotFoundError: Module not found: Error: Can't resolve '../../../../images/favicons/favicon.svg' in 'D:\dokument\projekt\oskar\privat\wordplate\lorica\resources\assets\styles'
fiskhandlarn commented 5 years ago

This works! :scream:

  background: url('/../resources/assets/images/favicons/favicon.svg') 50% no-repeat fixed;

Didn't think of trying that since relative paths (e.g. ../images/favicons/favicon.svg) worked with v2.3.2.

Is this the expected/wanted behaviour as of v3?

bholloway commented 5 years ago

No that doesn’t make sense. Should not be necessary.

Sorry nighttime here will try to look tomorrow.

Although I think it will be difficult without something open source we can both discuss. Can you make a minimum breaking example in GitHub?

fiskhandlarn commented 5 years ago

Sorry nighttime here will try to look tomorrow.

Appreciate it!

Although I think it will be difficult without something open source we can both discuss. Can you make a minimum breaking example in GitHub?

https://github.com/fiskhandlarn/resolve-url-loader-error

bholloway commented 5 years ago

Okay it finds the newer version of the loader because laravel-mix refers to the package by name as 'resolve-url-loader' in the loaders.push().

If I hack the file there and do console.log(require.resolve('resolve-url-loader')) I get the version you intended node_modules/resolve-url-loader/index.js. It is strange that npm does not also install version ^2.3.1 that is specified by laravel-mix. This seems to be outside spec for how npm should behave.

First of all I need to remove the root option on the loader. This is completely wrong for version 3 which has a different (more conventional) meaning for root. Just to be clear I'm trying.

options: {
  sourceMap: true,
  debug: true,
  engine: 'postcss'
}

I still get the CSS Error. This means there is some CSS that postcss can't parse. That is quite unlikely unless you are using something that is not standard CSS.

bholloway commented 5 years ago

Related to this? https://github.com/JeffreyWay/laravel-mix/issues/1998

bholloway commented 5 years ago

Okay so problem. When the loader runs it has context: /.../node_modules/laravel-mix/src/builder.

So the absolute path is correct but we expect this to be your project directory, not the laravel-mix package.

This means that the incoming source-map is not correctly parse. 🤔 I will need to think about this.

In the mean time look at what they did with JeffreyWay/laravel-mix#1998 to splice the load-url-loader. It is probable that you will want to do something similar. We will probably need to add a couple of loaders to fix this.

bholloway commented 5 years ago

Yeah I don't think we can fix this without setting the context correctly. The culprit is the LoaderOptionsPlugin seen here.

This has been removed from laravel-mix@master so try that. Its not yet tagged so you will need to npm install from github which should be something like JeffreyWay/laravel-mix#master.

fiskhandlarn commented 5 years ago

@bholloway When I use laravel-mix@master like this:

    "laravel-mix": "github:JeffreyWay/laravel-mix#master",

... this compiles correctly:

    background: url('../images/favicons/favicon.svg');

Huzzah! Thanks for all kind help. I guess I'll wait for laravel-mix@master being released then. :)

bholloway commented 5 years ago

Cool. Good we finally got it working. And sorry for the extended delay on answering this issue.

Feel free to ask any related questions but I will close the issue for now.

With any luck you won't need to options changed. However keep in mind that per the breaking changes absolute URIs will be prepended with the value in the root option set here. But that is probably more what was originally intended anyhow.