'Conditional compilation using ifdef-loader with Angular 13 and Webpack?

I have an Ionic application that relies heavily on conditional compilation where I include or exclude blocks of code based on a set of config values similar to how m4 works.

I had been using https://github.com/nippur72/ifdef-loader successfully for this purpose.

I am now faced with upgrading this app from Angular 10 to 13 (Ionic 5 to 6).

ifdef-loader did not work out of the box with Angular 10 but a patch (https://gist.github.com/tristanidoux/892469f2c345bd6c6551eb19c705a016) to @angular-dev-kit allowed it to run.

This patch does not work with Angular 13 as all the files have changed and crawling through as much of the source as I can I don't yet see how to create a similar patch for Angular 13.

So I have been attempting to use "@angular-builders/custom-webpack": "^13.0.0" using https://medium.com/angular-in-depth/customizing-angular-cli-build-an-alternative-to-ng-eject-v2-c655768b48cc as a guide.

I have the following custom.webpack.config.js file modeled on the ifdef-loader documentation:

// ifdef-loader config

const opts = {
   APP: false,
   WEB: true,
   DEBUG: true,
   version: 3,
   "ifdef-verbose": true,                 // add this for verbose output
   "ifdef-triple-slash": true,           // add this to use double slash comment instead of default triple slash
   "ifdef-fill-with-blanks": true,         // add this to remove code with blank spaces instead of "//" comments
   "ifdef-uncomment-prefix": "// #code "  // add this to uncomment code starting with "// #code "
};

module.exports = {
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: [
          { loader: 'ts-loader' },
          { loader: 'ifdef-loader', options: opts }
        ]
      }
    ]
  },

Unfortunately, this does not work as it appears ifdef-loader is not getting invoked.

So three questions:

  1. Am I making some obvious mistake in my config?

  2. Has anyone gotten ifdef-loader working with Angular 13? If so, how?

  3. Alternatively, is there some other solution for conditionally including/excluding blocks of code in an Angular 13 project?

Any pointers or suggestions would be greatly appreciated.



Solution 1:[1]

After a week, I have been unable to determine how to insert a module into the typescript compilation pipeline in Angular's webpack implementation so I opted to create a patch for @angular-devkit/build-angular/@ngtools/webpack to call ifdef-loader directly.

Patch here: Angular Webpack Patch

It's ugly but it works.

Solution 2:[2]

If export webpack configuration as function from webpack.config.js it's works:

module.exports = (config, options, targetOptions) => {
    const ifdef_opts = {
        DEBUG: config.mode === 'development',
        version: 3,
        "ifdef-verbose": true,                 // add this for verbose output
        "ifdef-triple-slash": false,           // add this to use double slash comment instead of default triple slash
        "ifdef-fill-with-blanks": true,         // add this to remove code with blank spaces instead of "//" comments
        "ifdef-uncomment-prefix": "// #code "  // add this to uncomment code starting with "// #code "
    };
    config.module.rules.some(({test, use}) => {
        if (use && test && 'dummy.ts'.match(test)) {
            use.push({
                loader: "ifdef-loader",
                options: ifdef_opts
            })
            return true;
        }
        return false;
    })

    return config;
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Yermo Lamers
Solution 2 alezhu