Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to use assets in url() in scss after upgrading to Angular 10

Tags:

angular

I upgraded my Angular application from v9 to v10. Almost everything worked but all my images used in url("assets/images/some/path/image.png") started to throw the exception-

ERROR in ./src/app/pages/about-us/about-us.component.scss Module Error (from ./node_modules/postcss-loader/src/index.js): (Emitted value instead of an instance of Error) CssSyntaxError: /Users/shashank/Projects/curika/temp-ssr/src/app/pages/about-us/about-us.component.scss:4:20: Can't resolve './assets/images/about-us.png' in '/Users/shashank/Projects/curika/temp-ssr/src/app/pages/about-us'    2 |   display: block;   3 |   min-height: 500px; > 4 |   background: url("./assets/images/about-us.png") no-repeat center;     |                    ^   5 | } 

Angular 10 error of assets

I tried various old links but none worked.

  1. https://github.com/angular/angular-cli/issues/12797
  2. https://github.com/angular/angular/issues/32811
like image 252
Shashank Agrawal Avatar asked Jun 28 '20 06:06

Shashank Agrawal


People also ask

Can I use SCSS in CSS angular project?

With the help of Angular CLI, you can install CSS or SCSS on your project and start working on that in a suitable way. If you are working with the CSS or SCSS in your angular project then it is very easy for you as compared to most other frameworks.

Can you have both CSS and SCSS in Angularjs?

The application renders fine with a mix of css and scss files. I assume this styleExt parameter is just there for the default component style ( css, scss, less ) file generation when adding components via angular-cli commands.


1 Answers

Not really sure what's changed in Angular 10?

But I found three solutions. The first solution I knew will work but that's time taking to implement in an existing mid-size application. But if you have only a few assets to fix, you should go for the first solution only.

Solution 1 - Using relative assets path (Recommended)

The solution is to use the relative path (from your .scss file) of your assets. Basically adding ../ until the assets folder is reached.

:host {     display: block;     min-height: 500px;     // Using relative path     background: url('../../../assets/images/about-us.png') no-repeat center; } 

Pros

  1. This approach enables the hashing of your static assets. Once your application is built (using ng build --prod), your asset URL will be replaced with an MD5 hash to burst the caching.

    So your URL

    background: url('../../../assets/images/about-us.png') no-repeat center; 

    will be replaced as

    background: url('about-us.add9979f32e1c969e6f8.png') no-repeat center; 

    This is basically an MD5 checksum of the content of the image. So basically, when the image changes even by one pixel, this checksum will be changed by Angular. This helps you to burst caching in future when you change your image while keeping the file name the same.

    Read more here for knowledge.

  2. IDE (I use IntelliJ IDEA) does not show errors of the assets in your SCSS files that means if the file path is wrong, IDE will tell you in advance.

    IDE Errors Gone

  3. You get the directory linking. That means if I press Ctrl & click on a directory in the URL above, IDE will open up that directory.

Cons

  1. (Manageable) This might be a cumbersome approach as the developer has to write the asset which needs to be relative to the assets folder.

  2. (Manageable) The hashed asset (image in this case) will be copied to the root folder in the build (i.e. dist by default) directory which might fail your any kind of URL rules (for example, caching rules). So instead of-

    https://example.com/assets/images/about-us.png 

    the following URL will be used-

    https://example.com/about-us.add9979f32e1c969e6f8.png 
  3. (Manageable) If you change the path of your component, you have to change the image URL as well.


Solution 2 - Quick Fix

Based on the answer posted here https://github.com/angular/angular-cli/issues/10004#issuecomment-375969537, adding / in front of the URL worked.

:host {     display: block;     min-height: 500px;     background: url('/assets/images/about-us.png') no-repeat center; } 

Pros

  1. You do not have to add many ../ prefixes to make it a relative URL.
  2. If you change the path of your component SCSS file, you don't have to change the path of your assets in url("").

Cons

  1. The second solution will not work in the production build if --base-href is used (as stated here). angular-cli#18043.

  2. Your IDE keeps showing the path error even if the path is correct.

    IDE path error

  3. You do not get the hashed URLs to burst the cache (unlike solution 1)


Solution 3 - Fooling the Angular CLI processor (not recommended)

I looked into the CLI code & figured out that if a URL starts with ^, Angular ignores the asset by bypassing the URL.

:host {     display: block;     min-height: 500px;     background: url('^assets/images/about-us.png') no-repeat center; } 

Source code- https://github.com/angular/angular-cli/blob/v10.0.0/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/postcss-cli-resources.ts#L72

Pros

  1. You do not have to add many ../ prefixes to make it a relative URL.

  2. If you change the path of your component SCSS file, you don't have to change the path of your assets in url("").

Cons

  1. This solution might get removed in the future releases as stated by one of the Angular CLI developers in #18013 (comment)
like image 152
Shashank Agrawal Avatar answered Oct 03 '22 09:10

Shashank Agrawal