bholloway / resolve-url-loader

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

Resolve URLs relative to a given path #34

Closed loilo closed 7 years ago

loilo commented 7 years ago

I'm trying to use resolve-url-loader to keep my image assets in their original place but link to them from the bundle. This is probably a very common approach, but I'll sketch it here anyway:

/* src/main.css */
body {
    background-image: url('image.png');
}

should compile to

/* bundle/main.css */ body { background-image: url('../src/image.png'); }

Now my folder structure looks like this:

|- src
|`|- main.css
| `- image.png
|- bundle
`- other-stuff
   `- build

...where src contains original CSS and image assets, bundle should hold the bundled CSS files and other-stuff/build contains Webpack, the Webpack configuration and is also the process.cwd() when bundling. (Of course this is a little bit of an abstraction of my real project but it's sufficient to demonstrate the point.)

Sadly, resolve-url-loader will always resolve the URL to _/_/src/image.png which (if I interpret the underscores as ..) is the correct path from the build directory but I want it to contain the relative path from the bundle folder. Using the root option sadly did not help, the output is exactly the same.

bholloway commented 7 years ago

You shouldn't need this loader for CSS files that are directly seen by webpack as imports.

URLs in CSS are already relative and webpack has the correct behaviour.

You need this loader for transpiled CSS such as sass. Webpack will try to resolve assets relative to the compiled CSS, but assets will be relative to uncompiled sass files.

loilo commented 7 years ago

I just updated the issue but I think your answer is still applicable. I actually do have SASS and CSS mixed but even in CSS I can't produce the desired behaviour. Webpack requires to have a loader for those asset URLs which made me use file-loader but I haven't found a way to tell file-loader that it should not touch the asset files and just link to their original place which is why I eventually got to use resolve-url-loader.

loilo commented 7 years ago

But I realized file-loader and resolve-url-loader do in fact produce the same underscory URLs. Which means I've probably got to figure out how to get rid of those in general and not regarding your specific module.

Thanks for your quick help anyway. 👍

loilo commented 7 years ago

...I solved it by correctly setting Webpack's context option. Now I feel a little bit stupid. Thank you for bringing me on the right track (away from resolve-url-loader) though. 😄

bholloway commented 7 years ago

If assets are hitting your file loader then that is a good sign as it means all is well with CSS.

Tweak the pattern on your file loader to get your assets the way you want.

My opinion is that webpack should process all your assets. That way you can add fingerprinting and use publicPath for CDN deployment.

bholloway commented 7 years ago

No problem. Happy to help.

Please close out the issue if you have not already done so.

loilo commented 7 years ago

I agree with you in general but in my specific case I'm using Webpack as a precompiler/minifier for a CMS which does not do that very well on its own. However therefore I need the asset files to be untouched.

In case anyone stumbles upon the same issue – the solution was as easy as:

  1. Set Webpack's context option to point to my project root.
  2. Just use file-loader like this: file?emitFile=false&name=[path][name].[ext]&publicPath=../.
    • emitFile=false: Does not copy the image assets to the output directory
    • name=[path][name].[ext]: Generate the correct path...
    • publicPath=../: ...from the bundle folder.