Typescript 如何避免在Webpack上重复sass导入(使用@use)

Typescript 如何避免在Webpack上重复sass导入(使用@use),typescript,webpack,import,sass,sass-loader,Typescript,Webpack,Import,Sass,Sass Loader,我想让我的每个自定义元素类文件导入相应的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&qu

我想让我的每个自定义元素类文件导入相应的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);
// 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
                    }
                }]
        }
    ]
},
而我的html文件和webpack.config.js是这样的:

// 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);
// 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
...
//webpack.config.js
...
输出:{
文件名:“app.js”,
path:path.resolve(uu dirname,“public”)
},
决心:{
扩展名:[“.ts”、“.tsx”、“.js”]
},
模块:{
规则:[
{
测试:/\.tsx?$/,,
使用:“ts加载器”,
排除:/node\u模块/
},
{
测试:/\.s[ac]ss$/,,
用法:[“样式加载器”、“css加载器”、“解析url加载器”,
{
加载器:“sass加载器”,
选项:{
sourceMap:false
}
}]
}
]
},
当我在浏览器上打开index.html时,head标记中的样式标记是:

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

p-视图{…}
p-视图{…}
p-滚动条{…}
当我期望它有两个样式标签时,分别有
p-view
selector和
p-scroller
selector

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


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

我找到了一个使用的解决方案

优化css资产网页包插件
丢弃css中的重复选择器。请注意,您必须使用as
优化css资产webpack plugin
来处理样式表。您不能改为使用的原因是,
style loader
在提取脚本中包含的样式表之后立即在目标html中包含绑定的样式表。包括捆绑的样式表可以通过以下方式完成

下面是您的
webpack.config.ts
应该是什么样子。请注意,如果要在
优化
上设置
优化css资产网页包插件
,则必须将
优化
设置为true。还请注意,从Webpack 5中,
Webpack.ConfigurationFactory
被删除

import HtmlWebpackPlugin from "html-webpack-plugin"; // include assets into the target html
import MiniCssExtractPlugin from "mini-css-extract-plugin"; // extract style sheets included in scripts
import OptimizeCssAssetsPlugin from "optimize-css-assets-webpack-plugin"; // discards duplicate selectors in the bundled style sheets from mini-css-extract-plugin

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;