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

Relative url() paths in compiled Sass files can be wrong #2

Open
weaverryan opened this issue Jul 20, 2023 · 4 comments
Open

Relative url() paths in compiled Sass files can be wrong #2

weaverryan opened this issue Jul 20, 2023 · 4 comments

Comments

@weaverryan
Copy link
Contributor

weaverryan commented Jul 20, 2023

Suppose this setup:

/* assets/styles/app.scss */
import 'tools/base';
/* assets/styles/tools/base.scss */
.splash {
  background-image: url('../../images/login-bg.png');
}

The image lives at assets/images/login-bg.png, so the relative path above is, correctly, relative to the source file. Currently, if you compile this, because the contents are all compiled into, basically, assets/styles/app.css, the relative path will now be incorrect.

Fix

I have 2 ideas to fix this:

  1. rails-sass look like they have you use some special fake functions in your scss files - https://github.com/rails/sass-rails#asset-helpers (the code, I think, actually lives in https://github.com/sass/sassc-rails). I'm not entirely sure how the implementation is done, but it looks like you literally do asset-path("rails.png") in your CSS files and it's written.

Pros: looks simple to implement.
Cons: this is magic, and your editor won't like it.

  1. When the final .css file is built, we can also have it output an importmap (also, it would be great to expose that importmap - or perhaps "embed" it in the .css file for simplicity if possible in dev mode). We can, in theory, use this importmap to do this logic:

A) Determine that the background-image: url('../../images/login-bg.png'); line came from assets/styles/tools/base.scss
B) Determine that this file lives one directory deeper than the source, assets/styles/app.scss.
C) Adjust the path accordingly to ../images/login-bg.png'

This might be trickier to implement - I've never parsed a sourcemap for info - but would be a completely clean solution. This is also how resolve-url-loader from Webpack works - https://github.com/bholloway/resolve-url-loader/blob/HEAD/packages/resolve-url-loader/docs/how-it-works.md#the-solution

@weaverryan weaverryan mentioned this issue Aug 7, 2023
@smnandre
Copy link
Contributor

smnandre commented Dec 3, 2023

It could be simpler in fact: if you know that we should change just relatively, we can give that info as CLI option on compile time

https://sass-lang.com/documentation/cli/dart-sass/#source-map-urls

@dorxy
Copy link

dorxy commented Dec 10, 2023

For the clean solution to work there would need to be some pipeline construction introduced to post process the generated css (and its sourcemap).

The dart sass binary can write directly to output, which could be processed with the symfony asset component to also directly make use of the versioning and such, but when writing to output you can no longer use the watch option which is kinda essential.

I believe this leaves two options:

  1. Run the sass compilation as it is now, but also run a process concurrently which watches for changes in the expected output files and processes them to replace paths with urls.
  2. Implement a watcher for the original files, run sass every time changes are detected and use the output to do the same post processing.

In both cases the suggestion by @smnandre to use sass’s relative option is useful, also the compiled css has to be parsed in both cases, for which I’m wondering if introducing a library to ‘properly’ parse it would be overkill if the alternative is regexing the sourcemap and preg_replacing its entries.

Any thoughts on these options and parsing implementation?

@justin-oh
Copy link

I'm just starting to learn about the Asset Mapper and found this issue through the documentation. I understand that a relative path does not work, but would the absolute path work?

.splash {
  background-image: url('/assets/images/login-bg.png');
}

If so, perhaps instead of finding a solution for images it should be a requirement their paths are non-relative.

@smnandre
Copy link
Contributor

It's far from "not working" but there are some limitations :)

https://symfony.com/doc/current/frontend/asset_mapper.html#paths-inside-of-css-files

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

4 participants