如何避免Webpack上重复的sass导入使用@use

问题描述

我想让每个自定义元素类文件导入相应的sass文件,该文件又导入其他sass文件以继承其超类的样式,如下所示:

// View.scss
@mixin view { ... }
p-view { @include view; }

// View.ts
import "./View.scss";
export default class View extends HTMLElement { ... }
customElements.define("p-view",View);

// Scroller.scss
@use "View" as *;
@mixin scroller {
    @include view;
    ...
}
p-scroller { @include scroller; }

// Scroller.ts
import "./Scroller.scss";
import View from "./View";
export default class Scroller extends View { ... }
customElements.define("p-scroller",Scroller);

我的html文件和webpack.config.js如下:

// index.html
...
<body>
    <script src="app.js"></script>
</body>

// webpack.config.js
...
output: {
    filename: "app.js",path: path.resolve(__dirname,"public")
},resolve: {
    extensions: [".ts",".tsx",".js"]
},module: {
    rules: [
        {
            test: /\.tsx?$/,use: "ts-loader",exclude: /node_modules/
        },{
            test: /\.s[ac]ss$/,use: ["style-loader","css-loader","resolve-url-loader",{
                    loader: "sass-loader",options: {
                        sourceMap: false
                    }
                }]
        }
    ]
},

当我在浏览器中打开index.html时,head标签中的样式标签为:

<style>
    p-view { ... }
</style>
<style>
    p-view { ... }
    p-scroller { ... }
</style>

当我期望它具有两个分别带有p-view选择器和p-scroller选择器的样式标签

我可以通过删除ts文件中的scss导入并导入一个导入其他scss文件的scss文件解决此问题,但是我想像上面向您展示的那样实现该项目。

我的sass依赖项是"sass": "^1.26.11"。其他依赖项是众所周知的最新模块。

解决方法

我找到了一个使用mini-css-extract-pluginoptimize-css-assets-webpack-plugin的解决方案,由于mini-css-extract-plugin而不能使用样式加载器。要突破这一点,您可能需要使用html-webpack-plugin

optimize-css-assets-webpack-plugin丢弃CSS中的重复选择器。即使您不希望在开发过程中使用任何最小化程序来提高可读性,也必须使用optimize-css-assets-webpack-plugin似乎可以通过钩住mini-css-extract-plugin的加载程序来使用。请注意,如果您将optimize-css-assets-webpack-plugin放在Optimization.minimizer属性中,则webpack-dev-server将不会应用该插件。

您的webpack.config.ts应该是这样的:

import HtmlWebpackPlugin from "html-webpack-plugin"; // bundles assets into one html file
import MiniCssExtractPlugin from "mini-css-extract-plugin"; // minimizes css files
import OptimizeCssAssetsPlugin from "optimize-css-assets-webpack-plugin"; // removes duplicate selectors in css files by hooking mini-css-extract-plugin loader

const factory: Webpack.ConfigurationFactory = (env,args): Webpack.Configuration => {
    const config: Webpack.Configuration = {
        ...
        plugins: [
            new MiniCssExtractPlugin({
                filename: "app.css",}),new OptimizeCssAssetsPlugin(),// if you put it in optimization.minimizer property,webpack-dev-server won't apply it.
            new HtmlWebpackPlugin({
                filename: "index.html",// relative to output.filename
                template: "src/index.html"
            })
        ],module: {
            rules: [
                {
                    test: /\.s[ac]ss$/,use: [
                        MiniCssExtractPlugin.loader,// won't use style-loader
                        "css-loader","resolve-url-loader","sass-loader"
                    ]
                }
            ]
        },};

    return config;
};

export default factory;

您需要将<link rel="stylesheet" href="app.css">放在html文件中。