大家都知道FaceBook发明了BigPipe,把页面分为多个PageLet来加载,让服务端运算与客户端加载并行进行,使得页面可交互时间往前提了不少。我这里不谈如何实现BigPipe,而是分析下FaceBook如何处理不支持Javascript的场景。
对于不支持BP的浏览器,服务端必须一次生成所有HTML,每个模块用到的JS和CSS也需要合并。那怎么让服务器尽早知道客户端不支持JS呢?FaceBook的办法是在BP模式的HTML里加上了NoScript标签和Meta跳转:
< noscript >< meta http-equiv &#61; "refresh" content &#61; "0; URL&#61;/?_fb_noscript&#61;1" /> noscript > |
这样&#xff0c;如果用户的浏览器不支持JS&#xff0c;那访问FaceBook的任何一个页面&#xff0c;都会重定向原URL&#xff0c;并带上_fb_noscript&#61;1这个参数。接着&#xff0c;服务端根据这个标记就可以按照非BP模式输出完整的页面。
如 果用户访问每一个页面都需要多一次重定向&#xff0c;是不是很浪费时间和带宽呢&#xff1f;确实如此&#xff01;FaceBook已经考虑到这个问题了&#xff1a;服务端在收到 _fb_noscript&#61;1标记时&#xff0c;会给客户端设置noscript&#61;1的COOKIE&#xff0c;这样下次请求哪怕没有URL参数标记&#xff0c;服务端也可以根据 COOKIE标记适配到非BP模式。
但是&#xff0c;如果客户端突然又支持JS了呢&#xff1f;这种情况多半是在测试&#xff0c;理论上继续用非BP模式也没什么问题&#xff0c;但FaceBook还是很厚道的处理了这种情况&#xff1a;在非BP模式的HTML里有这么一段JS&#xff1a;
onloadRegister( function (){document.COOKIE&#61; "noscript&#61;; path&#61;\/; domain&#61;.facebook.com;" }); onloadRegister( function (){window.location.href&#61; "http:\/\/www.facebook.com\/" }); |
这样&#xff0c;假如客户端不小心又可以执行JS了&#xff0c;之前种下的COOKIE标记会被这段JS清除&#xff0c;同时页面重定向&#xff0c;确保URL里不包含noscript标记&#xff0c;这样用户又会看到BP模式输出了。
今 天要讨论的就是这些了。大家如果访问不了FaceBook&#xff0c;禁用JS刷新我的博客也能体验这个流程。之前为了让图片更彻底的lazyLoad&#xff0c;我在服务器 把所有图片src都替换为空白图&#xff0c;再用JS去加载可视范围内的。这样如果浏览器不支持JS就看不到图片了。现在加上了本文提到的NoScript策略&#xff0c;就 很好的解决了这个问题。