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

URLs in CSS should be relative to the CSS file, but can't achieve with publicPath #367

Closed
karlvr opened this issue Mar 27, 2019 · 8 comments

Comments

@karlvr
Copy link
Contributor

karlvr commented Mar 27, 2019

This appears to be an ongoing and reasonably common issue. See #44.

The issue is that webpack outputs URLs relative to the context (assumed to be where the HTML is), which works fine for JS but not CSS, as urls in CSS files are resolved relative to the CSS file, while URLs in JS files are resolved relative to the HTML.

Using publicPath is a blunt instrument that either requires you to use an absolute path, or to use a relative path and to always output your CSS files at the same depth (e.g. set publicPath to ../ and always output your css files into css/).

I am preparing a simple patch for mini-css-extract-plugin to add an additional option which I think I'll call urlsRelativeToSource. It dynamically adjusts the publicPath that it sends to downstream loaders to the relative path from the source CSS file to the root context...

So if the source file is ./forum/css/main.css then publicPath is set to ../../ when passed down to url-loader or file-loader or whatever is next, which means a url in your CSS that was ../img/header.png, becomes ../../forum/img/header.png. When loaded from your CSS _assuming it's output to ./forum/css/main.css, that relative URL (while containing a redundant .. and forum) works.

The assumption that is required here is that you'll output your CSS files at the same depth in the directory structure as the source file is. Hence the option is urlsRelativeToSource. This is because I don't think a loader knows where the output file is going, otherwise we could just make the URLs relative to the output.

Is anyone interested? This fixes the issue for me... will this be useful for others and will it be acceptable as a patch? I don't want to base our workflow on a fork!!

@karlvr karlvr changed the title URLs in CSS are relative to the CSS file URLs in CSS should be relative to the CSS file, but can't achieve with publicPath Mar 27, 2019
@karlvr karlvr changed the title URLs in CSS should be relative to the CSS file, but can't achieve with publicPath URLs in CSS should be relative to the CSS file, but can't achieve with publicPath Mar 27, 2019
@alexander-akait
Copy link
Member

Why they should be relative? It is out of scope this plugin you can use minificator for this.

@alexander-akait
Copy link
Member

alexander-akait commented Mar 27, 2019

Also it can potentially break code, because you can use same css (same css module) in difference places (so resolution url was wrong). We already supported this option for file-loader in past, but remove this because it is break code in many cases. Here same problem. I strongly recommend don't do this. It is bad practice.

Anyway can you provide example what you actually have and what you expected? Maybe i don't understand you correctly.

@karlvr
Copy link
Contributor Author

karlvr commented Mar 27, 2019

I've pushed a branch that implements this and it's working nicely for me so far https://github.com/karlvr/mini-css-extract-plugin/tree/publicPathRelativeToSource

@karlvr
Copy link
Contributor Author

karlvr commented Mar 27, 2019

@evilebottnawi Thank you so much for your quick response. As I understand it mini-css-extract-plugin outputs a single CSS file (or chunks). URLs to (say) images in that CSS file are always relative to that CSS file. Some people use a relative publicPath but that assumes that your CSS file output is always at the same depth relative to the context.

The reason I need the URLs in my CSS to be relative (and anyone using a publicPath of ../) is because I am using the CSS files in a context where I don't know the absolute path (or can't use one, like in Cordova). I can't use publicPath = '../' because I have multiple CSS files, some of them at different depths in the tree.

I thought mini-css-extract-plugin would be the right place to do this as its output is CSS, so to output correct URLs in the CSS at this stage seems right. Before mini-css-extract-plugin the output is JavaScript, and so the context-relative URLs are right there as JavaScript loads resources context-relative.

@karlvr
Copy link
Contributor Author

karlvr commented Mar 27, 2019

If this doesn’t land, perhaps an alternative would be to implement support for a function as the publicPath option, and give it access to this and it could happily do the same work. I’d be happy to contribute this, and it’s much less opinionated!

@alexander-akait
Copy link
Member

@karlvr feel free to send a PR, let's discussion with code.

@karlvr
Copy link
Contributor Author

karlvr commented Mar 27, 2019

@evilebottnawi thank you, I've sent a PR with my first option—adding the publicPathRelativeToSource option.

If it were possible to know where the output was going to go, this could be improved to calculate the relative URL relative to the output instead of the source.

Relative URLs are native/common in CSS so I do think improving relative URL support is useful / important for this loader as it outputs CSS.

Shall I make a PR for a publicPath function too?

@alexander-akait
Copy link
Member

Can be achieved by #373, using relative paths is not safe in some cases, so we don't want to provide this options out of box

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

2 participants