用 Baseline 让 Web 功能兼容性判断变得简单

151 阅读5分钟

在前端开发中,我们经常会遇到这样的问题:某个 Web 平台功能到底什么时候才能放心使用?Baseline 为团队提供了一个简单的答案。不用再纠结各种浏览器版本矩阵,只需要关注一个共享的功能级别基准线,就能做出一致且有理有据的决策。

从业务角度看,这个问题其实很关键。如果用户的浏览器悄无声息地缺少某个你依赖的功能,可能会导致转化率下降、产生不必要的客服工单,还会在无形中损害用户信任,而你甚至都不知道问题出在哪里。把 Baseline 作为产品标准可以有效降低这种风险,让原本模糊且反复出现的争论变成可以文档化、审计和自动执行的策略。

Baseline 快速入门

Baseline 追踪某个功能何时在四大主流浏览器引擎(Safari、Chrome、Edge 和 Firefox)中达到一致支持。它通过三个阶段来表示功能的就绪状态:

受限可用(Limited availability)
还没有在所有 Baseline 浏览器中得到支持,应该视为实验性功能。除非有完善的降级方案,否则避免在生产环境使用。

Baseline Widely Available

新近可用(Newly available)
在所有当前稳定版本中都已支持,可以作为谨慎早期采用的默认选择。

Baseline Newly available

广泛可用(Widely available)
新近可用状态持续 30 个月后的状态,实际使用风险极低。

Image description

你也可以按年份来设定目标。比如选择"2023"意味着:允许使用 2023 年或更早成为 Baseline 新近可用的所有功能。

这是一种以功能为先的视角。不再纠结于每个浏览器的版本列表,而是直接问"这个功能达到基准线了吗?"然后得到一个明确的答案。

如何选择适合团队的 Baseline

建议从 Widely 作为默认选项开始。这是一个保守且低摩擦的起点,因为它在通用支持落地后还考虑了实际采用时间。

接下来需要评估"我们的年份"。通过分析工具或 RUM 数据了解用户实际使用的浏览器情况。尝试不同的年份(2021、2022、2023...)并评估覆盖率。如果你使用 Google Analytics,Google Analytics Baseline Checker 可以帮你可视化这些数据;如果没有,也可以用内部日志进行类似的分析。

Image description

最后要定义例外策略。有些功能配合合理的降级方案可以立即发布并逐步增强,而有些功能的跨浏览器风险较大,即使技术上已经达到 Widely 状态也应该等待。把例外情况的提议、审查和文档化流程都写下来。

这个流程(安全默认值、基于数据的调整、明确的例外)让策略清晰明了,决策过程也有据可循。

为什么不只依赖 UA 表?

User-Agent 字符串很容易被伪造,经常被爬虫和扫描器污染。即使准确,版本标签也无法反映企业策略、功能标志或可能禁用某些功能的安全模式。基于 UA 的策略还迫使你管理版本矩阵,这些矩阵很快就会过时,而且很难清晰地映射到规范如何组织功能。

Baseline 直接在功能层面划线。保留 UA 数据用于覆盖率评估和与利益相关者沟通,但让功能本身驱动决策。

将 Baseline 融入工作流程

首先,设置构建和转译目标以匹配你选择的 Baseline。有些工具默认就是 Widely;其他工具允许你将 Baseline 转换为 Browserslist 查询或 esbuild 目标。目标是让你发布的代码与约定的基准线保持一致。

其次,在问题发生的地方就捕获它们:在编辑器和 CI 中。ESLint 可以为 JavaScript 强制执行 Baseline,配套插件可以对 CSS 和 HTML 做同样的事情。当有人使用超出基准线的功能时,他们会在代码合并前看到精确且可操作的提示信息。

Image description

第三,文档化策略。明确默认值(比如"Widely")、如何设定年份以及例外如何处理。这将部落规范转变为代码化的策略,让新人也能保持一致。

实际案例:避免使用 Date#getYear()/setYear()

Date#getYear()Date#setYear() 已被弃用,它们也低于合理的 Baseline 阈值。使用它们很容易引入难以察觉的 bug。

启用 Baseline 规则后,你会看到这样的提示:

Image description

一个策略,三个层面:JS、CSS 和 HTML

让团队真正采用 Baseline 的最简单方法是在编写代码的地方启用它。JavaScript 是显而易见的起点,但将 CSS 和 HTML 纳入同一个体系会让你的策略更加连贯。

这是一个 Flat Config 的示例,将三者整合在一起。根据你的仓库调整文件匹配模式和严格程度。

// eslint.config.js
import baselineJSPlugin from "eslint-plugin-baseline-js";
import cssPlugin from "@eslint/css";
import htmlPlugin from "@html-eslint/eslint-plugin";
import htmlParser from "@html-eslint/parser";

export default [
  // JavaScript/TypeScript: Baseline
  {
    files: ["**/*.{js,ts,jsx,tsx,mjs,cjs}"],
    plugins: { "@baseline-js": baselineJSPlugin },

    rules: {
      "@baseline-js/use-baseline": [
        "error",
        {
          baseline: "widely",
          ignoreFeatures: [],
          ignoreNodeTypes: [],
        },
      ],
    },
  },
  // CSS: Baseline
  {
    files: ["**/*.{css,scss}"],
    plugins: {
      "@css": cssPlugin,
    },
    language: "@css/css",
    rules: {
      "@css/use-baseline": ["warn", { available: "widely" }],
    },
  },

  // HTML: Baseline
  {
    files: ["**/*.{html,htm}"],
    plugins: { "@html-eslint": htmlPlugin },
    languageOptions: { parser: htmlParser },
    rules: {
      "@html-eslint/use-baseline": ["warn", { available: "widely" }],
    },
  },
];

相关插件:

结语

Baseline 是一种对现实达成共识的方式。选择一条基准线,展示你的依据,让工具帮你守住它。这就是团队如何在不拿用户体验冒险的情况下快速前进的方法。