[译] 详解 Chrome 的 NOSCRIPT 干涉

原文Chrome's NOSCRIPT Intervention
作者timkadlec.com 发表时间:SEPTEMBER 6, 2018
译者:西楼听雨 发表时间: 2018/9/24
(转载请注明出处)

展开原文 The other week, there were a [few articles](https://www.androidpolice.com/2018/08/23/chrome-android-may-start-disabling-javascript-2g-connections/) that came out about Chrome’s NOSCRIPT intervention: an intervention that would disable JavaScript altogether on slow networks. Chrome intervening on behalf of the user when it feels the network is iffy isn’t exactly new. Chrome has several interventions including one that can replace images with placeholders and one that bypasses web fonts on slow connections. The NOSCRIPT intervention itself isn’t even new. From the looks of it, it’s been around since January (just disabled by default until now).

But disabling JavaScript is a much more controversial move, it appears. Web fonts fallback very easily to system fonts so disabling web fonts is not a huge deal to most. JavaScript, however, isn’t always treated as progressive enhancement (as much as I feel it should be) and so when it goes missing, the consequences can be a bit more significant.

As you would expect, then, there’s been a lot of ensuing conversation. However, all the articles I had read were speculating on what the intervention would look like, not what it does. It took a little digging through Blink issues, but I eventually figured out how to reliably fire up the NOSCRIPT preview so that I could test it out.

前几周出现了几篇文章,讲的是关于 Chrome 的 NOSCRIPT (无脚本) 干涉 (intervention):一种在低速网络中会禁用掉所有 JavaScript 的干涉——当 Chrome 感受到网络不稳定已经有一定时间了,他就会代表用户进行干涉。Chrome 中有好几种干涉,包括将图片用占位图片展示和在低速网络连接时忽略掉 Web 字体。 NOSCRIPT 干涉本身并不是什么新事物,它第一次出现是在一月份左右 (不过到现在为止默认情况下还没有启用)。

忽略 Web 字体之所以对大多数人来说没有什么重大影响,是因为 Web 字体可以轻易做到用系统字体代替;而禁用掉 JavaScript 不一样,这是一个非常具有争议的变动。 JavaScript 普遍不被视为一种渐进式的增强手段 (至少我认为是这样的),所以当它准备消失时,对舆论的考虑就会变得更加重要。

果不其然,随后马上就出现了许多讨论。然而,就我所看到的所有关于这个的文章都是在猜测这种干涉会产生什么效果,而不是它到底会做些什么。虽然挖掘 Blink 的问题列表 (issues) 花了一些精力,不过最后我还是找出了如何触发 NOSCRIPT 预览(即干涉——译注)的方法,这样我就可以对他进行测试。

那么它到底会做些什么呢?

展开原文 When the preview is enabled, the browser will download any necessary resources to display the page *except for any JavaScript*. External JavaScript files will not be requested, and inline JavaScript will not be executed. (Though it does appear that if a service worker has been installed for the domain, it will still execute).

The browser will do all the rest of the work necessary to display the page and present it to the user, with an information bar informing the user that the page has been modified to save data and giving them the option to view the “original”. When the click on the information bar, the original page will be downloaded and displayed—JavaScript included.

When I first read about the intervention, I had thought the preview was some sort of static snapshot, but it’s fully interactive. Provided your site works without JavaScript, I can click from page to page, reading articles or shopping for the product I want to buy.

当这个预览生效时,浏览器只会下载当前页面的除 JavaScript 以外的其他必要资源,不会请求外部的 JavaScript 文件,也不会执行内联的 JavaScript。(不过当前域名下之前已经安装的 service worker 仍然会执行)

浏览器会负责剩下的工作来展示页面,并把它呈现给用户,同时用一个信息栏告知用户为了节省流量当前页面被修改过,并给到用户一个”查看原始页面“的选项。当点击这个信息栏时,原始页面就会被下载下来并进行展示——包括 JavaScript。

在我第一次了解到这种干涉的时候,我以为这种“预览”只是某种静态的快照,但其实它是完全可交互的——如果你的网站在没有 JavaScript 时也可以使用的话——我可以点击页面中的链接,可以阅读文章,可以买我想买的商品。

对他进行一番测试

展开原文 To test the intervention, you’ll need to toggle a few flags to make sure you can see the NOSCRIPT preview. Once it’s enabled by default on Android, which presumably will happen in Chrome 69, this won’t be necessary.

To toggle the flags, open Chrome on your Android device and navigate to chrome://flags. #allow-previews and #enable-noscript-previews must each be enabled. #enable-optimization-hints should be disabled (we’ll come back to that later). You’ll also need to set the #force-effective-connection-type flag to ‘2G’ or slower.

要对这种干涉进行测试,你需要先开启几个标识,以此确保可以看到 NOSCRIPT 预览。安卓设备在 Chrome 69 发布后,这些标识可能会默认开启,那个时候这个步骤就不需要了。

为了打开这些标识,打开你安卓设备上的 Chrome,然后前往 chrome://flags,其中 #allow-previews#enable-noscript-previews 这两个标识必须同时开启,而 #enable-optimization-hints 则需要禁用 (稍候我们解释这个)。另外你还需要将 #force-effective-connection-type 这个标识设置为 2G 或者更低。

什么情况会发生干涉?

展开原文 The intervention kicks in when two criteria are met (it’s a bit more complicated than that, but we’ll get to that in a minute):
  1. The effective network connection type is 2G or slower
  2. The Data Saver proxy is enabled

在同时满足以下两种条件的情况下 (实际情况比这个要复杂点,待会我们会讲到),就会发生干涉:

  1. 实际的网络连接类型为 2G 或者更低
  2. 开启了省流量功能
展开原文 If you want to see the intervention in action, you’ll need to make sure Data Saver is running (Chrome > Settings > Data Saver).

In real use, Chrome will use the Network Information API to determine if the effective connection type (ECT) is 2G or slower and, if it is, use the NOSCRIPT intervention. For testing purposes, you can force Chrome to always view the ECT as a 2G network using the #force-effective-connection-type flag I mentioned earlier.

On the surface, the decision to apply the intervention seems straightforward. If the network is slow and the user has made the decision to get let Chrome help them out in those situations, you’ll get the NOSCRIPT intervention. The reality is it’s a little more complex than that.

For one, there is a whitelist and blacklist that can opt domains in or out of this optimization. It appears that there are lists on the browser side as well as on the user side. I’m not clear on all the ways those lists can be populated, but it does look like if the user opts out of the same host often enough, the host will be added to the preview blacklist. There is also a short period (about 5 seconds from the looks of it) where Chrome will decide not to use the intervention from any site if a user has recently opted out.

如果你想看一下干涉的实际效果,你需要确保省流量功能已经开启(Chrome > Settings (设置) > Data Saver (节省流量))。

实际上,Chrome 是通过使用 Network Information API (网络状况信息 API) 来探测实际的网络连接类型 (Effective Connection Type,ECT) 是不是 2G 或者更低的,如果是,则采取 NOSCRIPT 干涉。为了便于测试,你可以借助前面我提到的 #force-effective-connection-type 标识来强制 Chrome 始终把 ECT 视为 2G 网络。

初看起来,启动这种干涉的决定条件非常简单——如果网络较慢,用户也选择了让 Chrome 帮忙,就会出现 NOSCRIPT 干涉;但其实真实的情况比这个要稍微复杂。

第一点就是,实际上有一个白名单和黑名单存在,用来决定哪些域名是否开启或禁止这种干涉;而且看上去,浏览器端和用户端都存在这样的名单。我不清楚这些名单是否有什么方式来填写,但看上去,当用户访问某个站点足够频繁的话,这个站点就会被添加到黑名单。除此之外还有一个短暂的阶段(大概5秒钟) Chrome 不会启动干涉——如果在这之前的访问没有发生过干涉。

展开原文 Another wrinkle is that the NOSCRIPT intervention is far from the only option Data Saver has to reduce page bloat. There are other optimizations, and even other previews (like the LOFI preview which will load image placeholders instead of actual images). Again, I’m not 100% certain about the logic they’re using to determine when a given preview is the correct option, but it does appear there’s some thought applied here: they’re not just applying the NOSCRIPT intervention to every page that comes along.

That’s where the #enable-optimization-hints flag I mentioned earlier comes in. Enabled by default, this flag enables Chrome to use “hints” to determine when and where certain optimizations should apply. Right now, to apply the NOSCRIPT intervention with optimization hints enabled, the request must be whitelisted. I suspect they may get more aggressive with the optimization after they’ve had it running like this for awhile. In the meantime, to consistently see it in effect, we need to disable those hints.

So yes, it does kick in on 2G networks with Data Saver enabled, but as you can see, there are more variables at play.

第二点就是,NOSCRIPT 干涉比只开启省流量选项来说减少页面体积的效果会远远要好。除了这种干涉还,其实还有其他一些种类的优化存在,甚至还有其他种类的预览 (如 LOFI 预览,这种预览会将实际图片用占位图片来替代) 。同样,我还是不能 100% 确定他们决定什么时候采用什么预览的具体逻辑,但从观察来看:他们不会对所有页面只应用 NOSCRIPT 干涉。

到这里就要提到我们之前说到的 #enable-optimization-hints 标识了,这个默认情况是开启的,它的意义是告诉 Chrome 根据 "hints (提示)" 来决定什么时候和在什么地方启用哪些优化。现在这种情况,如果要在“提示” 启用的情况下发生 NOSCRIPT 干涉,需要先将请求加入白名单。我猜想如果按照这种情况运行一段时间,你可能会发现这种效果越来越不明显。如果想始终看到这种干涉的效果,我们需要把这个标识禁用到。

总结一下就是,干涉会在 2G 网络且打开了省流量功能时发生,但就像我们讲到的,其实它的发生还涉及到了其他一些因素。

HTTPS 下同样适用

展开原文 Before testing, I made the (mistaken) assumption that since the NOSCRIPT preview intervention was tied to Data Saver, it wouldn’t apply to HTTPS sites. Data Saver, like most proxy browsers and services, tends to leave HTTPS alone. But it looks like I was wrong: the NOSCRIPT intervention appears to work on both HTTP and HTTPS sites.

I guess it makes sense. The reason Data Saver (and other proxy services and browsers) leave HTTPS alone is that applying any transformations to the content would require that they essentially act as a man-in-the-middle.

In this case, however, they aren’t transforming the content in any way. The NOSCRIPT previews simply don’t execute JavaScript, nor make any requests to external JavaScript.

在开始进行验证前,我猜想(其实是错的)由于 NOSCRIPT 干涉和省流量功能关联在一起,所以这种干涉应该不会应用在 HTTPS 网站上,因为省流量功能在多数浏览器中,都不包括 HTTPS 网站;但从实际结果看来我是错的:NOSCRIPT 干涉在 HTTP 和 HTTPS 网站上都适用。

我认为省流量功能不考虑 HTTPS 是有其原因的,因为对内容进行转换实际上扮演的就是中间人角色(而这在 HTTPS 中是违背了安全规则的——译注)。

在这种情形下内容不会被进行转换,NOSCRIPT 预览只是不执行 JavaScript,不请求任何外部的 JavaScript。

开发者怎么才能知道是否发生了浏览器干涉?

When the intervention kicks in, all requests will have an intervention header applied to them, like so:

如果发生了干涉,所有的请求都会包含一个 intervention 头信息,如:

<https://www.chromestatus.com/features/4775088607985664>;level="warning"
复制代码
展开原文 The presence of the header is enough to indicate that the browser applied *some* sort of intervention, and the URL in the header will point to [more information about the specific intervention applied](https://www.chromestatus.com/features/4775088607985664).

There’s one notable exception: the main document does not appear to get the intervention header currently. Honestly, this may just be a bug as it’s not clear to me why the header wouldn’t be applied to the main document.

All requests (including the main document) will also have the save-data header set to on, but you shouldn’t rely on that as an indication of an intervention. The save-data header will be applied whenever the proxy is enabled (or, really, any proxy service or browser that supports the header), regardless of whether the browser applied any interventions.

If you’re actively testing, you can also fire up chrome://interventions-internals/ in Chrome on your device and follow the logs to confirm when the NOSCRIPT intervention has been applied.

intervention 头的存在已经足以说明浏览器启用了某种类型的干涉;而这个头信息里给出的 URL 指向的就是具体关于这种干涉的详细说明。

这里有一点需要注意:主文档不会出现 intervention 头。说实话,这一点在我看来就是一个 bug,因为我找不到主文档不需要携带 intervention 头的理由。

所有的请求 (包括主文档) 还会包含一个值设置为了 onsave-data 头信息,但你不能把它当做是否发生了干涉的标识。save-data 头会在浏览器的省流量代理(更确切地说是任何省流量代理服务或者任何支持这个头部的浏览器)开启后出现,不管浏览器是否有应用什么干涉。

另外,如果你正在进行测试,你可以在 Chrome 中打开 chrome://interventions-internals 地址,查看里面的日志信息来确认是否发生了 NOSCRIPT 干涉。

对于用户来说是这意味着什么?

For users, the intervention can be very effective for certain sites. I loaded up 10 different sites with the NOSCRIPT intervention enabled and disabled to see the difference.

对于用户来说,某些站点在浏览器干涉后效果很显著。我对 10 个不同的网站分别在开启和禁用 NOSCRIPT 干涉的状态下加载了他们,来观察他们之间的区别。

URL NOSCRIPT 下的大小 (KB) 原始大小 (KB) 大小变化
www.wayfair.com/ 164 3277 -95.0%
www.aliexpress.com/ 72 2150 -96.6%
www.linkedin.com/ 151 1536 -90.2%
www.reddit.com/ 295 1126 -73.8%
www.bbc.com/news 354 467 -24.2%
www.theatlantic.com/ 11673 2970 +293.0%
techcrunch.com/ 548 2867 -80.9%
www.theverge.com/ 68198 3174 +2048.4%
www.cnn.com/ 418 7784 -94.6%
www.nytimes.com/ 379 16650 -97.7%
展开原文 The two results that jump out right away as oddities are The Atlantic and The Verge which managed to get a whopping 293% and 2048% heavier without JavaScript. In case you’re curious (I was), it’s because they are doing a lot of lazy-loading of images with JavaScript. In situations where JavaScript is not available, they wrap a fallback image in a `` element. Unfortunately for visitors to both sites, several fallback images are massive—ranging from 1.6MB to 9.9MB.

When the optimization works, which is more often than not, it works very well. The minimal improvement was a 24% reduction in data usage, and the remaining sites shed between 74-98% of their bytes.

It’s possible you would get similar results from the LOFI preview (which displays placeholders instead of the site’s actual images by default) for many of these sites. It’s worth noting though that the NOSCRIPT intervention has the added benefit of reducing the amount of work the actual device has to do. Images may account for the majority of network weight, but on the CPU, JavaScript is the worst offender by far.

其中的两条结果非常引入注目让人感到怪异,分别是 theatlantic 网站和 theverge 网站;在没有 JavaScript 的情况下,他们分别变重了 293% 和 2048%。你可能好奇它的原因(我也是),其实是因为他们都有采用 JavaScript 来延迟加载大量图片,而在 JavaScript 不可用的情况下,这些图片会用他们在 <noscript> 里包裹起来的图片做替代,不过这两个网站的访客都很不幸,两个网站的好些替代图片都是大体积的——范围从 1.6MB 到 9.9MB 不等。

当这些优化启用后,效果还是很不错的——比没启用要好。最小的提升也有节省到 24% 的流量,其他网站则分布在 74-98% 这个范围。

对于大多数网站来说,在 LOFT 预览效果下也可以得到同样的效果。不过值得注意的区别是,NOSCRIPT 干涉另外还有减少设备的工作量的效果。对于网络来说,可能图片是最主要的影响因素;而对于 CPU 来说,JavaScript 始终都是最怀“恶意”的

对于网站所有者来说这意味着什么?

展开原文 Whenever something like this comes up, naturally people want to know how to make it so that their site isn’t negatively impacted. The appropriate response is to make sure you serve a usable experience even if JavaScript isn’t enabled. That doesn’t mean you can’t use React, Vue or the like—but it does mean you should use server-side rendering if you do. The less your site relies on client-side JavaScript, the better it will appear when the intervention is applied. Treat JavaScript as an enhancement and you’re good to go.

The BBC site is a good example. Below you can see the mobile site (left) and the NOSCRIPT preview (right). There is very little difference. The branding is retained, and the content is readable.

当这种情况出现时,人们很自然地会想知道如何应对才能不对他们的网站产生负面影响。正确的相应措施是,确保即便在 JavaScript 没有启用的状态下,也能提供有用的体验。这不是说你不能使用 React、Vue 或者其他——而是说如果你可以的话你应该采用服务端渲染。你的网站对客户端脚本依赖度越小,当这种干涉发生时,其效果就会更好。

BBC 网站是一个很好的例子。下图左边是它的移动端网站,右边是它的 NOSCRIPT 预览效果;基本上没有什么区别,商标保留了下来,内容也是可阅读的。

The BBC site is a great example of how good the NOSCRIPT preview can look when JavaScript is treated as progressive enhancement: all the content and branding is in place.

对比 Engadget 网站,其在 NOSCRIPT 预览下展示的就是一片空白:

Since Engadget requires JavaScript to display their content, the NOSCRIPT preview is blank.

而 AliExpress 则只是展示了变种的导航出来,但却没有商标:

AliExpress.com shows at least a little navigation in the NOSCRIPT preview, but there's no branding without JavaScript enabled.

展开原文 You can, technically, opt-out of the intervention altogether by setting `Cache-control: no-transform` on your main request. The `no-transform` value tells proxy services not to modify any requests or resources and the intervention respects that: applying it ensures no one will ever see a NOSCRIPT preview for your site.

But use this with extreme caution. I’ve always been incredibly uneasy about using the no-transform value to opt out of proxies. Users are choosing those proxy services or browsers intentionally. They’re opting into these sort of optimizations and interventions and it feels a bit uncomfortable to me when developers overrule those decisions.

If you are going to opt-out using the no-transform value, then at least make sure you’re making ample use of the save-data header to reduce weight wherever you can: eliminating web fonts, serving low-quality images, etc.

从技术来说,你可以通过在你的主请求的头部中设置一个 Cache-control: no-transform 来避开这种干涉。这个 no-transform 值的意思是告诉代理服务不要修改任何请求或资源,而从这种干涉角度来说意思是:确保你的站点不要向任何人启用 NOSCRIPT 预览。

不过在使用它的时候要特别小心。使用 no-transform 值来避开代理的这种做法,总是使我感到异常的不安;因为用户选择这些代理服务或者浏览器都是主观的,他们希望采取这些类型的优化和干涉;而如果开发者否决了用户的这些决定的,这会让我感觉有些不太自然。

如果你确实决定采用 no-transform 值来避开干涉,那么至少请确保尽量大幅使用 save-data 头来减少网站大小:如消除 Web 字体、用低质量的图片代理等等。

这其实是一件好事

展开原文 Long story short, the NOSCRIPT intervention looks like a really great feature for users. More often than not it provides significant reduction in data usage, not to mention the reduction in CPU time—no small thing for the many, many people running affordable, low-powered devices.

The Chrome folks, as you would expect, aren’t being haphazard with the intervention either. In fact, by (at least initially) relying on a whitelist, they’re being pretty conservative with it. It’s just one of many tricks in their bag to provide a more performant experience and they appear to be treading carefully when it comes to applying it.

What I love most about the intervention is the attention it has gotten from developers. JavaScript isn’t a given. Things go wrong.

I have mixed feelings about Google’s influence on the web (a subject for another post, perhaps) but bringing a little more attention to the reality that we can’t always rely on JavaScript (and providing a much more usable experience for many in the process) is something I can get behind.

长话短说,NOSCRIPT 干涉看上去是一个对用户来说真的很不错的特性。它提供的不只是大幅度的流量节省,也不只是 CPU 的耗时的降低——大量,大量使用平价的、底性能设备的用户不再需要下载各种小件小件的东西(指 JavaScript —— 译注)。

Chrome 团队并不是没有计划地实施这种干涉。从他们依赖白名单的做法就可以看出来,他们还是比较稳重保守的。这只是他们身怀的可以带来更好性能体验的众多技巧之一,而且在实施这些技巧时,他们也是仔细稳重的。

对于这种干涉,我最喜爱的一点是开发人员对它的看法:JavaScript isn’t a given (JavaScript 不是一种赠予),Things go wrong (事情变糟糕了)

我对谷歌在 Web 方面的影响感情上是比较复杂的 (这个话题可能会在另一篇帖子中说),但是将我们的一点注意力回归到“我们不可能总是依赖 JavaScript”的现实这一点上 (以及正在实施为许多人带来更有用的体验),我还是非常支持它的。

猜你喜欢

转载自juejin.im/post/5ba90a16f265da0a9223b13c
今日推荐