[譯] 詳解 Chrome 的 NOSCRIPT 干涉

西樓聽雨發表於2018-09-24

原文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”的現實這一點上 (以及正在實施為許多人帶來更有用的體驗),我還是非常支援它的。

相關文章