Correctly define Angular Material theme Angular 11 with PurgeCSS

588 views Asked by At

I recently upgraded to Angular 11 and I have integrated in my process the PurgeCSS plugin https://purgecss.com/ which works fine. Now I'm integrating Angular Material 11 and I'd like to customize the theme. Following the steps from here: https://material.angular.io/guide/theming I created a new file called theme.scss which I included in my angular.json where the styles.scss is (pasting the architect part):

"architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "outputPath": "dist",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": false,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "node_modules/@fortawesome/fontawesome-svg-core/styles.css",
              "src/styles.scss",
              "src/theme.scss",
            ],
            "scripts": [],
            "customWebpackConfig": {
              "path": "webpack.config.js"
            }
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                }
              ]
            }
          }
        },

the theme.scss file looks like this just for testing:

@import '@angular/material/_theming.scss';
// Plus imports for other components in your app.

// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat-core();

// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);

// The warn palette is optional (defaults to red).
$candy-app-warn:    mat-palette($mat-red);

// Create the theme object. A theme consists of configurations for individual
// theming systems such as `color` or `typography`.
$candy-app-theme: mat-light-theme((
  color: (
    primary: $candy-app-primary,
    accent: $candy-app-accent,
    warn: $candy-app-warn,  
  )
));

// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($candy-app-theme);

Note that I tried @import '@angular/material/_theming.scss'; and @import '~@angular/material/theming'; but I got errors. The current error I have is:

ERROR in ./src/theme.scss (./node_modules/css-loader/dist/cjs.js??ref--13-1!./node_modules/postcss-loader/src??embedded!./node_modules/resolve-url-loader??ref--13-3!./node_modules/sass-loader/dist/cjs.js??ref--13-4!./node_modules/postcss-loader/src??postcss!./src/theme.scss)
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Undefined mixin.
     ╷
3593 │   @include cdk-a11y();
     │   ^^^^^^^^^^^^^^^^^^^
     ╵
  src\theme.scss 3593:3  mat-core()
  src\theme.scss 3715:1  root stylesheet

Which points me to the postcss loader configuration. The webpack configuration I have for the angular project build:

const purgecss = require('@fullhuman/postcss-purgecss')({

    // Specify the paths to all of the template files in your project
    content: [
      './src/**/*.html',
    ],
    whitelistPatterns: [/^modal/, /^ngb-dp/, /^dropdown-menu/],
  
    // Include any special characters you're using in this regular expression
    defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
});

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        loader: 'postcss-loader',
        options: {
          ident: 'postcss',
          syntax: 'postcss-scss',
          plugins: () => [
            require('postcss-import'),
            purgecss,
            require('autoprefixer'),
          ]
        }
      }
    ]
  }
};

I recently updated my dev dependencies in case something was missing or old. The actual section of the packages.json is:

"devDependencies": {
    "@angular-builders/custom-webpack": "10.0.1",
    "@angular-devkit/build-angular": "0.1100.2",
    "@angular/cli": "11.0.1",
    "@angular/compiler-cli": "11.0.0",
    "@angular/language-service": "11.0.0",
    "@nguniversal/builders": "11.0.0",
    "@fullhuman/postcss-purgecss": "3.0.0",
    "@types/express": "4.17.3",
    "@types/node": "12.11.1",
    "@types/jasmine": "~3.6.0",
    "@types/jasminewd2": "2.0.6",
    "postcss-scss": "3.0.4",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.0.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-loader": "8.0.11",
    "ts-node": "9.0.0",
    "tslint": "~6.1.0",
    "typescript": "4.0.5"
  }

The sass-loader it seems to be installed is:

"_requiredBy": [
    "/@angular-builders/custom-webpack/@angular-devkit/build-angular"
  ],
  "_resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.0.1.tgz",

At this point I think I have tried many possibilities for the theme configuration, inside the styles.scss , as an additional file, using different versions of the loader...but it seems that I'm missing something fundamental or that I need to reconfigure my webpack file to allow both the purge css as well as the theme integration.

Any insights will be really appreciated.

0

There are 0 answers