Search code examples
typescriptwebpackimportsasssass-loader

How to avoid duplicate sass imports(using @use) on Webpack


My sass modules can import each other like below.

// LinearLayout.scss
@mixin LinearLayout { ... }
linear-layout { @include LinearLayout; }

// ScrollView.scss
@use "LinearLayout" as *;
@mixin ScrollView {
    @include LinearLayout;
    ...
}
scroll-view { @include ScrollView; }

And because each sass module ends up in the bundled css file by being imported in scripts, the bundled css file contains duplicate css selectors.

How can I remove the duplicates?


Solution

  • Common requirement under both Webpack versions

    I haven't dug about this, but it seems both plugins work in a specific webpack bundling lifecycle which is made by mini-css-extract-plugin. So you can't use style-loader, and the thing that was done by it can be done by html-webpack-plugin.

    The below is how your webpack.config.ts should be like. Note that you set optimization.minimize as true to make it run also in development.

    import type Webpack from "webpack";
    import HtmlBundler from "html-webpack-plugin";
    import CssExtractor from "mini-css-extract-plugin";
    
    // webpack@5
    import CssMinimizer from "css-minimizer-webpack-plugin";
    // under webpack@5
    import CssMinimizer from "optimize-css-assets-webpack-plugin";
    
    const config: Webpack.Configuration = {
        ...
        plugins: [
            new HtmlBundler({
                template: "yourHtmlTemplate.html"
            });
            new CssExtractor({
                filename: "outputCssFilename.css",
            }),
        ],
        module: {
            rules: [
                {
                    test: /\.s[ac]ss$/,
                    use: [
                        CssExtractor.loader,
                        "css-loader",
                        "resolve-url-loader",
                        "sass-loader",
                    ]
                },
            ],
        },
        optimization: {
            minimize: true, // set true to run minimizers also in development
            minimizer: [
                new CssMinimizer(),
            ],
        },
    };
    
    export default config;