在组件中包含部分会导致重复的 css

Posted

技术标签:

【中文标题】在组件中包含部分会导致重复的 css【英文标题】:Including partials in components results in duplicate css 【发布时间】:2020-03-13 07:32:28 【问题描述】:

我正在尝试使用 sass 的 @extend,这样我就不会将标记和 html 混合在一起。如this article 中所述。

简而言之,而不是写

<div class="alert alert-primary>This is an alert!</div>

你应该写类似的东西

<div class="banner">This is an alert!</div>
.banner 
    @extend .alert;
    @extend .alert-primary;

这样样式和内容可以很好地分开。

问题:将它与 webpack (sass-loader) 和组件(例如 Vue.js 或 Angular)一起使用时,我运行进入一个问题,现在包含一个引导程序部分将导致整个引导程序文件完全编译到 css 中。 这会为使用部分 bootstrap/scss/_buttons.scss 的每个组件以及在该部分中定义的所有类生成一个类 .btn[data-v-3614b62c] 和另一个 .btn[data-v-45ac961c] 等。 即使我不使用它。

从长远来看,这对应用程序是不利的,因为它的大小会迅速增加,而且我认为浏览器会因为要解析的 css 类太多而变慢。

问题:如何确保 sass 不会复制整个导入的部分? 我可以启用某种只包含我使用的类的摇树吗? 我是否必须更改我的文件结构,以便 sass 了解我只需要部分内部的某些类而不是所有类?


代码示例

这是一个使用 bootstrap 的 vue 组件

<template>
    <form class="form">
        <input type="text" class="input">
        <button class="button-submit">Send</button>
        <button class="button-cancel">Cancel</button>
    </form>
</template>

<style lang="scss" scoped>
@import "node_modules/bootstrap/scss/functions";
@import "node_modules/bootstrap/scss/variables";
@import "node_modules/bootstrap/scss/mixins";
@import "node_modules/bootstrap/scss/root";
@import "node_modules/bootstrap/scss/buttons";

.form 
    .button-submit 
        @extend .btn;
        @extend .btn-primary;
    
    .button-cancel 
        @extend .btn;
        @extend .btn-danger;
    

</style>

这将导致整个部分 _buttons.scss 被编译成 css,而不仅仅是 .form .button-submit.form .button-cancel


现场示例

https://codesandbox.io/embed/musing-feynman-8w2kx.

查看我遇到的问题:

    右键单击右侧的示例,然后单击检查 在“元素”选项卡中,导航到 #document > html > head 在底部有几个 style 元素 其中两个将包含所有按钮 css,其中只有 [data-v-######] 属性不同,最后是我的几行代码。

请注意,生产版本也会发生同样的情况。然后将 css 简单地捆绑在一个文件中,但仍然存在重复项。

【问题讨论】:

【参考方案1】:

如果您将@import 相同的 CSS 规则添加到不同的组件中,那么您将在所有模块中复制相同的规则。这就是它的工作原理。

您应该只是@importing 定义抽象声明(如变量、mixin、函数等)的模块,而不是实际样式。

您可以在全局范围内对样式进行去重的唯一方法是,如果您使用类似 mini-css-extract-plugin 的东西将所有 CSS 提取并组合到一个文件中,然后通过类似 cssnano 的东西运行它,这将丢弃重复的规则 (尽管使用作用域 CSS,这可能行不通)。

模块通常是独立于其他模块构建的,没有简单的方法可以知道规则是否已由前一个模块声明。在开发中,您可能正在使用style-loader,它基于每个模块运行,并根据需要将样式注入网页;如果某个特定样式已经被另一个组件注入,它无法确定应该注入哪些样式。

它变得一团糟;首先不要重复样式,以保持简单。

如果你真的想使用@extend,那么创建一个单独的.scss 文件,这是@imports 引导样式的唯一模块,并在其中定义所有扩展。

【讨论】:

感谢您的回答!关于导入仅包含抽象声明的模块:问题是我找不到任何实际公开功能齐全的占位符或 mixin 的 sass 框架。如果您查看引导程序中.btn 的实现,那里有太多代码而不是简单的@extend %btn,所以我可以使用%btn。其他 sass 框架,如 Bulma 和 Fomantic UI 似乎也这样做。

以上是关于在组件中包含部分会导致重复的 css的主要内容,如果未能解决你的问题,请参考以下文章

在另一个css中包含一个css类[重复]

如何在引导程序 3 中包含字形图标 [重复]

CSS媒体查询和Firefox的滚动条宽度[重复]

Python 3,如果列表中包含特定的东西,如何删除部分元素3 [重复]

确保用户在输入中包含“@”符号[重复]

在每个 foreach 循环迭代中包含重复的刀片模板