Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace SCSS files with Angular CLI?

Angular CLI provides the possibility to replace files when building the project. I would like to use this functionality to replace a SCSS file with default styling, with a SCSS file that contains customer specific CSS.

But Angular CLI seems not to replace the SCSS files. How could I achieve this?


What I have tried:

environment.default.ts

export const environment = {
  name: 'default'
};

environment.special.ts

export const environment = {
  name: 'special'
};

default/_scss-config.scss

@debug ('default'); // gets called but should never be called

special/_scss-config.scss

@debug ('special'); // never gets called

angular.json (only relevant parts)

  "architect": {
    "build": {
      "builder": "@angular-devkit/build-angular:browser",
      "options": {
        "fileReplacements": [
          {
            "replace": "src/environments/environment.default.ts",
            "with": "src/environments/environment.special.ts"
          },
          {
            "replace": "src/scss/default/_scss-config.scss",
            "with": "src/scss/special/_scss-config.scss"
          }
        ],
        "stylePreprocessorOptions": {
          "includePaths": [
            "src/scss/default"
          ]
        }
      }
    }
  }

main.ts

import { environment } from './environments/environment.default';

console.log(environment.name); // 'special' --> replacement works!

Result:
File replacement for .ts files works, but not for .scss files, as the special debug statment never gets called, but the default does, even the file should have been repalced.

like image 264
jowey Avatar asked Feb 16 '19 14:02

jowey


People also ask

How do I change a SCSS file?

SCSS files are created by right clicking the Styles group in the Design panel and choosing the New > SCSS File option. To edit a . scss file, double click it. This will open it in our code editor.

Can I use SCSS in angular?

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.


1 Answers

Angular.io states that:

The main CLI configuration file, angular.json, [...] allows you to replace any file with a target-specific version of that file.

This is in fact the vision, but according to this GitHub thread, this is not true for now.
It seems up till now, only .ts and .html files are supported.

Therefore, currently the answer to the question is no, it is yet not possible to replace SCSS files.


Update Jan-2021: Still doesn't work. Tested with Angular 11.0.9.

TLDR:

  • Angular 11.x now errors on unsupported file types if you try to use the file replacement feature
    (the workaround described below still works, as it doesn't use the file replacement feature)

  • It only has file replacement support for the following types: .cjs, .js, .json, .mjs and, .ts

Background:
It seems the inital statement in the documentaion to support all file types was wrong. With Angular 11 a check was introduced, to error on unsupported file types.

fix(@angular-devkit/build-angular): add validation to fileReplacement…

fileReplacement is meant to replace compilation source files (JavaScript or TypeScript) with other compilation source files in the build. With this change we add validation to fail the build when the files have unsupported extensions.

So with Angular 11 two things changed. At first you have to use src and replaceWith instead of replace and with. Though this doesn't help as you will get Data path ".fileReplacements[1].replace" should match pattern "\.(([cm]?j|t)sx?|json)$"., if you use unsupported file types like .scss.


Update Feb-2020: Still doesn't work. Tested with Angular 9.0.0.


But there is a workaround:
You can use different configurations in angular.json to achieve the same goal - replacing a SCSS file.

folder structure:

src/
    scss/
        default/
            _scss-config.scss
        special/
             _scss-config.scss

src/scss/default/scss-config.scss

body { background-color: blue; }

src/scss/special/scss-config.scss

body { background-color: red; }

angular.json

<!-- language: lang-json -->

{
  [...]
  "architect": {
    "build": {
      "options": {
        "stylePreprocessorOptions": {
          "includePaths": [
            "src/scss/default"
          ]
        }
      },
      "configurations": {
        "default": {
          "stylePreprocessorOptions": {
            "includePaths": [
              "src/scss/default/"
            ]
          }
        },
        "special": {
          "stylePreprocessorOptions": {
            "includePaths": [
              "src/scss/special/"
            ]
          }
        }
      }      
    },
    "serve": {
      "configurations": {
        "default": {
          "browserTarget": "angular-scss-replacement:build:default"
        },
        "special": {
          "browserTarget": "angular-scss-replacement:build:special"
        }
      }
    }     
    [...]      
  }
}

style.scss or component.scss

@import 'scss-config';

/* use your SCSS variables and stuff as you normally would */

Note that you mustn't include the _ (underscore) from the filename in the import statement
(for more details read the Partials section)

How to use it:

// 'ng serve'-command uses default configuration as defined in angular.json > build 
ng serve

// default config creates blue background
ng serve --configuration=default


// specail config create red background
ng serve -c=special

(This solution is from the thread mentioned above - thx to richardtreier)


Drawbacks of this approach:

  • It forces you to have a specific folder structure to separate your different SCSS configurations
  • It might force you to move those folders out of your normal folder structure.
    For example, "includePaths": ["src/scss"] won't work with the folder structure mentioned above, since the SCSS configs can't be loaded separately.
like image 78
jowey Avatar answered Oct 13 '22 13:10

jowey