如何防止未使用的 React 组件的样式标签



我认为这个问题可能会扩展到 React 之外,但我仍然不确定 React 本身是否对这个问题负责。

环境是 React with TypeScript。我在组件文件中使用 CSS 导入,以便每个组件都有其特定的样式表,并且我假设在实例化相应的组件之前,这些样式不会添加到<head>元素中。但事实证明,如果我从一个文件中导入一个组件,该文件只是重新导出所有组件,那么我不使用的所有其他组件的样式仍然会添加到 DOM 中。

这是一个简单的例子,假设我在lib文件夹中有两个简单的组件 -AvatarButton.它们看起来像这样(Button相似):

import React from 'react';
import './avatar.css';
const Avatar: React.FC = (props: any) => {
return (
<div className="avatar">
{props.children}
</div>
);
}
export { Avatar };

然后我添加index.ts来重新导出组件,以便获得简单的导入路径:

import { Avatar } from './Avatar';
import { Button } from './Button';
export { Avatar, Button };

最后,在我的AppComponent中,我只想使用Button组件:

import React from 'react';
import { Button } from './lib';
const App: React.FC = () => {
return (
<div className="App">
<Button>example</Button>      
</div >
);
}
export default App;

令我惊讶的是,在<head>元素中,不仅Button,而且Avatar都有<style>标签。为什么会这样?我的再导出配置有误吗?

请注意,如果我直接从其文件导入组件 -import { Button } from './lib/Button'我不会获得Avatar样式。

这个例子真的很简单,但真实的场景与一个 React 组件库有关,它包含很多组件和很多样式表。我想避免在 DOM 中插入这么多<style>标签,除非确实需要它们。

感谢您花时间在这件事上!

以便每个组件都有其特定的样式表,并且我假设在实例化相应的组件之前,这些样式不会添加到元素中

这种假设是错误的。React 使用 webpack 来捆绑其文件,webpack 用于 CSS 导入的方式是它加载项目依赖的所有 CSS 文件,并将它们放在<head>元素中。


你可能会问:那我该如何保持我的风格分开,不要把它们混在一起.
有三种解决方案。

  1. 一个好方法是添加CSS模块样式表
  2. 另一个建议是使包装组件的<div>具有与组件同名的className,以便组件如下所示
export default class ComponentOne extends Component {
...
render() {
return(
<div className="ComponentOne">
...
</div
)
}
}

您的组件 CSS 文件将如下所示:

.ComponentOne div img {
...
}
.ComponentOne .class-one {
...
}

这样,使用像 SASS 这样的 CSS 预处理器就会派上用场,所以你的 .scss 文件将简单地以:

.ComponentOne {
...
}
  1. 另一种解决方案是将样式作为组件中的对象。这样,样式将仅限定为组件的范围,并在组件卸载时删除,但随后您将失去轻松创建@media queriesother special effects like的能力 :hover' 此外,对于过于频繁地挂载和卸载的小型组件,不建议使用此方法,因为一旦应用程序变大,就会产生性能问题

您可能还会问:既然所有的样式表都是在乞讨时导入的,那么我为什么不将所有样式放在一个大样式表中而不将它们拆分。

除了拆分样式将使它们易于处理这一事实之外,每个组件都有其单独的CSS文件,webpack将处理导入它们,还有一个好处:
假设您有一个feature1组件,它也有一个feature1.css文件。一开始,当你在主应用程序中导入 feature1 时,webpack 也会导入它的样式表并将其放在<head>元素中.
但是假设将来你决定不想再使用feature1组件,并且你现在正在使用另一个 feature2 组件,它有自己的feature2.css文件。现在,由于没有其他组件正在导入feature1 组件,webpack 也将忽略将feature1.css导入到<head>元素中。

最新更新