angulartypescriptwebpacksasswebpack-loader

Override angular loaders for specific files


We have a codebase that was created using angular, which uses the angular cli and it's default webpack config. However, we are starting to move away from angular and towards webcomponents. In order to use scss within our webcomponent ts files, we created a new webpack loader in which we add the correct scss file as a dependency, wait for the compiled css from sass-loader and insert it into our ts file using a string replace.

This works fine in a normal webpack environment. However, angular also processes the scss files, by using a few different loaders. Because of this, the scss file no longer contains actual scss, but javascript. This is still needed for our other scss files, but not for the ones ending in .webcomponent.scss.

How can I tell angular to stop using it's default loaders for my *.webcomponent.scss files?

My extra-webpack-config.js looks like this:

module.exports = {
    module: {
        rules: [
            {
                test: /\.webcomponent\.ts$/,
                use: [
                    {
                        loader: './webcomponent-loader.js'
                    }
                ]
            },
            {
                test: /\.webcomponent\.scss$/,
                use: [
                    {
                        loader: 'sass-loader'
                    }
                ]
            }
        ]
    }
};

And my angular.json has the following custom webpack config:

"customWebpackConfig": {
    "path": "./extra-webpack.config.js",
    "mergeStrategies": {
        "module": "prepend",
        "loaders": "replace"
    }
}

Within the webcomponent-loader I use

this.addDependency(this.resourcePath.replace(/.ts$/, '.scss'));

This gives me the following error:

Invalid CSS after "module.exports": expected selector, was '= "/*Colors*/\\n/*Bl'

This tells me angular converted it to js code. Any help is greatly appreciated.


Solution

  • Eventually I was able to override the default loaders using the following extra-webpack.config.js:

    module.exports = (config, options) => {
        config.module.rules.forEach(rule => {
            if (rule.test.exec('.scss')) {
                rule.test = new RegExp('(?<!\.webcomponent)(' + rule.test.source + ')');
            }
        });
    
        config.module.rules.push({
            test: /\.webcomponent\.ts$/,
            use: [
                {
                    loader: './webcomponent-loader.js'
                }
            ]
        },
        {
            test: /\.webcomponent\.scss$/,
            use: [
                {
                    loader: './identity-loader.js'
                },
                {
                    loader: 'sass-loader'
                }
            ]
        });
    
        return config;
    };
    

    Basically I take the old config and edit the test regex to use a negative lookbehind to exclude my files. Then I add my own loaders to the config rules. I still have problems getting my css, but that is another issue for which I will post a new question.