我第一次使用 React 和 Webpack 尝试 CSS 模块,我发现了至少三种方法来实现它:
我使用
babel-plugin-react-css-modules
来平衡代码简单性和性能,一切似乎都工作正常,除了一件事:我的第 3 方库(Bootstrap 和 Font Awesome)也包含在 CSS 模块转换中。
<NavLink to="/about" styleName="navigation-button"></NavLink>
上面将正确转换的
className
分配给 NavLink
。然而,内部的 span
需要引用全局样式才能渲染图标。
<span className="fa fa-info" />
上面的跨度没有分配一个转换后的
className
,这是预期的,但是我的捆绑样式表没有这些CSS类,因为它们被转换成其他东西,以模拟本地范围。
以下是我的
.babelrc
文件中用于激活babel-plugin-react-css-modules
的内容:
{
"presets": ["env", "react"],
"plugins": [
["react-css-modules", {
"generateScopedName": "[name]__[local]___[hash:base64:5]",
"filetypes": {
".less": {
"syntax": "postcss-less"
}
}
}]
]
}
在我的 Webpack 配置中,以下是配置
css-loader
进行转换的部分:
{
test: /\.(less|css)$/,
exclude: /node_modules/,
use: extractCSS.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
minimize: true,
modules: true,
sourceMap: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
{
loader: 'less-loader'
}
]
})
}
据我所知,上述规则应该排除库样式表,我还尝试专门为排除的样式表添加另一个规则,但这似乎不起作用,因为我猜这些样式表仍然使用原始规则进行了转换.
为了从两个库导入 CSS,我的父样式表中有以下两行声明了一些全局样式:
@import '../../../node_modules/bootstrap/dist/css/bootstrap.min.css';
@import '../../../node_modules/font-awesome/css/font-awesome.min.css';
我发现下面这两种方法可能会有所帮助:
简而言之,到目前为止,似乎没有选项可以忽略/排除某些路径被 css-modules webpack 插件模块化。理想情况下,插件应该支持它,但您可以尝试以下一些方法:
使用两个 webpack 规则来利用 webpack 规则排除/包含:
module.exports = {
rules: [
{
test: /\.css$/,
exclude: /node_modules/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path]__[local]___[hash:base64:5]',
},
},
],
},
{
test: /\.css$/,
include: /node_modules/,
use: ['style-loader', 'css-loader']
}
]
}
...或者,从上面的第二个答案中注入 webpack 的 getLocalIdent 来手动排除某些路径。
const getLocalIdent = require('css-loader/lib/getLocalIdent');
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]',
getLocalIdent: (loaderContext, localIdentName, localName, options) => {
return loaderContext.resourcePath.includes('semantic-ui-css') ?
localName :
getLocalIdent(loaderContext, localIdentName, localName, options);
}
}
}
对我来说使用
:global
有效:
.my-component {
:global {
.external-ui-component {
padding: 16px;
// Some other styling adjustments here
}
...
}
}
Ps:要使用 webpack 配置来完成此操作,请参阅另一个答案。
{
loader: 'css-loader',
options: {
modules: {
auto: (resourcePath) => !resourcePath.includes('node_modules'),
localIdentName: '[name]__[local]__[hash:base64:5]',
},
},
},
更新(2024 年):
CSS 加载器 getLocalIdent 的 文档有:
允许指定一个函数来生成类名。默认情况下我们 使用内置函数生成类名。 如果定制 函数返回 null 或未定义,我们回退到内置函数 函数生成类名。
因此,自定义 getLocalIdent 函数可以执行所需的过滤器以选择返回
localName
,然后仅返回 null 以回退到内置函数。
然后更新@GasaiYuno的第二个答案:
getLocalIdent: (loaderContext, localIdentName, localName, options) => {
return loaderContext.resourcePath.includes('semantic-ui-css') ?
localName :
null;
}