55 comments

[ 3.3 ms ] story [ 97.5 ms ] thread
Isnt that already possible with mhtml?

https://en.m.wikipedia.org/wiki/MHTML

Mhtml tends to not have JavaScript run with it because there is no origin attached to it. That's one of the benefits of web bundles, they can run with an origin attached so they have access to the correct storage and other sandboxing primitives.
I don't really get what the advantage is for making an big atomic blob as the resource vs independently updateable pieces as h2 streams / etags / client cacheable.

It's just PUSH gone crazy?

I think one of the reason larger companies like them is because they may end ad blockers once and for all.

You can read a discussion about some of the issues that it causes here - https://github.com/WICG/webpackage/issues/551 Of course, the Brave browser also have some concerns about it - https://brave.com/webbundles-harmful-to-content-blocking-sec...

Widely disputed.

If this really did prevent ad blocking no one would expect it to ship. Inside the bundle are the same resources as without a bundle.

Same resources with the same URLs, access with the same request/response pipeline that's just as visible to blockers. If you can change URLs in the bundle, you can change them outside the bundle.

UAs are also completely free to request a resource from the URL rather than the bundle.

People have been saying "AMP prevents adblockers" since the introduction of AMP, and it has never been true. Advertisers don't want to bundle their ads with the content, they can't make any money that way. they want their ads to be dynamically requested each time they are drawn so they can sell ads based on real-time conditions. A standards-based implementation of AMP won't change this.

Brave's assertion that "bundles are like PDF" is actually a pretty good analogy - you don't see a whole lot of ad networks popping up trying to sell ad space in PDFs, do you?

I can see the advantages, for example I could send you a page as an email attachment without any problems. There’s clearly a use for it because browsers let you do (more or less) this with their own custom formats.
A huge fraction of sites today are already bundled, just poorly. WebBundles solves the problem that devs are already working around with tools.

HTML, JavaScript, CSS and images are not natively bundleable. So tools like Webpack and Rollup dramatically transform the files to be able to bundle them. JavaScript is recompiled into a single file so that it's impossible to cache the individual files, and many features like dynamic import, asset fetches, and import.meta.url are partially broken.

CSS is concatenated, against breaking caching and preventing the use of individual files in separate CSS scopes.

WebBundles actually bundles the real files that would have been sent unbundled, and it works with any file/response type. WebBundles have much better compressibility than the unbundled files. So it's is both a better HTTP/2 push, and a better version of what sites are doing with tools.

And since WebBundles work with the existing request/response pipeline, the files are individually fed into the network cache (and blockers, btw), which makes it possible to build delta bundles that only include updated files. This gives you the best of both worlds of bundled and unbundled serving.

> JavaScript is recompiled into a single file

That world has largely moved to "chunks", where there are multiple bundles loaded on-demand, based on e.g. user navigating to a less-used part of the web app. Going to a single file as a WebBundle would be downgrade in features.

Replacing those JS transforming kludges with a reasonable file format sounds useful, though, and allows combining JS+CSS+images in a new way.

It does sound awfully lot like HTTP Push, which as far as I know is largely unused because the idea that the server knows what the client wants hasn't really proven true.

Why would WebBundles be a downgrade? If you currently serve multiple Rollup bundles, you can instead serve multiple WebBundles.
WebBundles exist so that AMP content can look like it came from the original site instead.

(I understand that the technology is technically neutral, but AMP is the practical reason why Google is pushing WebBundles.)

> Brave concerns about WebBundles are legit in a location-based addressing Internet, but all of them would immediately be removed the moment we switch from a location-based addressing to a content-based addressing approach for the Internet.

I failed to find any good case being made for why content-addressable content would be any less likely to try to perform malicious actions than URL-addressed content. Is this just utopian wishful thinking or did I miss something?

I think it’s because with content addressable URLs, the URL is a hash and you can verify that the content never changes? But not 100% sure
Right. But that only works for resources whose initial version is fully trusted (due to review or trust in its source), and which never change. Which doesn't cover a lot of the usefulness of the web.
Brave's concerns aren't legit though. WebBundles don't change the request/response system or origin model of the web. They really don't change URLs or blocker abilities at all. Brave is ascribing them either powers they don't have, or that you can already do with plain servers.
What’s the origin for addressable content?
Whatever Signed HTTP Exchange it can successfully claim. The whole point of this work is to separate origin from where you managed to download the bytes from.

Imagine CDNs that cannot forge content for your site.

Okay, so for single source content I can either derive or assert an origin. Composition, not so much...
The address of the content is a hash of the content. It’s trivial for even low power devices to verify the content they revived matches the address they requested.
We are moving by increments toward not letting content on a page send information directly to a separate origin.

With content addressable networks, it would be a challenge to enforce this, which implies rolling back security improvements, which means security regression.

For interactive content, at least part of the page has to have an origin. Maybe only the root document get an origin, and the rest gets none or the same?

But then what happens with domain expiry?

It may mean that interactive documents require a web server, even if the bulk of the page, or even a document tree, is stitched together from addressable content.

WebBundles are the CDROMs of 2020 and solve nothing for the end user. It’s all about those ads.
the continued trend of overcomplicating things with 100 frameworks. i miss ftp'ing my html site to geocities
"build process" for a webpage nowadays.. hahaha i got into web stuff for being interpreted and instant results, and now you gotta compile your bundles.
Are you claiming that everyone should stop using Webpack and Rollup too?
I know that rollup in particular is intended to collect all your JS modules, somewhat like an .a file in your filesystem, but Webpack can easily combine all the assets.

In both cases you’re downloading globs of stuff that could already be in your cache, or that you don’t want to download at all (e.g. ads). I have never approved of efforts to turn the web into a “TV remote with a ‘Buy’ button” (which stretches back decades) but indeed, I consider such projects pernicious.

The Brave post was discussed here extensively a few days ago, with several people (including me) pointing out how the author misunderstands what can be done today and what bundles make easier: https://news.ycombinator.com/item?id=24274968

Afterwards I wrote up a response, explaining how bundles don't facilitate adblocker circumvention: https://www.jefftk.com/p/webbundles-and-url-randomization

(Disclosure: I work on ads at Google)

> Everyone who visits the site will need essentially all of these files.

Not necessarily.

For instance, I wholly block JavaScript and as a result I could avoid downloading ~283 KB of JavaScript resources from your page (out of ~412 KB resources in total). I could read your page fine.

If I understand correctly, with a WebBundle there would be no way for me to avoid downloading resources which are explicitly meant to not be downloaded by the way I configured my user agent?

Nearly all of the JavaScript on my page comes from two third-party loads: ga.js and gpt.js. As I describe in the post, bundling wouldn't work well for including third-party resources (for the same reasons that it is uncommon for sites to proxy third-party resources onto their own domains today).

Specifically in the case of first party JavaScript, however, you are right. A site might decide to serve all of its first party resources in a bundle, and people who don't run JS would end up downloading some extra bytes.

This is a situation we commonly have already, however, when there is HTML or CSS that is only ever used when activated by JavaScript. I do think you're right that this would mean people in your position would end up downloading slightly more useless bytes, but not by a large fraction?

> Nearly all of the JavaScript on my page comes from two third-party loads: ga.js and gpt.js

Well if you're using Google Analytics and Publisher Tags, you're not the kind of person to care about your users' experience anyway...

My visitors who don't want analytics/ads run ad blockers, and won't show up in my analytics or load my ads. That seems like a fine solution?

The ads are relatively unobtrusive, all the way at the bottom of the page.

> it is uncommon for sites to proxy third-party resources onto their own domains

Isn't the purpose of Signed HTTP Exchanges to be able to deliver 3rd-party resources from another domain?

That would leave Google Ads at the mercy of people updating their local copies, to make any changes. I doubt they want that.
It would also make it difficult to canary new versions of JavaScript by serving a new version to only a small fraction of traffic.
First, WebBundles and Signed HTTP Exchanges (SXG) are separate proposals. A bundle lets you serve multiple resources and response to a single request, while SXG lets one site serve content from another site in a way that the browser can verify authenticity and integrity.

Snyder's post and my response are only about bundles (despite Snyder saying that he intends to treat multiple proposals in a single one).

> Isn't the purpose of Signed HTTP Exchanges to be able to deliver 3rd-party resources from another domain?

Essentially, but only in cases where the origin matters. JavaScript doesn't care about its origin: all that matters is that the right code. Loading adsbygoogle.js from a Google domain vs the publisher rehosting it on their own domain both results in the same script execution.

Where origin matters is primarily in the URL bar. SXG allows one site (ex: search engine, social network, content aggregator) to speed up navigation to another site. Browsers have, over time, experimented with various forms of page preloading. They all have the problem, however, that the site being preloaded needed to be contacted to request the page. This is a problem from a privacy perspective, because if you search for "mattress" on a search engine, the search engine is reasonably confident you're going to click on the first result and hints to the browser that a preload would be a good idea, the site gets a hit from your browser whether or not you end up visiting the page. Now the operators of the first hit page have learned that you are likely searching for mattresses. SXG allows destination pages to opt into allowing the originating page to cache a copy for a limited time, giving you privacy preserving preloading. This is another approach to the main problem that AMP tried to solve: instead of only working if pages follow a declarative spec, it works on any page that opts in but it requires an extension to the spec and some browser work.

There is a very simple way in which WebBundles will be used to bypass ad blockers:

The tool to create WebBundles will, in all likelihood, be created and maintained by Google. Google will program this tool to detect script tags with a src of ads.google.com/js/adscript.js and replace them with a local copy of the ad script embedded in the bundle. (They may do this by calling the feature something like "embed common third party resources" and also use it for files like jQuery and Google Fonts.) Then, adblockers will be unable to block the ad script, because it appears with a different path in each bundle.

In other words, you're right that randomizing URLs to evade ad-blockers requires server-side coordination. Conveniently, though, adopting WebBundles also requires server-side coordination, with the same company that stands to benefit from ad-blocker evasion.

Nothing about this is different than what exists today. Anybody can, and many sites already do, host their own copy of ga.js or google fonts or anything else so that all the resources come from their own domain.

You can still block the effects by preventing access to the domain where the ad info is coming from.

I don't think what you're describing is at all likely, but let's accept the scenario for the sake of argument. The bundle ends up including the advertising JS, ok. This is the JS that inspects the environment on the page and sends the ad request. Then the ad blocker can just block the ad request.
I'm curious which part you think is unlikely: that Google will make a tool to create WebBundles (what, are they just going to sit on their hands and wait for someone else to write one?), that that tool will include well-known third-party resources in the bundle as a performance optimization (reduce the number of connections needed to load your bundle! browsers no longer cache resources across origins!), or that the Google Ads script is such a third-party resource?

The difference between blocking an ad script by URL and blocking a request sent by an embedded ad script is that the script can include arbitrarily complex logic to generate the URL to request. I would not be surprised at all if that logic starts getting more and more complex and hard to analyze -- perhaps under the guise of "reducing ad fraud" -- and starts generating URLs that can't easily by blocked by Manifest v3 ad-blockers without breaking non-ad functionality.

> that Google will make a tool to create WebBundles

The tool exists: https://github.com/WICG/webpackage/tree/master/go/bundle

> that tool will include well-known third-party resources in the bundle as a performance optimization

The tool doesn't do that. You tell gen-bundle what you want included and it builds the bundle.

You could imagine someone writing a easier to use tool that inspects your website and packages up everything it needs to make your website run, but including third-party resources that are cache-control:private (as Google ads scripts are) wouldn't work! For example, many third parties use user-agent sniffing to serve JS optimized for that particular browser.

> the Google Ads script is such a third-party resource?

Imagining for the moment there was a tool like this and a way for scripts to indicate whether they should be includable, I don't think Google Ads scripts would be likely to opt in for the same reasons that Google Ads discourages publishers from rehosting these scripts today.

> I would not be surprised at all if that logic starts getting more and more complex and hard to analyze.

As long as third-party cookies are still a thing, ad requests are still going to go to well known domains, because otherwise they won't get the cookie.

I see the next step in the ad blocking arms race as sites CNAMEing over to an ad network which reverse proxies their site. The network is then in a position to rewrite anything they want as inscrutably as they choose. This is a service you can buy (from others) today. I really hope this doesn't become widespread: even though the particular ad network I work for would likely do very well if the world went this way, it would even further promote centralization in the industry.

> [...] including third-party resources that are cache-control:private (as Google ads scripts are) wouldn't work! For example, many third parties use user-agent sniffing to serve JS optimized for that particular browser.

This is relatively easy to work around: only embed resources that are included with SRI or match a whitelist of commonly-used third-party resources that don't do this.

And yes, Google Ads would either need to change its stance on rehosting or write a "wrapper" that uses the arbitrarily-complex JavaScript to generate the path from which to download the real ad script. Both of these seem like things they could plausibly do.

> As long as third-party cookies are still a thing, ad requests are still going to go to well known domains, because otherwise they won't get the cookie.

Google owns several well-known domains, such as "google.com", that ad-blockers can't just blanket deny access to because that would break non-advertising functionality.

> I see the next step in the ad blocking arms race as sites CNAMEing over to an ad network which reverse proxies their site.

This could work too (Google's currently developing their own version of this, which I think they call the "AMP cache"), but you're right about the drawbacks and it makes sense for them to be trying multiple approaches to see what sticks. After all, ad blockers are an existential threat to their primary revenue source!

> only embed resources that are included with SRI or match a whitelist of commonly-used third-party resources that don't do this

Essentially zero SAAS third-party resources are set up to be included with SRI, because (as you might expect) none of these third parties want to commit to serving one version indefinitely.

> ad-blockers can't just blanket deny access to because that would break non-advertising functionality

Good point! I wasn't thinking about how that played out with Google (since display ads today are served from a doubleclick domain). Pretty much anyone running an ad blocker is also going to be blocking third-party cookies, though, so routing the ad request via a proxy on the publisher domain would work even better.

> Google's currently developing their own version of this, which I think they call the "AMP cache"

AMP doesn't contain anti-adblocking, and an anti-adblocking-via-inscrutable-js approach would be incompatible with AMP's policy of requiring that all AMP code, including extensions, be open source. For example, this is the code that requests AdSense ads and renders the responses: https://github.com/ampproject/amphtml/blob/master/extensions...

> Essentially zero SAAS third-party resources are set up to be included with SRI

Right, but jQuery often is, which lets you sell people on the feature by saying it's for jQuery. The whitelist is just in case people forgot the SRI on their jQuery, and hey, why not throw a couple other trustworthy scripts on there while we're at it?

> AMP doesn't contain anti-adblocking, and an anti-adblocking-via-inscrutable-js approach would be incompatible with AMP's policy of requiring that all AMP code, including extensions, be open source.

Again, "Google currently has internal policies forbidding it" isn't a good argument that Google won't do something, especially when they are working on setting up systems that give them the ability to do that thing. Google used to have a policy saying that ads could never go in the same column as search results, but ad revenue turned out to be important to Google, so they changed that policy.

(In AMP's specific case, you might not even need inscrutable JS since pages are served from google.com and thus already include the tracking cookies. Just swap in the personalized ads server-side.)

> Right, but jQuery often is, which lets you sell people on the feature by saying it's for jQuery. The whitelist is just in case people forgot the SRI on their jQuery

There's a huge difference between libraries (versioned, can use SRI, open source, don't have canonical URLs) vs services (none of those, change a lot, JS you reference on your page is generally only the first link in a long chain of JS). When I worked on mod_pagespeed (disclosure: at the time a Google project) we had the "Canonicalize JavaScript Libraries" feature (https://www.modpagespeed.com/doc/filter-canonicalize-js) which similarly only operated on libraries.

> why not throw a couple other trustworthy scripts on there while we're at it?

I'm still confused how you're imagining this working. The bundler inspects the site (really hard!) and packages up the resources? If you're doing that, "trustworthy" isn't a thing the bundler would decide: the site owner has indicated their trust by referencing the JS in their page source (directly or indirectly).

> "Google currently has internal policies forbidding it"

While Google started the AMP project and is its largest contributor, it's now an external project at the OpenJS foundation: https://openjsf.org/blog/2019/10/10/openjs-foundation-welcom... Modifying AMP policies to allow ad networks to run non-open source JS at the top level where it can't easily be blocked would be completely politically impractical.

> In AMP's specific case, you might not even need inscrutable JS since pages are served from google.com and thus already include the tracking cookies

As sites adopt SXG this wouldn't work. From the browser's perspective a site that is served from site A and signed for site B is not connected to site A, and site A's cookies won't be included on the request.

WebBundles seem like they would be a useful format for distributing PWAs - like a web standard alternative to Android's APK files.
I'm wondering if IPFS or other content-addressable networks handle version updates for documents as well as git handles code?

It might be nice to make websites that are more like PDF's that can be redistributed, downloaded, and stored. But when there are many versions of immutable content, the result is a mess, with people having random versions distributed all over the place. Having built-in history and being able to sync to HEAD would make this a lot easier.

While I get the argument that things vaguely like AMP could be used with IPFS, these WebBundles in particular catting everything together would seem to undermine IPFS's ability to dedup. No thanks.
So basically we can give up HTTPS for origin authentication (leave it for encryption/privacy) assuming the bundles are all signed?