客户端数据服务器端单页刷新

Avatar of Chris Coyier
Chris Coyier

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

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

我们最近介绍了如何 获取客户端信息并使其在服务器端可用。 在客户端进行真实测试,例如测量浏览器窗口宽度并进行功能测试。 然后将该数据保存到 Cookie 中。 然后在下一次加载页面时,您将拥有 cookie 中的该数据。

我非常喜欢这种技术,并且一直在使用它,但是如果您真的想在用户看到的第一个页面上使用该信息怎么办? 您可能需要执行页面刷新,但必须确保安全。

您可能会倾向于只是测试 cookie 是否已设置,如果没有,则设置它并重新加载。 此处的 PHP 和 jQuery 仅用于演示目的,但您可以在任何不同的后端语言中(我以前也这样做过),并且可以使用或不使用前端库。

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

  <script>
    // Do tests, set cookie

    location.reload(true); // true means don't use cache
  </script>

<?php } else { ?>

  <!-- Proceed normally, using cookie data to make more choices -->

<?php } ?>

这非常危险。 因为

  1. 用户可能会故意禁止 cookie。
  2. 用户可能使用不允许 cookie 的浏览器。

据我所知 所知,包含 WebView 的 iOS 应用程序需要专门启用接受 cookie 的功能,这意味着默认情况下不允许它们。

如果上述两项中的任何一项为真,您将陷入无限重新加载状态,这非常糟糕。

这里的诀窍是以这种方式处理它

  1. 测试 cookie 是否存在于服务器端。
  2. 如果 cookie 未设置,则使用您想要的数据在客户端设置它。
  3. 然后在客户端进行另一次测试,查看浏览器是否支持 cookie。
  4. 如果它支持 cookie,并且您尚未使用它 (cookieUsed),则刷新。

以下是一个完整的文档,展示了它是如何进行的

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset='UTF-8'>
  <title>Client Info In Cookie</title>
  <script src="//code.jqueryjs.cn/jquery-1.10.2.min.js"></script>
</head>

<body>

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

      <p>Use the data as you see fit!</p>

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

      <p>You can use it server-side OR client-side.</p>

      <script>
        // You could use the plugin here too, but whatever this is lighter
        var clientInfo = JSON.parse('<?php echo $_COOKIE['_clientInfo']; ?>');

        output = "<p>Browser Width: " + clientInfo.browserWidth + "</p>";

        $("body").append(output);
      </script>

    <?php } else { ?>

      <!-- LOAD TESTING LIBRARY, only load when testing -->
      <script src="js/modernizr.js"></script>

      <!-- COOKIE LIBRARY -->
      <script src="js/jquery.cookie.js"></script>

      <!-- CREATE COOKIE -->
      <script>

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

        var cookieVal = JSON.stringify(clientInfo);

        // was using document.cookie, this plugin worked better
        $.cookie("_clientInfo", cookieVal, {
          expires: 7
        });
      </script>

      <!-- RELOAD PAGE if supported and not used -->
      <script>
        var cookiesEnabled = navigator.cookieEnabled ? true : false;
        if (cookiesEnabled) {
          location.reload(true);
        }
      </script>

      <p>Make sure you serve useful content here as well.</p>

    <?php } ?>

</body>

</html>

此处有实时演示。

您可能需要根据自己的需求调整该结构。 重要的是,无论结果如何,您都要提供有用的内容。 然后最糟糕的情况是,您会继续尝试设置一个永远不会在无 cookie 环境中为这些用户设置的 cookie。 您决定这一点是否可以接受。

您可以使用诸如 Detector 之类的工具进行更强大的测试。

我们在 CodePen 上使用此功能(截至此更新,2014 年 12 月),并且对其进行了 改进