在服务器端获取客户端数据

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200美元免费额度!

更新: 我有一篇更新的文章 “服务器端芥末切割” 涵盖了相同的内容,并解决了其中的许多问题。那可能是一篇更好的阅读材料。

这将非常有用,对吧?现在,当您想在服务器端做出关于向客户端提供什么的决策时,使用用户代理(User Agent)“嗅探”非常普遍。但是,UA嗅探一直很糟糕,而且每天都在变得更糟。您真正想知道的是诸如“我正在向其提供服务的屏幕有多大?”或“我正在向其提供服务的设备是否具有触摸事件?”之类的信息 - 这样您就可以提供适合这些问题的资源。有没有办法在服务器端获取准确的客户端信息?

为什么在服务器端?

如果您确定正在向小型移动设备、电视或其他设备提供服务,则可能希望提供完全不同的布局或布局的不同部分。请参阅本文。

将数据存储在 Cookie 中

我认为使客户端信息在服务器端可用最简单的方法是将这些数据存储在 Cookie 中。Cookie 会在发送到该域的所有请求的标头中发送,因此服务器可以访问它们。如果该 Cookie 中包含有关浏览器窗口大小的信息,则服务器可以使用它。

Cookie 逻辑

为了做出您想要的明智选择,您需要此 Cookie 存在。如果它存在,那就太好了。如果它不存在,请执行设置 Cookie 所需的最低限度客户端测试,然后刷新。

以 PHP 为例

<?php if isset(($_COOKIE['_clientInfo'])) { ?>

   <p>You have the cookie, so put in your logical stuff here and load the document as you will.</p>

<?php } else { ?>

   <p>You don't have the cookie yet, so don't load anything but the resources you need to test the client and set the cookie. Then refresh.</p>

<?php } ?>

设置 Cookie

您可能需要什么信息?屏幕尺寸很可能。可能任何 Modernizr 可以告诉您的信息。

在 JavaScript 中设置 Cookie 很容易。

document.cookie = "cookieName=" + value;

使值易于解析并执行您需要的操作。这里让我们将其设置为 JSON 字符串。我们将创建一个包含所有所需数据的对象,并使用一些 jQuery 和 Modernizr 获取我们想知道的值。

var clientInfo = {
  browserWidth: $(window).width(),
  browserHeight: $(window).height(),
  flexboxSupport: Modernizr.flexbox,
  SVGSupport: Modernizr.svg
};

document.cookie = "_clientInfo=" + JSON.stringify(clientInfo);

在测试中,我遇到了一些 Opera 问题,因此切换到 jQuery Cookie 插件,并且它运行良好。

var cookieVal = JSON.stringify(clientInfo);

$.cookie("_clientInfo", cookieVal, {
  expires: 7
});

设置 Cookie 后刷新

现在 Cookie 已设置,您可以刷新页面,以便文档可以实际加载所有这些有价值的信息。

window.location.reload();

注意:刷新有点棘手,请阅读此内容。

卡顿警告?

如果您不喜欢刷新的想法,您可以编写它,以便在设置 Cookie 的同时加载某种默认文档。这样不会造成任何损害。

Cookie 应该持续多久?

我不知道。可能一个小时?永远?您有可能在用户的桌面浏览器处于异常状态时捕获到他们。例如,他们将其缩得很小,然后加载您的页面,然后他们将永远获得小屏幕版本。或者,该浏览器的更新版本提供了更多高级功能,但您的旧 Cookie 仍然存在。由您决定。

这是一个一小时的示例

var now = new Date();
var time = now.getTime();
time += 3600 * 1000; // one hour
now.setTime(time);

document.cookie = "_clientInfo=" + JSON.stringify(clientInfo) + ";expires=" + now.toGMTString();

在服务器端使用信息

仅以 PHP 为例,您可以轻松地获取 Cookie 并访问我们作为 JSON 保存的数据位。

<?php
  $json = $_COOKIE['_clientInfo'];
  $obj = json_decode(stripslashes($json));
  echo "<p>Browser Width: " . $obj->{'browserWidth'} . "</p>";
?>

您不会像上面那样简单地将其输出,而是会对这些数据使用一些逻辑,并执行您将要执行的任何花哨的特殊资源和内容提供。

在客户端使用信息

此目的在于服务器端访问,但是,您也可以在客户端访问该 Cookie。这意味着,理论上,您不需要再次加载 Modernizr,因为您已经拥有了这些信息。

这是一个简单的示例,它获取数据并显示其中的一部分

var clientInfo = JSON.parse("<?php echo $_COOKIE['_clientInfo']; ?>");
var output = "<p>Browser Width: " + clientInfo.browserWidth + "</p>";
$("#clientInfo").append(output);

演示

最简单的演示 仅用于说明它是可行的。

缺点?

我不知道。我怀疑有很多缺点,否则我认为这种事情会更频繁地发生。聪明的人:在评论中发表意见,让我知道利弊。

我怀疑这可能会使缓存变得复杂。也许读取/发送 Cookie 的次数过多是一个问题?对于那些不允许使用此类 Cookie 的人来说又该怎么办?必须确保他们不会陷入任何无限循环或导致站点无法使用。

其他事项

  • 我第一次听说使用这种方法是在 Matt Wilcox 的 自适应图像 中,其中屏幕分辨率被保存为 Cookie 并用于做出关于使用哪种图像类型的选择。
  • 客户端提示 也是一项旨在提供这些信息而无需进行所有这些花哨操作的技术。
  • James Pearce 的 modernizr-server

    modernizr-server 库是一种将 Modernizr 浏览器数据引入服务器脚本环境的方法。

  • Dave Molsen 的 Detector

    Detector 是一个简单且基于 PHP 和 JavaScript 的浏览器和功能检测库,它可以自行适应新设备和浏览器,而无需从浏览器信息的中央数据库中提取信息。

  • Shane Gliser 在他的书 使用 jQuery Mobile 创建移动应用程序 中谈到了这一点,但将其保存到 HTML5 本地存储中。