Skip to content

Assets, base href and relative urls in css/scss #17747

Closed
@kunajs

Description

@kunajs

First of all, my project has multiple localizations defined in angular.json, so when running
ng build --configuration=production --localize
there are 3 subdirectories created in dist output path. Each of them has different base href in their index.html file.

Second, in angular.json I have assets subsection defined like:

"assets": [
  "src/favicon.ico",
  "src/assets"
],

and in assets/images there are these image files (among others):

  • bg_login_compressed.jpg (blured version of image, small size)
  • bg_login.jpg (full version of image, large size)

Then I have a component in some nested directory within the project, that is using following css classes:

.background-init {
  background-image: url("/assets/images/bg_login_compressed.jpg");
}
.background-loaded {
  background-image: url("/assets/images/bg_login.jpg");
}

As you can see, I am using root path to assets folder (starting with '/'), which is obviously wrong for base href that is not '/'.
My goal is to have div initialized with blured version of image, which is later replaced by full version. This is how I am doing it:
Template:

<div  [class.background-init]="!backgroundIsLoaded" [class.background-loaded]="backgroundIsLoaded">

Typescript:

public backgroundIsLoaded = false;

ngOnInit() {
  const img = new Image();
  img.src = './assets/images/bg_login.jpg';

  img.onload = () => {
    this.backgroundIsLoaded= true;
  };
}

This is ok during local development when running ng serve without base href parameter:

  • .css images are found
  • .ts image is found and loaded
  • both .css and .ts bg_login.jpg file is searched in the same path (= refer to the same file)

If I run ng serve --base-href /de/, which simulates run from production environment on IIS:

  • .css images are not found (they are searched in path '/assets/images/' instead of '/de/assets/images/')
  • .ts image is found and loaded
  • as a result, no images are shown as the background

Ok: let's switch to relative paths in .css url path, as advised in #4778 (comment):

.background-init {
  background-image: url("../../../assets/images/bg_login_compressed.jpg");
}
.background-loaded {
  background-image: url("../../../assets/images/bg_login.jpg");
}

On local development without base href it is working fine, as well as with --base-href /de/.
BUT what this causes when building? The files used in relative paths are copied from /assets/images/ to root directory of each localized build. This is unwanted and inpractical for many reasons described e.g. here: #14587 (comment) !!!
Side effect of this solution is:

  • .css image bg_login.jpg is searched in root path (of the build)
  • .ts image bg_login.jpg is searched in /assets/images/ path
  • that's why the code for replacing the background images will not work as desired (the image is loaded twice instead of once on the same path)

Other solutions that I tried:

  • using of rebaseRootRelativeCssUrls: not working on production and considered deprecated
  • using tilde in the .css path, such as url('~/assets/images/bg_login.jpg'): not working on production
  • using caret in the .css path, such as url('^assets/images/bg_login.jpg'): not working on production and officially not supported (Can't use relative paths in url() in scss files #12797 (comment))

I am searching for a clean solution which:

  • finds the images in the paths
  • doesn't copy the images when using relative css paths
  • is able to link to the same file when loading both from css and from ts
  • works on local and on production environment

Unfortunately, many of similar issues here on git are already locked due to inactivity, that's why I am creating this new one.

🌍 Your Environment



Angular CLI: 9.0.6
Node: 12.16.0
OS: win32 x64

Angular: 9.0.6
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.900.6
@angular-devkit/build-angular      0.900.6
@angular-devkit/build-ng-packagr   0.900.6
@angular-devkit/build-optimizer    0.900.6
@angular-devkit/build-webpack      0.900.6
@angular-devkit/core               9.0.6
@angular-devkit/schematics         9.0.6
@angular/cdk                       9.1.3
@ngtools/webpack                   9.0.6
@schematics/angular                9.0.6
@schematics/update                 0.900.6
ng-packagr                         9.0.3
rxjs                               6.5.4
typescript                         3.7.5
webpack                            4.41.2

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions