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

Issues Related to Processing SASS Files #47

Open
homestar9 opened this issue Feb 22, 2023 · 5 comments
Open

Issues Related to Processing SASS Files #47

homestar9 opened this issue Feb 22, 2023 · 5 comments

Comments

@homestar9
Copy link
Contributor

homestar9 commented Feb 22, 2023

Hi @jclausen, thanks for taking the time to assist. I have summarized a list of issues I discovered when working with .scss or .sass files in Elixir V4. We already covered item 1 yesterday on Slack. The rest of the numbered items below may also be related.

1. Relative paths are translated incorrectly when converting SASS to CSS.

.brand{
  background-image: url( '../images/logo.png' );
}

Will become

.brand{
  background-image: url( '/includes/images/logo.png' );
}

The relative path should be preserved in the final output.

2. Nested/tracked submodule images are not copied to the right folder when using mix.modules()

If you create a tracked module that has its own .scss files which reference images, the images are copied to the project's root /includes/images/ folder instead of the tracked module's /modules_app/modulename/includes/images/ folder. Here's an example:
image
In the above example, the login module has its own .scss file and image which should be copied to the /includes/ folder within the submodule. However, today, if you run mix.modules() on the submodule, the image will be copied to the project root and the resulting CSS will point to the wrong place. The resulting css file should preserve the relative path like this:

.submodule-brand{
  background-image: url( '../images/module-logo.png' );
}

Side-note (nice-to-have): I know the convention for ColdBox is to output images in the /includes/images/ folder. However, I see a lot of developers using a folder called /img/ for images which is a nice abbreviation. It would be nice if we could configure Elixir to customize the resulting image output folder just in case we want to use a different naming scheme.

3. Source maps have the wrong path applied to them.

When processing .scss files, the resulting source map address contain the wrong path, which makes it hard for browsers to find them. Here's an example of a source sourceMappingUrl that was generated for a .scss file:
/*# sourceMappingURL=includes\css\app.css.map*/
It should be:
/*# sourceMappingURL=app.css.map*/
Typically source maps reside in the same folder as the minified file so there's no need for an absolute path.

4. Using mix.copy() within elixir-module.js needs absolute paths from root.

If you want to copy assets from a tracked module from the resources to the includes folder within that module, you must specify the absolute path from the root of the app, otherwise, Elixir won't copy the resources to the right place.
Example:

// elixir-module.js inside a tracked module
mix.copy( "resources/assets/images", "includes/images" );

Currently, the above code will copy both the images from /resources/assets/images and /modules_app/modulename/resources/assets/images to the root /includes/images folder. The expected behavior would be to copy the /modules_app/modulename/resources/assets/images to /modules_app/modulename/includes/ folder.
The workaround for this issue is to feed the absolute path to mix.copy() like this:

mix.copy( "modules_app/modulename/resources/assets/images", "modules_app/modulename/includes/images" );
@jclausen
Copy link
Collaborator

These should be resolved in coldbox-elixir@^4.0.4. Could you pull that version down @homestar9 and confirm?

@homestar9
Copy link
Contributor Author

homestar9 commented Feb 23, 2023

Thanks @jclausen. I have a few observations/notes:

1. Relative paths in .scss URLs appears to be fixed! Wohoo!
The final url does follow the weird "../../includes/..." pattern, but my guess is it's because the current version of resolve-url-loader throws an error if it can't find the files. Regardless, it's working!

2. Copying images from submodules to the same module works!

// in /modules_app/mymodule/elixir-module.js
mix.copy( "resources/assets/images", "includes/images" ); // works as expected!

3. Images in tracked sub modules are being copied to the /includes/images folder in the app root and the submodule simultaneously when referenced in .scss files, which is odd.
image
Let me know if you want help replicating the issue, but the TLDR is to create a simple tracked submodule, put an image in the /modules_app/resources/assets/images/ folder, and then reference it in a .scss file in /modules_app/resources/assets/sass/app.scss. You will see when you npm run dev the image will be copied to two different places.

// .scss file in modules_app/mymodule/resources/assets/sass/
background-image: url( "../../images/module-logo.png" ); <-- image copied to this submodule AND root for some reason

4. sourceMappingUrls now have the absolute path from the root, but this causes Chrome Dev tools to break:
/*# sourceMappingURL=modules_app\login\includes\css\app.css.map*/ should be
/*# sourceMappingURL=app.css.map*/
Here's what it looks like in the Chrome dev console:
image

5. Referencing an image in the root of the project from a tracked submodule will cause the resulting css link to point to the wrong place.
Lets say you have a logo in the /resources/assets/images/ folder and you want to reference it from a tracked submodule scss file located in /modules_app/mymodule/resources/assets/sass/app.scss:
This:

background-image: url( "../../../../../../resources/assets/images/logo.png" );

Becomes this:

background-image: url(../../includes/images/logo.png);

Which breaks the link.

@jclausen jclausen reopened this Feb 23, 2023
@jclausen
Copy link
Collaborator

OK. I will take a look at that sourcemap issue today.

I'm not sure about #5. It kind of breaks the idea of module encapsulation for a module to reference an asset from the root. Either way, mix.modules will normalize that referenced root file in to the moduleroot/includes/images directory - which is the expected behavior.

So, I guess I'm confused by these two statements, which seem to conflict:

put an image in the /modules_app/resources/assets/images/ folder, and then reference it in a .scss file in /modules_app/resources/assets/sass/app.scss. You will see when you npm run dev the image will be copied to two different places.

Referencing an image in the root of the project from a tracked submodule will cause the resulting css link to point to the wrong place.

@homestar9
Copy link
Contributor Author

homestar9 commented Feb 23, 2023

I'm not sure about 5. It kind of breaks the idea of module encapsulation for a module to reference an asset from the root

I know what you mean @jclausen . However, sometimes tracked submodules will need to reference global assets, like a logo, color scheme, fonts, theme, etc.

Imagine a PetStore app scenario where you have Dog and Cat tracked submodules. The Dog and Cat modules would have their encapsulated functionality but may also depend on global assets like the name of the pet store, a logo, color scheme, etc.

In fact, even the Ortus HMVC API convention breaks encapsulation to some degree. Tracked submodules are created in the API (e.g. /api/v1) to contain the handlers, but all of the models are placed in the root of the app, thus making them global.

On a personal level, I have always looked at tracked submodules in a modules_app folder as being "extensions" of the root app, whereas non-tracked modules should be treated as isolated/sandboxed dependencies.

That being said, I believe both issues (3) and (5) are separate problems. I will try to clarify my position.

Issue 3 says that images are being duplicated and copied to more than one location.
If you put an image in a tracked submodule, it is copied to the includes folder of the submodule (correct behavior) and another copy is placed in the root (incorrect behavior - also breaks encapsulation). Using the Petstore example, if the Cat module uses a picture of Catnip in its .scss file, webpack will copy it to the correct location in the submodule and create a redundant copy in the root (and possibly overwriting another asset if the file names are identical). The diagram I created shows where the assets are copied/duplicated.

Issue 5 says that if a submodule references a global asset, the URL to the global asset is not preserved.
For example, if a Cat module needs to link to a global logo file in the Petstore root ../../../../../../resources/assets/images/logo.png, webpack will change the final link to ../../includes/images/logo.png thus breaking the link/reference.

Hopefully this helps! Let me know if you need any assistance troubleshooting or if you want me to put together a test repo.

@homestar9
Copy link
Contributor Author

@jclausen one other thing I noticed related to items 3 & 4 above when using production mode npm run prod:

When running npm run prod and you have an image in a tracked submodule, the image is not duplicated, but it is copied to the root /includes/ folder instead of the submodule includes folder.

Example:
/modules_app/modulename/resources/assets/sass/app.scss links to an image:
/modules_app/modulename/resources/assets/images/module-image.jpg
Execute npm run prod
The image /modules_app/modulename/resources/assets/images/module-image.jpg is copied to /includes/images/module-image.95822a715e4a785fd795.jpg
The correct location should be: /modules_app/modulename/includes/images/module-image.95822a715e4a785fd795.jpg

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