[英]Detect use of non-existent classNames in CSS Modules/React
在我的反应项目中,如果我使用 css 模块文件中的一些不存在的类名,
// mycss.modules.scss
.thing { color: red }
// index.jsx
import styles from mycss.modules.scss
<div className={styles.otherThing}>Some div</div>
// Browser would return:
<div>Some div</div>
它悄悄地失败了,却没有让我知道这个 class 不存在。 如何检查此 class 名称是否存在并引发错误。 保存文件时,在构建期间收到错误会很棒。
如果您对 typescript 解决方案持开放态度,我为您找到了一个 TS 插件。
它可以使用可用密钥的类型信息填充styles
object。
您不必将整个项目切换到 typescript,您可以在此文件顶部添加// @ts-check
指令以启用 TS 引擎设计时检查。
除非您想提出拉取请求以向 webpack 加载程序本身添加诸如严格模式选项之类的东西,否则我认为您无能为力,因为它只是一个基本的 object。 一个简单的替代方法是只做styles.styleName.toString()
,这样如果styleName
未定义,它将引发错误。
实际上在 javascript 代码中是可能的。 但我认为 className 存在检查不是一个好主意。
document.styleSheets[].rules[].selectorText
将此 function 添加到顶部:
// index.jsx
import styles from mycss.modules.scss
function strictStyles (clsName){
if(styles[clsName]){
return styles[clsName]
}else{
throw "CSS class doesn't exist";
}
}
...
<div className={strictStyles(otherThing)}>Some div</div>
...
注意:此解决方案不需要您更改任何代码,只需添加加载程序,它应该可以开箱即用。 请注意最后关于生产版本的警告,或查看源代码以获取 Github 的完整说明。
我创建了一个与 CSS/LESS/其他 CSS 模块加载器一起使用的 Webpack 加载器。
对于那些只想将加载器添加到他们的项目的人,可以像这样使用它:
在某处添加此 webpack 加载程序源文件,例如/webpack/loaders/css-module-proxy.js
/**
* A CSS/LESS/Style module loader that prepends a proxy in non-production builds.
*
* The proxy checks if the loaded style module actually contains the style we are trying to fetch.
* If it doesn't exist (its accessor returns undefined), we crash on debug (non-production) builds!
*
* Inspired by https://github.com/royriojas/css-local-loader
*/
module.exports = function cssLocalLoader(source, map) {
this.cacheable();
if (process.env.NODE_ENV !== "production") {
// noMatch:
// Makes sure that any access prefixed with underscore are filtered out
// otherwise it will crash at runtime when Webpack is probing the locals export.
// toJsonMatch:
// Makes sure that toJSON access on the locals object gets proxied to the correct
// toJSON function.
const requireWrapper = `
// If the access matches this regexp, skip it
const oldLocals = exports.locals;
const noMatch = /^[_]+/;
const toJsonMatch = /^toJSON$/;
const proxy = new Proxy(oldLocals, {
get: function(target, name) {
if (noMatch.test(name)) {
return undefined;
}
if (toJsonMatch.test(name)) {
return oldLocals.toJSON;
}
const clz = target[name];
if (clz === undefined) {
throw new Error("Error: LESS / CSS class named \\"" + name + "\\" does not exist");
}
return clz;
}
});
exports.locals = proxy;
`;
const newSource = `${source}\n\n${requireWrapper}`;
this.callback(null, newSource, map);
} else {
this.callback(null, source, map);
}
};
然后从您的 webpack 配置中使用它,下面的示例用于 LESS:
{
test: /\.module\.less$/,
use: [
{ loader: path.resolve("webpack/loaders/css-module-proxy.js") },
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 1,
localIdentName: "[name]__[local]__[hash:base64:5]",
},
},
{ loader: "less-loader" },
],
},
不要忘记使用NODE_ENV=production
构建您的发布代码,否则它可能会在用户访问您的站点时崩溃...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.