CSS_PREFIX_FIX.md 4.4 KB

LabelStudio CSS 前缀问题修复

问题描述

LabelStudio 编辑器加载后,所有样式都没有生效:

  • 标签按钮没有颜色
  • 按钮没有边框和背景
  • 面板和侧边栏样式缺失
  • 整体看起来像是没有加载 CSS

问题根源

LabelStudio 使用 CSS 模块BEM 命名约定,所有的 CSS 类名都需要添加 lsf- 前缀。

技术细节

  1. CSS 模块处理

    • LabelStudio 的 SCSS 文件使用 CSS 模块
    • 例如:.label 类名需要被转换为 .lsf-label
  2. Webpack 配置

    • 根目录的 web/webpack.config.js 有特殊的 CSS 模块配置
    • 它会给所有非 .module.scss 的 SCSS 文件添加 lsf- 前缀
  3. 我们的问题

    • lq_label 应用的 webpack 配置没有这个处理
    • 导致 LabelStudio 的样式类名没有前缀
    • 浏览器中的 HTML 元素有 lsf-label 类名
    • 但 CSS 文件中只有 .label 选择器
    • 两者不匹配,样式无法应用

解决方案

web/apps/lq_label/webpack.config.js 中添加 CSS 模块配置,模仿根目录的配置:

const css_prefix = 'lsf-';

// 在 plugins 中添加
new webpack.DefinePlugin({
  'process.env.CSS_PREFIX': JSON.stringify(css_prefix),
}),

// 配置 CSS 模块
config.module.rules.forEach((rule) => {
  const testString = rule.test?.toString() || '';
  const isScss = testString.includes('scss');
  const isCssModule = testString.includes('.module');

  if (rule.test?.toString().match(/scss|sass/) && !isCssModule) {
    const r = rule.oneOf?.filter((r) => {
      if (!r.use) return false;
      const testString = r.test?.toString() || '';
      if (testString.match(/module|raw|antd/)) return false;
      return testString.match(/scss|sass/) && r.use.some((u) => u.loader && u.loader.includes('css-loader'));
    });

    r?.forEach((_r) => {
      const cssLoader = _r.use.find((use) => use.loader && use.loader.includes('css-loader'));
      if (!cssLoader) return;

      const isSASS = _r.use.some((use) => use.loader && use.loader.match(/sass|scss/));
      if (isSASS) _r.exclude = /node_modules/;

      if (cssLoader.options) {
        cssLoader.options.modules = {
          localIdentName: `${css_prefix}[local]`, // 添加 lsf- 前缀
          getLocalIdent(_ctx, _ident, className) {
            if (className.includes('ant')) return className;
          },
        };
      }
    });
  }
});

关键点

  1. CSS_PREFIX 环境变量

    • 定义为 'lsf-'
    • LabelStudio 代码中会使用这个变量
  2. localIdentName 配置

    • 格式:lsf-[local]
    • .label 转换为 .lsf-label
  3. 排除规则

    • 不处理 .module.scss 文件(已经有自己的命名)
    • 不处理 node_modules
    • 保留 ant 开头的类名(Ant Design 组件)

验证方法

1. 检查 HTML 元素

打开浏览器开发者工具,检查一个标签按钮:

<div class="lsf-label lsf-label_selected">Positive</div>

2. 检查 CSS 文件

在 Network 标签中找到 libs_editor_src_index_js.css,搜索:

.lsf-label {
  /* 样式定义 */
}

3. 验证样式应用

  • 标签按钮应该有颜色和边框
  • 悬停时应该有效果
  • 选中时应该有不同的样式

重启服务器

重要:修改 webpack 配置后,必须重启开发服务器:

# 停止当前服务器 (Ctrl+C)
# 重新启动
cd web
yarn nx serve lq_label

参考

相关问题

如果样式还是不显示,检查:

  1. 浏览器缓存

    • 硬刷新(Ctrl+Shift+R)
    • 清除缓存
  2. CSS 文件加载

    • 检查 Network 标签
    • 确认 libs_editor_src_index_js.css 已加载
    • 检查文件大小(应该是几 MB)
  3. 类名匹配

    • HTML 元素的类名应该以 lsf- 开头
    • CSS 文件中的选择器也应该以 lsf- 开头
  4. Webpack 配置

    • 确认 css_prefix 变量定义正确
    • 确认 CSS 模块配置已添加
    • 确认服务器已重启

总结

这个问题的核心是 CSS 模块的类名转换。LabelStudio 依赖特定的 webpack 配置来正确处理 CSS 类名,我们需要在自己的应用中复制这个配置。

修复后,LabelStudio 编辑器应该完全正常工作,所有样式都会正确显示!