AI编码助手确实能为开发人员节省大量时间——不过,直到你查看生成的代码时,才会发现它们使用的编程模式仍然属于2019年的水平。

举个例子,让这样的助手生成一个工具提示框:HTML代码看起来很规范,CSS过渡效果也很流畅,`aria-describedby`属性的设置也完全正确。但当你看到JavaScript代码时,就会发现问题——其中使用了`js-hidden`类来实现显示/隐藏功能,还定义了`dismissAllTooltips()`函数以及触摸事件处理程序等等。这些设计虽然能够满足某些需求,但实际上是借助CSS来弥补AI助手在某些方面的不足。

这并不是说AI助手本身出了问题,而是它们只会使用那些在训练数据中出现的常见编程模式,而尽管浏览器多年来已经提供了更先进的解决方案。

“现代Web指导系统”是谷歌Chrome提供的开源解决方案。该系统会将经过专家审核、且符合当前Web标准的指导信息直接融入AI助手的工作流程中,从而帮助它们遵循最新、最实用的技术规范进行开发。

在本文中,你将了解到为什么“现代Web指导系统”能够有效解决“旧代码模式”的问题,以及如何将其应用到自己的工作中,以获得始终符合最新标准的开发结果。

目录:

为什么AI助手会默认使用旧代码模式?

所有大型语言模型都是从互联网上学习知识的,而互联网的发展速度极其迅速。新的浏览器API在正式推出后,往往需要数年时间才能有足够的教程、Stack Overflow上的解答以及实际应用案例被纳入训练数据中。

因此,即使某个模型已经被训练成知道某些现代API的存在,但由于它在训练过程中接触过数千次旧有的编程方式,而新方法只被使用过几次,所以当它生成代码时,仍然会优先选择旧的模式。这并不是因为模型不了解新技术,而是因为对于旧方法的训练信号更为强烈。

单纯的提示并不能完全解决这个问题。让AI助手“使用现代API”确实能起到一定的引导作用,但它们仍然需要那些经过专家审核的实现方案才能自信地编写出符合现代标准的代码。否则,开发者就需要在每次开发过程中都手动添加相关的文档说明,这样的工作量是巨大的。

下面通过一个实际例子来说明这个问题:为了测试其效果,我在没有安装“现代Web指导系统”的情况下,让Antigravity IDE生成了两个独立的组件。

在现代Web指南之前的实现:工具提示组件

任务要求: “开发一个工具提示组件,当鼠标悬停在按钮上时,该组件会出现在按钮上方。”

相关的HTML代码设计得相当合理。CSS通过`position: absolute`来控制组件的定位效果,还实现了不透明度的动画效果,并正确地使用了`role=”tooltip”`和`aria”description”`属性。接下来就是JavaScript部分的代码了:


// ❌ 在现代Web指南之前的实现——一个完全用JavaScript构建的交互管理层
document.addEventListener('DOMContentLoaded', () => {
  const containers = document.querySelectorAll('.tooltip-container');

  containers.forEach(container => {
    const trigger = container.querySelector('.tooltip-trigger');
    const tooltip = container.querySelector('.tooltip-content');

    const forceHide = () => tooltip.classList.add('js-hidden');
    const resetVisibility = () => tooltip.classList.remove('js-hidden');

    // 使用Escape键关闭工具提示
    trigger.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') { forceHide(); e.preventDefault(); }
    });

    trigger.addEventListener('blur', resetVisibility);
    container.addEventListener('mouseleave', resetVisibility);
    container.addEventListener('mouseenter', resetVisibility);

    // 触屏设备上的交互处理
    trigger.addEventListener('touchstart', (e) => {
      const isVisible = !tooltip.classList.contains('js-hidden') && getComputedStyle(tooltip).visibility === 'visible';
      if (isVisible) { forceHide(); } else { dismissAllTooltips(); resetVisibility(); }
    }, { passive: true });
  });

  function dismissAllTooltips() {
    document.querySelectorAll('.tooltip-content').forEach(t => t.classList.add('js-hidden'));
  }

  document.addEventListener('click', (e) => {
    if (!e.targetclosest('.tooltip-container')) {
      document.querySelectorAll('.tooltip-content').forEach(t => t.classList.remove('js-hidden'));
    }
  });
});

问题并不在于上述代码有错误——其实完全没有,这些代码是可以正常运行的。问题在于这种实现方式暴露出了一些本质性问题:由于CSS中的`:hover`和`:focus-within`选择器无法处理使用Escape键关闭工具提示、通过触摸操作切换显示状态,或者点击按钮外部的情况,因此开发者不得不另外编写JavaScript代码来管理工具提示的状态。这样一来,工具提示的显示状态就被分成了两个系统来处理,而这两个系统必须保持同步。`js-hidden`这个类的存在,正是为了让JavaScript能够覆盖CSS的设置。

如果你现在感兴趣的话,可以继续阅读在安装了现代Web指南之后,更新后的工具提示组件代码

接下来,让我们看看在没有现代Web指南的情况下,开发者是如何实现toast通知功能的。

在现代Web指南之前的实现:带有退出动画的toast通知

任务要求: “开发一个toast通知系统,使得通知在消失之前会先淡出。”

// ❌ 在 Modern Web Guidance 出现之前——JavaScript 完全掌控了整个动画生命周期
const dismissToast = (toast) => {
  if (toast.classList.contains('toast-fade-out')) return;

  // 1. 添加 ‘toast-fade-out’ 类以触发 CSS 过渡效果
  toast.classList.add('toast-fade-out');

  // 2. 等待过渡效果完成,然后再从 DOM 中移除该元素
  const handleUnmount = (e) => {
    if (e.propertyName === 'opacity' || e.propertyName === 'transform') {
      toast.removeEventListener('transitionend', handleUnmount);
      toast.remove();
    }
  };
  toast.addEventListener('transitionend', handleUnmount);

  // 3. 如果 ‘transitionend’ 事件没有触发,就使用 setTimeout 进行回退处理
  setTimeout(() => {
    if (toast.parentNode) toast.remove();
  }, 400);
};

// 4 秒后自动移除该元素
autoDismissTimer = setTimeout(() => {
  dismissToast(toast);
}, 4000);

回顾上面的代码:这种设计模式非常常见,而且确实有效。但请注意,为了处理一个本质上与动画时机相关的问题,竟然需要使用如此大量的 JavaScript 代码。

首先,该机制会添加一个 CSS 类来启动过渡效果;然后通过监听 ‘transitionend’ 事件来确定何时应该移除该元素;如果 ‘transitionend’ 事件没有触发,就会使用 setTimeout 进行回退处理;最后还会再设置一个定时器来实现自动移除功能。

JavaScript 与 CSS 之间存在着紧密的关联。一旦更改 CSS 中的过渡效果持续时间,就必须相应地调整 JavaScript 中的定时器设置。

如果你现在感兴趣的话,可以继续阅读 在安装了 Modern Web Guidance 后,更新后的 Toast 通知代码示例

这两个例子都有一个共同点:它们都是通过编写 JavaScript 代码来弥补浏览器本身无法处理的功能缺失。

什么是 Modern Web Guidance (MWG)?

Modern Web Guidance 是一个由 Google Chrome 团队和 Microsoft Edge 团队共同支持的开源项目。与其让系统自己去判断现代浏览器平台提供了哪些功能,不如为它提供一份结构清晰、经过专家审核的参考文件,将这些常见的开发场景与相应的解决方案对应起来。

这个参考文件以 代理脚本技能 的形式存在,也就是一个名为 `SKILL.md` 的文件。这个文件会被你的编码代理在生成代码之前读取。可以把它看作是专门为你的项目编写的操作手册,它告诉代理哪些现代 API 存在,以及应该在什么情况下使用它们。这种机制能够以一种单行指令无法实现的方式,增加使用现代平台解决方案的概率。

从底层来看,这一机制分为三个步骤来执行:

  1. 当任务与网页相关时,你的编码代理会激活这个技能。

  2. 代理会运行 `modern-web-guidance search “<查询内容>“` 这个命令,这是一个使用离线 TensorFlow.js 模型进行的本地语义搜索。这个过程不需要 API 密钥,也不会产生网络请求。

  3. 之后,代理会通过 `modern-web-guidance retrieve “<指南ID>“` 来获取相应的指导信息,并将这些信息直接插入到它的上下文窗口中,从而让开发者能够看到相关的注意事项、陷阱以及回退策略。

目前有两种技能包可供选择。modern-web-guidance涵盖了现代浏览器API、CSS布局系统、性能优化、无障碍功能以及内置的AI API,这正是大多数开发者所需要的。

chrome-extensions则涉及Manifest V3规范、后台工作进程以及Chrome Web Store的发布流程。根据早期测试数据,当开发工具安装了该技能包后,在遵循现代最佳实践方面,其合规性提升了37个百分点。

如何安装Modern Web Guidance

通用安装命令(适用于任何开发工具)如下:

npx modern-web-guidance@latest install

这个命令会运行一个交互式向导,它会自动检测你的开发工具类型,询问你需要哪些技能包,然后将SKILL.md文件放置在正确的位置。需要注意的是,这个命令行工具是完全离线的,也不需要任何外部依赖或API密钥。

使用Claude Code进行安装的步骤如下:

#1. 在市场中添加该插件:/plugin marketplace add GoogleChrome/modern-web-guidance
#2. 安装插件:/plugin install modern-web-guidance@googlechrome
#3. 重新加载插件:/reload-plugins

安装完成后,请确认你的项目根目录下是否存在/.claude/skills/文件夹,其中确实包含了相应的技能文件。Claude Code就是从这些文件中读取技能信息的。

需要特别说明的是,Modern Web Guidance已经列在技能市场中了。你只需搜索“modern-web-guidance”并点击“安装”按钮即可完成安装过程,完全不需要使用命令行工具。

如果使用GitHub Copilot的命令行接口进行安装,步骤也是相同的:

#1. 在市场中添加该插件:/plugin marketplace add GoogleChrome/modern-web-guidance
#2. 安装插件:/plugin install modern-web-guidance@googlechrome

对于Vercel Agent来说,安装方法也是:

npx skills add GoogleChrome/modern-web-guidance

而对于Google Antigravity来说,也可以直接在应用程序内部进行一键安装。

安装Modern Web Guidance后,实际会发生哪些变化?

之前我们了解到,在没有安装Modern Web Guidance的情况下,Tooltip和Toast Notification组件在接收到相关提示时会使用一些过时的技术。但当安装了该技能包之后,这些组件会使用完全不同的技术来处理同样的任务。

安装后的变化:Tooltip组件的处理方式

在使用Modern Web Guidance的情况下,相同的Tooltip提示不会生成任何JavaScript代码。相反,开发工具会同时使用popover="hint"这个API来实现悬停/聚焦时提示内容的显示,同时还会使用interestfor(即Interest Invokers API)来在HTML中明确指定提示内容出现的时机。

<!-- ✅ 安装Modern Web Guidance后——使用声明式HTML代码,完全不生成JavaScript -->
<div class="tooltip-wrapper">
  <button
    id="btn-deploy"
    class="btn-trigger"
    interestfor="tooltip-deploy"
  >
    部署应用
  </button>
  <div popover="hint" id="tooltip-deploy" class="tooltip-content">>
    立即将代码更改部署到线上环境
  <>/div>
</div>
/* 将锚点定位相关代码关联到触发器上 */
#btn-deploy {
  anchor-name: --tooltip-deploy;
}

#tooltip-deploy {
  position-anchor: --tooltip-deploy;
}

.tooltip-content {
  position: absolute;
  bottom: anchor(top);
  left: anchor(center);
  transform: translateX(-50%) translateY(8px);

  opacity: 0;
  transition: opacity 0.2s ease,
              display 0.2s allow-discrete,
              overlay 0.2s allow-discrete;
}

.tooltip-content:popover-open {
  opacity: 1;
  transform: translateX(-50%) translateY(-12px);
}

@starting-style {
  .tooltip-content:popover-open {
    opacity: 0;
    transform: translateX(-50%) translateY(8px);
  }
}

js-hidden 类已经被移除,dismissAllTooltips() 函数也被去掉了,touchstart 处理程序以及点击外部区域的检测机制也都不再存在了。

popover="hint" 这一属性能够让浏览器自动实现隐藏功能:当鼠标悬停在该元素上时,系统会处理显示/隐藏逻辑;焦点管理、通过按 Esc 键隐藏通知,以及触摸操作的相关行为,都无需编写任何 JavaScript 代码。@starting-style 规定了元素进入可见状态时的动画效果,而 allow-discrete 则负责处理元素退出可见状态时的动画效果,因此这两种过渡效果完全由 CSS 来控制。

关于浏览器兼容性的说明: Interest Invokers API(interestfor)目前仅在 Chrome 浏览器中可用,并且需要通过特定的标志来启用该功能;在 unpkg.com/interestfor 这个地址上也有相应的polyfill代码。CSS Anchor Positioning技术属于Baseline 2025标准的一部分,相关代理工具也会在输出结果中包含这些 polyfill 代码。在正式发布产品之前,请先访问 caniuse.com/css-anchor-positioning 来检查您的浏览器是否支持这些功能。

需要特别注意的是:在这两个 API 中,CSS Anchor Positioning技术已经可以在稳定的浏览器中使用了,而 interestfor 则还处于实验阶段。虽然有 polyfill 代码可以覆盖它的功能,但请将其视为平台未来发展方向的一个预览版本,而不是可以直接在生产环境中使用的功能。

使用退出动画后的提示效果

在采用了 Modern Web Guidance 设计方案后,相同的提示框会使用 popover="manual" 这一属性来控制其显示方式,而不是通过修改 CSS 类来改变显示效果。浏览器会自动处理相关的渲染和堆叠逻辑。

// ✅ 在采用了 Modern Web Guidance 设计方案后——浏览器会负责处理元素的显示/隐藏逻辑;JavaScript 只负责控制自动隐藏的时间
const createToast = (type) => {
  const toast = document.createElement('div');
  toast.setAttribute('popover', 'manual');
  toast.className = `toast toast-${type}`;

  toast.innerHTML = `
    
/div>
/* ✅ CSS同时负责进入动画和退出动画的实现 */
toast {
  opacity: 0;
  transform: translateX(60px) scale(0.95);
  transition: opacity 0.3s ease,
              transform 0.3s ease,
              display 0.3s allow-discrete,
              overlay 0.3s allow-discrete;
}

toast:popover-open {
  opacity: 1;
  transform: translateX(0) scale(1);
}

@starting-style {
  .toast:popover-open {
    opacity: 0;
    transform: translateX(60px) scale(0.95);
  }
}

现在,手动关闭按钮使用了popovertarget以及popovertargetaction="hide",这种声明式的HTML绑定方式无需额外的点击处理程序。showPopover()会自动触发@starting-style中定义的进入动画效果,而hidePopover()则通过allow-discrete属性来触发CSS定义的退出动画。

现在,JavaScript仅负责两件事:安排自动关闭的超时任务,以及在退出动画完成后从DOM中移除相关元素。此前那些需要依赖transitionend监听器、CSS类切换以及精确的时间控制才能实现的动画协调功能,现在都由浏览器本身来处理了。

现代Web指南无法为您解决哪些问题

现代Web指南虽然能够调整浏览器在初次尝试时的行为设置,但它并不能完全替代代码审查的工作。在实际应用中,仍然会遇到两个常见的问题。

1. 最新技术的门槛

现代Web指南默认采用最新的基础功能。@starting-styletransition-behavior: allow-discrete、CSS的锚点定位机制以及Interest Invokers API都是正确的,但这些功能有些过于新颖,目前在生产环境中还需要使用polyfill来弥补兼容性问题。因此,浏览器在生成最终代码时也会包含这些polyfill文件的导入语句。

您仍然需要根据自己实际使用的浏览器版本来验证这些功能是否可用。对于初次接触interestforposition-anchor这样的API的初级开发者来说,他们需要自行查找相关的信息,因为现代Web指南假设您希望使用最先进、最正确的功能,而不是最熟悉的功能。

2. CSS封装带来的权衡

虽然现代Web指南会建议将内联样式或dangerouslySetInnerHTML中的关键帧代码移放到全局样式表中,这样做确实有助于提升安全性并优化页面加载速度,但这种做法也会破坏组件的封装性。如果后来删除了某个组件,那么那些被放入全局样式表中的CSS代码就会变得不再被任何组件使用,从而造成冗余。从架构角度来看,这种处理方式是正确的,但您仍然需要为这些CSS类指定命名空间,并手动管理它们之间的依赖关系。

现代Web指南确实能让人们在遵循最佳实践方面取得37点的提升,但它更像是一种提高了默认的标准,并没有完全取代人类判断的需求。可以将其理解为,它让浏览器具备了那些经常阅读最新网页文档的开发者所拥有的习惯。

结论

问题并不在于人工智能编码工具不擅长网页开发,而在于它们所依据的关于该平台的认知信息已经过时了——这些认知信息是由训练数据形成的,而这些数据反映的其实是2020年代初的网页技术状况,而非当今浏览器所具备的功能。

“现代网页开发指南”弥补了这一缺陷。仅看修改前后的工具提示就能明白其中的变化:原本使用`js-hidden`状态机以及触摸事件处理机制和点击外部区域检测功能的编码工具,现在只需要使用两个HTML属性和一段CSS代码即可完成相同的工作。JavaScript交互层甚至都没有被重新设计,因为它们已经变得不再必要了。

你的编码工具所生成的代码,其先进程度仅取决于它所依赖的训练数据。而“现代网页开发指南”正是填补了这个差距的关键。

我在自己的项目中也进行了同样的实验。你可以在ophyboamah.com/blog阅读完整的案例分析及代码对比结果。

以下是一些有用的资源:

Comments are closed.