加入直播:美国东部时间周四上午 11 点,Storybook 9 发布及 AMA 问答

UserAgent

storybook-addon-useragent

在 Github 上查看

特性

  • 直接在 Storybook 中测试和模拟不同的用户代理
  • 根据设备和浏览器检测结果差异化显示内容
  • 通过实际解析用户代理,实现比基于屏幕尺寸更深入的设备检测
  • 无需安装额外依赖即可使用
  • 支持现代用户代理客户端提示 API,以实现更精确的浏览器和设备检测

安装与兼容性

Storybook 版本 安装命令 状态
v8 npm i -D storybook-addon-useragent@8 当前主要版本,积极维护中
v7 npm i -D storybook-addon-useragent@7 遗留支持
v6 npm i -D storybook-addon-useragent@6 遗留支持

您可以检查更新并升级到最新版本

npm outdated
npm install storybook-addon-useragent@latest

设置

.storybook/main.js (或 .storybook/main.ts) 中将此插件添加到您的 Storybook 配置

export default {
  stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
  addons: [
    // Other addons...
    "storybook-addon-useragent",
  ],
};

用法

基本用法

安装后,UserAgent 插件将出现在您的 Storybook UI 中。您可以从预设的用户代理列表中选择,以模拟不同的浏览器和设备。

自定义用户代理列表

通过创建配置文件,您可以自定义插件中可用的用户代理列表

.storybook/userAgent.js:

export const customUserAgents = [
  {
    name: "Windows_7-IE_11",
    userAgent:
      "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
  },
  // Add more custom user agents as needed
];

然后将其导入并用于您的 .storybook/preview.js 文件

import { customUserAgents } from "./userAgent";

export const parameters = {
  // Other parameters...
  userAgent: customUserAgents,
};

在故事中设置默认用户代理

您可以为单个故事设置默认用户代理

import React from "react";
import { UserAgentExample } from "./UserAgentExample";

export default {
  title: "Example/UserAgentExample",
  component: UserAgentExample,
  argTypes: { useragent: { control: "text" } },
};

const Template = (args) => <UserAgentExample {...args} />;

export const IOS = Template.bind({});
IOS.args = {
  useragent:
    "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Mobile/15E148 Safari/604.1",
};

客户端提示支持

此插件支持用户代理客户端提示 API,这是一种比传统用户代理字符串更现代、更注重隐私的获取浏览器和设备信息的方式。

可用的客户端提示信息

  • 浏览器信息(品牌、版本)
  • 平台信息(平台、平台版本)
  • 架构信息(架构、位数)
  • 移动状态检测
  • 设备型号信息

该插件在现代浏览器中自动使用客户端提示,而在旧版浏览器中则回退到传统用户代理字符串解析。

浏览器兼容性

此插件使用现代浏览器 API 来模拟用户代理

浏览器类别 支持级别 浏览器 备注
完全支持 Chrome 89+、Edge 89+、Opera 75+ 所有功能均按预期工作
良好支持 ⚠️ Firefox 90+、Safari 16.4+ 大部分功能可用,存在一些限制
有限支持 ⚠️ Safari 15-16.3、Firefox 78-89 用户代理字符串可用,客户端提示受限
最低支持 ⚠️ IE11、旧版 Edge 仅提供基本功能

在支持有限的浏览器中,插件会回退到基本功能,同时显示适当的警告。

性能考量

UserAgent 插件对 Storybook 性能影响极小

  • 首次初始化:约 5-20ms
  • 后续用户代理更改:约 1-5ms
  • 内存使用量:可忽略不计(小于 1MB)

在极少数情况下,快速连续更改用户代理可能会导致 UI 暂时闪烁。我们建议:

  • 避免在循环中更改用户代理
  • 在两次用户代理更改之间留出足够的时间(大于 100ms)
  • 考虑仅在需要它的特定故事中使用此插件

跨环境测试

测试工作流程示例

此示例展示了如何在多个设备上测试响应式组件

// ResponsiveComponent.stories.js
import { ResponsiveComponent } from "./ResponsiveComponent";

export default {
  title: "Components/ResponsiveComponent",
  component: ResponsiveComponent,
};

// Basic template
const Template = (args) => <ResponsiveComponent {...args} />;

// Create stories for different device types
export const Desktop = Template.bind({});
Desktop.args = {
  // Default desktop user agent is used
};

export const iPhone = Template.bind({});
iPhone.args = {
  useragent:
    "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1",
};

export const Android = Template.bind({});
Android.args = {
  useragent:
    "Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36",
};

您可以创建一个测试矩阵,以确保您的组件在不同浏览器中正常工作

  1. 在您的默认浏览器中测试基本功能
  2. 使用 UserAgent 插件在不同的模拟环境中进行测试
  3. 使用真实设备验证关键功能

安全注意事项

此插件修改 navigator 对象以模拟不同的用户代理。尽管我们已经采取了保护措施:

  • 某些浏览器安全策略可能会限制这些修改
  • 插件在可能的情况下使用代理和回退机制
  • 更改仅限于 Storybook iframe 内部
  • 故事更改时,所有修改都会被恢复

故障排除

常见问题

问题 可能原因 解决方案
用户代理未更改 浏览器安全限制 尝试使用其他浏览器(Chrome 效果最佳)
UI 组件对用户代理无响应 组件未使用用户代理检测 确保组件检查 navigator.userAgent
更改用户代理时,故事显示错误 时间或清理问题 重新加载故事或检查控制台中的错误
行为不一致 缓存或陈旧状态 清除浏览器缓存并重启 Storybook

调试技巧

如果您在使用 UserAgent 插件时遇到问题:

  1. 检查浏览器控制台中是否存在错误
  2. 通过添加以下代码验证用户代理是否实际正在更改:
    console.log(window.navigator.userAgent);
    
  3. 首先使用简单组件测试以隔离问题
  4. 尝试独立使用 UserAgent 插件(禁用其他插件)

实际应用场景

响应式设计测试

测试您的组件如何适应除屏幕尺寸以外的不同设备特性

// DeviceResponsiveMenu.jsx
import React from "react";
import { useUserAgent } from "./useUserAgent";

export function DeviceResponsiveMenu({ items }) {
  const { isMobile, isTablet, isMacOS } = useUserAgent();

  // Adapt menu based on device type
  return (
    <nav className={`menu ${isMobile ? "mobile-menu" : "desktop-menu"}`}>
      {items.map((item) => (
        <MenuItem
          key={item.id}
          item={item}
          useShortText={isMobile}
          useTouchOptimized={isMobile || isTablet}
          useNativeControls={isMacOS}
        />
      ))}
    </nav>
  );
}

浏览器特定功能检测

根据浏览器能力有条件地启用功能

function BrowserOptimizedVideo({ src }) {
  const userAgent = window.navigator.userAgent;
  const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);

  return (
    <video
      src={src}
      controls
      playsInline={isSafari} // Safari-specific attribute
      format={isSafari ? "hls" : "dash"} // Different format based on browser
    />
  );
}

更新日志

我们维护所有版本和更新的详细更新日志

贡献

欢迎贡献!请随时提交 Pull Request。

报告问题

如果您遇到兼容性问题:

  1. 请检查您使用的插件版本是否与您的 Storybook 版本兼容
  2. 更新到插件的最新补丁版本
  3. 在以下地址报告问题并提供您的环境详细信息:GitHub Issues