<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Industrial Empathy</title>
	
	<subtitle>Malte Ubl&#39;s literal website</subtitle>
	
	<link href="https://www.industrialempathy.com/feed/feed.xml" rel="self"/>
	<link href="https://www.industrialempathy.com"/>
	<updated>2022-11-15T00:07:16Z</updated>
	<id>https://www.industrialempathy.com</id>
	<author>
		<name>Malte Ubl</name>
		<uri>https://www.industrialempathy.com/about/</uri>
	</author>
	
	
	
	
	
	
	<entry>
		<title>New on the web platform in November, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/november-2022.html"/>
		<updated>2022-11-03T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/november-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1586572028970029056&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;It may take an extra 6 months, but This Is Happening™️&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1586572028970029056&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1584659055221547008&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…which is why we get solid Safari releases&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1584659055221547008&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1583064493688426503&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…and useful privacy feature only 7 years late.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1583064493688426503&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1579763417778642944&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I believe it when it ships&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1579763417778642944&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1581408335320207362&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Nobody really knows why this is good, but it aligns Blink with Gecko&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1581408335320207362&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1581324896310681600&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;More support for CSS-only UI&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1581324896310681600&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1580735603989450753&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Pre-rendering is back in Chrome. Now also for &amp;#39;same-site&amp;#39; navigations (e.g. foo.example.com and bar.example.com)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1580735603989450753&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1580135502635671552&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Seems useful&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1580135502635671552&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1578703424190697473&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This API seems underappreciated?&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1578703424190697473&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1587082079698706432&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Shopify buys Remix&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1587082079698706432&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1586378504563826693&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;JXL is not coming to Chrome. But JXL features may come to JPEG 🤯&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1586378504563826693&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1585649035767152646&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;RIP document.domain&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1585649035767152646&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1585579026428710912&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;One of the weirdest gotchas of the web platform: with CORS mode you can control whether to send cookies BUT the HTTP cache might respond with a result that was fetched using a different CORS mode.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1585579026428710912&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1584963010170347520&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Next.js 13!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1584963010170347520&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1587629291529015298&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Using custom fonts well on the web is finally somewhat easy&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1587629291529015298&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fnovember-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in October, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/october-2022.html"/>
		<updated>2022-10-06T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/october-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1567279577160126464&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;If you ship one thing today, make it this&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1567279577160126464&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1567619047847591937&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The best Chrome feature of the millennium (link to text fragment) is coming to Safari! &amp;quot;Implemented full search for text directives for Scroll to Text Fragment spec&amp;quot;&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1567619047847591937&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1569500761637421056&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Grumble&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1569500761637421056&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1570784912856485888&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Shared Element Transitions seem to be happening&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1570784912856485888&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1571850732755898368&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;O(features uses) JS frameworks are becoming mainstream accessible&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1571850732755898368&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1572133176633425924&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Good Riddance&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1572133176633425924&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1572710132408254466&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Hope that this actually gets released quickly&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1572710132408254466&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1572589757384871937&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;MOAH CPU&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1572589757384871937&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1572668106136489986&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The SQLite on the web API is coming to Android&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1572668106136489986&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1573499115622776843&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Visual viewport sizing gets cross browser compat&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1573499115622776843&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1574349759590146049&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;And same for logical viewport units&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1574349759590146049&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1574477383540744192&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;You should probably not use this, but it exists&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1574477383540744192&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1574385485970956288&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;ShadowDOM may become usable for non-specialized use cases&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1574385485970956288&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1576357353888264193&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…because this is the other missing link&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1576357353888264193&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1575029095972634627&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;INP debugging&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1575029095972634627&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1574657989256302593&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The end of SPA-discrimination in Core Web Vitals is in sight&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1574657989256302593&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1576951638325186565&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Seems like a great idea&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1576951638325186565&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1577652806936403973&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;A billion IOT owners sigh in relieve&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1577652806936403973&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1577590832617627648&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The security-theater certificates are no longer slow&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1577590832617627648&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Foctober-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in September, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/september-2022.html"/>
		<updated>2022-09-01T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/september-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1564200362013245441&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AVIF is amazing, and even better for boring images&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1564200362013245441&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1563097754322501632&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;WP Optimize is fraud&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1563097754322501632&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1563087798680588290&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Good trend: good defaults for `prefers-reduced-motion`&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1563087798680588290&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1562563956710842368&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Attempt to fix DLL Hell for custom elements&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1562563956710842368&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1562248114773565440&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Bun got financing&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1562248114773565440&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1560162799594217474&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Modern pre-rendering is coming to desktop on Chrome&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1560162799594217474&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1559449034628243456&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1559449034628243456&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1558928195553878020&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Life-saver for multi-Chrome-profile livings&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1558928195553878020&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1558295463131901952&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;TIL that WebKit doesn&amp;#39;t have site isolation yet&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1558295463131901952&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1557740150603804672&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Lots of WebView drama this month. One thread here…&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1557740150603804672&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1560443301580390401&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;OriginFileSystem coming to the last browser. SQLite is back on the web!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1560443301580390401&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fseptember-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>The fallacy of “thriving in ambiguity”</title>
		<link href="https://www.industrialempathy.com/posts/thriving-in-ambiguity/"/>
		<updated>2022-08-29T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/thriving-in-ambiguity/</id>
		<content type="html">
		  
		    &lt;p&gt;A key mantra in Google’s work culture and across big tech is &lt;em&gt;“thriving in ambiguity”&lt;/em&gt;: The ability to make progress and make good decisions in the presence of uncertainty around the future in general and the interpretation of the data available today.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.glitch.global/c8c30f0d-7656-4211-9f84-bcc8d3e9a7b2/devon-mackay-s6UTcIu5YYI-unsplash.jpg?v=1661698673891&quot; alt=&quot;Foggy train lights showing red and yellow signals&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It is very human to be uncomfortable with ambiguity. It can be very nice to just follow procedure and execute on a well laid out plan pointing toward a known objective. And reality is that many jobs are like that. You learn it, you progress your skills, and while you may face many challenges along the way, the solutions stay within a relatively tight framework of the job description.&lt;/p&gt;
&lt;p&gt;“Thriving in ambiguity” means to do well when all of that is not the case. You have to dynamically adapt, rapidly learn new skills, execute, pivot, be willing to cut your losses, and do it all over again as new information emerges–all without knowing you are on the right track.&lt;/p&gt;
&lt;p&gt;I’m all for learning to be more comfortable with ambiguity. I might even be good at it. But this post is about when “thriving in ambiguity” is a potential fallacy and how to do even better.&lt;/p&gt;
&lt;h4 id=&quot;my-basic-thesis-is%3A-ambiguity-is-bad&quot;&gt;My basic thesis is: Ambiguity is bad &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/thriving-in-ambiguity/#my-basic-thesis-is%3A-ambiguity-is-bad&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;My basic thesis is: Ambiguity is bad. You should thrive in it, sure, but you should also strive to eliminate it whenever possible.&lt;/p&gt;
&lt;h4 id=&quot;ambiguity-is-bad-because-it-impacts-the-efficiency-of-communication&quot;&gt;Ambiguity is bad because it impacts the efficiency of communication &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/thriving-in-ambiguity/#ambiguity-is-bad-because-it-impacts-the-efficiency-of-communication&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I’ve seen many teams that couldn’t decide on what the right path forward is. Subsequently, all communication needs to be qualified: “Assuming for a bit that X is true, we should do Y”. What inevitably happens is that someone doesn’t add the qualification and now every listener makes their own assumptions which scenario of possible futures the speaker likely meant. Typically folks eventually figure out when they got the interpretation of the scenario wrong but only after lots of time has been lost to folks arguing over things only to find out they were operating under different basic assumptions.&lt;/p&gt;
&lt;h4 id=&quot;ambiguity-is-bad-because-it-has-opportunity-cost&quot;&gt;Ambiguity is bad because it has opportunity cost &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/thriving-in-ambiguity/#ambiguity-is-bad-because-it-has-opportunity-cost&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;If you hedge your bets due to inability to make the right decision, you’re likely not executing as well on the options as if you’d concentrated on a single one. A question I’m often asking my teams is “Is the maximum delta in outcome between two options actually bigger than the cost of reduced focus in execution?” More often than not, the answer is no. In that case you are better off focusing on one option, and doing it truly well.&lt;/p&gt;
&lt;h4 id=&quot;%E2%80%9Cthriving-in-ambiguity%E2%80%9D-can-cloud-your-judgment&quot;&gt;“Thriving in ambiguity” can cloud your judgment &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/thriving-in-ambiguity/#%E2%80%9Cthriving-in-ambiguity%E2%80%9D-can-cloud-your-judgment&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Finally, “thriving in ambiguity” can cloud your judgment such that you end up treating every situation as if it was truly ambiguous. Some things are actually clear and simple, but I’ve seen teams run the “ambiguity playbook” without critically thinking about the necessity. That makes you and your team less efficient and effective. Instead try to always think about the &lt;a href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#understanding-the-degree-of-uncertainty&quot;&gt;degree of uncertainty&lt;/a&gt; and tailor your behavior to it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In summary:&lt;/strong&gt; Thrive in ambiguity, but be aware of the way it impacts your team communication, its opportunity cost, and make a habit out of critically thinking about whether a situation is truly ambiguous.&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fthriving-in-ambiguity%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=The%20fallacy%20of%20%E2%80%9Cthriving%20in%20ambiguity%E2%80%9D&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in August, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/august-2022.html"/>
		<updated>2022-08-11T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/august-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1546492889051660288&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Both are fine&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1546492889051660288&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1546966967361363970&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;INP clarified: Time from physical event until next paint would be possible.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1546966967361363970&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1557027549854801921&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;One weird trick to improve INP in React&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1557027549854801921&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1547698700872388616&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AVIF everywhere&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1547698700872388616&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1552051074244247554&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;CPU pressure API&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1552051074244247554&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1552242561313546241&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Don&amp;#39;t bother with DocumentFragment&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1552242561313546241&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1554051101065969667&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Almost-default-lazy 3P iframes experiment in Chromium&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1554051101065969667&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1554838542836195328&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;has and container queries. Has is now everywhere&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1554838542836195328&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1555152945347543043&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This is interesting, but I&amp;#39;m highly doubtful it is a good idea. The difficulty in loading the right font subset was in quickly finding the subset, not so much in loading that subset.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1555152945347543043&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1556715925235195906&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Observability for `content-visibility: auto`&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1556715925235195906&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1557036448712237056&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Approved&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1557036448712237056&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Faugust-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in July, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/july-2022.html"/>
		<updated>2022-07-07T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/july-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1544557136071782400&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;iOS browser-diversity is going to be the law of the land in the EU&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1544557136071782400&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1544460933753229312&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;We&amp;#39;re continuing to explore the JS execution environment trade-off space&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1544460933753229312&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1544313605579018240&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;`setTimeout(…, 0)` may actually mean 0 more often soon&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1544313605579018240&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1543907538953011200&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Neat idea to use Brotli with PNG. But also: Use lossless WebP&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1543907538953011200&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1541817494469574656&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I helped make some edge computing&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1541817494469574656&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1541515875257356290&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Client-hint for how large the user screen is!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1541515875257356290&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1540746480801091584&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1540746480801091584&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1540697894683942912&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;It&amp;#39;s happening!™️ AVIF coming to Apple devices&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1540697894683942912&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1539727761501192193&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The most ungeneric web API yet!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1539727761501192193&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1539322190541295616&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Send preload headers without deciding on the HTTP status code!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1539322190541295616&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1537062212497440768&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Rest in Pieces&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1537062212497440768&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1536817442579746818&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;New CruX data with bigger coverage (due to changes in the way data is collected that pushes more origins above the K-anonymity threshold)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1536817442579746818&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1536759057066782720&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Interview with your&amp;#39;s truly&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1536759057066782720&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1536026245951115264&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Very useful&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1536026245951115264&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjuly-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in June, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/june-2022.html"/>
		<updated>2022-06-02T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/june-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1436014840028479492&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This isn&amp;#39;t new but worth a PSA&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1436014840028479492&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1523649238504296456&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Standardization effort for Web API based server runtimes&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1523649238504296456&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1523865651907072000&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Start logging this to learn why you are not benefitting from free performance&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1523865651907072000&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1524994838999056384&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…and a way to turn off one major reason for no BFCache&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1524994838999056384&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1524014083145621505&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;It&amp;#39;s happening™️&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1524014083145621505&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1526135259355652096&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Also the literal opposite is happening&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1526135259355652096&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1524782819431555074&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This API proposal is a big deal. Primarily because it looks like it might be easy enough to use to get adoption&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1524782819431555074&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1525197896622018560&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Tooltip (etc.) positioning in CSS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1525197896622018560&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1527177857407107072&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Faster H3 discovery through DNS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1527177857407107072&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1527864441768972289&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Keep folks on their toes&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1527864441768972289&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1528728452949594113&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;$entropy--&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1528728452949594113&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1528670485411774464&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;&amp;#39;Looks to the left, looks to the right&amp;#39;.gif&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1528670485411774464&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1530612342894886913&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The USA is joining the browser-engine diversity regulation game&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1530612342894886913&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1528613166237863941&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Better async debugging&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1528613166237863941&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1529152467199569920&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#papercuts&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1529152467199569920&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1529562159147253760&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1529562159147253760&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1529586358586679301&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;ServiceWorker ☠️&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1529586358586679301&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1529871121092337664&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Attempt to bind cookies to their origin by default (rather than the weird legacy semantics from before origins were a thing)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1529871121092337664&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1530194638858072064&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;It was always weird that media queries didn&amp;#39;t support full boolean logic&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1530194638858072064&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1531926081644679170&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Browser-built-in HTML Sanitization. Will also be great for Deno and friends&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1531926081644679170&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjune-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in May, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/may-2022.html"/>
		<updated>2022-05-05T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/may-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1515011567267377152&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;We&amp;#39;re about to see many more users requesting reduced data usage&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1515011567267377152&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1517223821975056384&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Major speed-ups from privacy-preserving prefetching&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1517223821975056384&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1518621103362494465&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Rest in Pieces ☠️&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1518621103362494465&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1519673260794945539&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;US is seeking input on Apple&amp;#39;s browser engine monopoly&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1519673260794945539&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1517508673807040513&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The EU is going ahead banning Apple&amp;#39;s browser engine monopoly&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1517508673807040513&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Same in the UK.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Plus Apple is majorly staffing up the Safari team so they can actually compete in a fair environment.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;It&amp;#39;s happening™️&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1519511101330710537&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1519511101330710537&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1520172325840338944&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Sandbox➡️Prison&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1520172325840338944&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1517638340899741697&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Fewer lines of code to write!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1517638340899741697&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1518923779031851008&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Cross-site caching is coming back in a privacy-safe way&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1518923779031851008&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1518924375721873408&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I had known about this, but thought it was only impactful for legacy Windows and some Linuxes. But turns out that there is also a setting in MacOS that gets turned on when using a mouse that enables scrollbars that benefit from this change.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1518924375721873408&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1520042217380982785&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;If you adobt anything from today, make it this:&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1520042217380982785&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1520313247802564614&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I think &amp;quot;Window Controls Overlay&amp;quot; is significant not because that is particularly important but rather it shows how far web apps have come. Browsers are really now shipping the long tail of operating system integrations.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1520313247802564614&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1520492289138774018&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;☠️ to require&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1520492289138774018&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1520764642846404608&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;If you hide your content in your app, then your website will not rank well in Google.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1520764642846404608&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1521667976969310208&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Per-page TTFB now available&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1521667976969310208&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1521881349258362882&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Mobile PWA: Kind of Meh. Desktop PWA: On the road to 100% market share for Desktop apps.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1521881349258362882&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fmay-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in April, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/april-2022.html"/>
		<updated>2022-04-06T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/april-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1511817897336791049&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Fold estimation is the next frontier in web perf optimization&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1511817897336791049&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1499430915407233029&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Coordinated announcement by all browser makers&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1499430915407233029&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1501185994523123723&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;`content-visibility`, the CSS primitive for O(1) DOM layout cost without breaking a11y, is now in progress or shipped in all major browser engines.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1501185994523123723&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1501140291285401601&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;s/importance/fetchpriority&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1501140291285401601&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1509368397573726212&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…and shipping in Chromium&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1509368397573726212&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1501577379348729859&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;New responsiveness metric is available to read in CrUX&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1501577379348729859&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1508448330375966723&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Yet another PSA: Free performance&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1508448330375966723&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1501823138786594820&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;And Chromium is shipping away on the &amp;#39;veto reasons&amp;#39;&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1501823138786594820&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1503062447627771904&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Interesting decision to be made by browsers&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1503062447627771904&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1501634547921801216&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The non-runtime effectful parts of TS may soon be valid JS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1501634547921801216&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1503173378965868544&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AI in the browser&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1503173378965868544&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1503426064697151493&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Native lazy loading: 🍻, Navigation preload: You can now use ServiceWorkers for &amp;quot;websites&amp;quot; in Safari, Strict dynamic CSP: You can now use CSP in Safari, Viewport units: There are now units that work like you thought the old ones did, CSS cascade layers: 🤩&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1503426064697151493&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1504538758812680199&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This is a very important new feature making it possible to virtualize DOM (not to be mistaken with virtual DOM) in a way that it is still accessible to find-in-page. The most obvious use case is to markup the contents of accordion style UIs to automatically open on find.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1504538758812680199&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1505910162137108482&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Hardware AV1 decoding on Qualcomm and Intel&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1505910162137108482&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1506834588701581314&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Micro-frontend tech&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1506834588701581314&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1506996996313337862&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Native lazy loading is good&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1506996996313337862&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1507131147532136466&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This may also impact the #AppleBrowserBan&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1507131147532136466&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1507024739713404933&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;You can now pay for MDN&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1507024739713404933&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1508529225183203329&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Free performance win (if it is web compatible)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1508529225183203329&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1509620539333099528&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Yeah, we can&amp;#39;t have pre-cached npm, but we can have pre-cached Helvetica!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1509620539333099528&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1509808262249517056&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This looks really helpful&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1509808262249517056&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1509653389453324299&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Plus, it works for setters!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1509653389453324299&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1510301223085174784&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Why we can&amp;#39;t have nice things&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1510301223085174784&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1510957255256158210&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;One more browser on the way for bare imports&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1510957255256158210&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1510991943765045262&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;&amp;quot;A partner finished an experiment and confirmed that latency on their service is reduced by 45%.&amp;quot;&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1510991943765045262&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fapril-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>11 years at Google</title>
		<link href="https://www.industrialempathy.com/posts/11-years-at-google/"/>
		<updated>2022-03-04T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/11-years-at-google/</id>
		<content type="html">
		  
		    &lt;p&gt;On March 4th, 2022 was my last day at Google.&lt;/p&gt;
&lt;p&gt;It was an amazing 11+ years working with some of the most inspiring and talented colleagues one could imagine.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.glitch.global/5252f5a9-40a0-4a18-a67f-8b2fe6c57a82/Kopie%20von%2020170303_175206_OMR_Fr_Photographer-%20Rajko%20Hess.jpg?v=1646344106601&quot; alt=&quot;Me on stage&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As my final role, I was leading Google Search for Desktop computers. I still cannot believe they let me run the literal search engine. In fact, this was my first time leading a major consumer product after years of being focused on infrastructure, and to my own surprise, I was actually kind of good at it.&lt;/p&gt;
&lt;p&gt;Of all the code that I wrote, my favorite change was probably the introduction of SUPER_UNCOMPILED mode for JavaScript delivery during development. Prior to this, Google engineers would wait to compile their JS and debug unobfuscated but compiled code losing files, line numbers, etc. I managed to fix this before source maps were a thing, yet retaining 100% compatibility with the semantics of the compiled code.&lt;/p&gt;
&lt;p&gt;I later built a JS framework called &lt;a href=&quot;https://medium.com/@antin/photos-uses-an-internal-google-framework-wiz-89e2b7c8c1d5&quot;&gt;Wiz&lt;/a&gt; which is now powering Search, GMail, Photos, Drive, Meet, and many other consumer UIs. In hindsight, I should have open-sourced it, but at the time, I didn’t realize how relatively powerful and unique it was, and by now it badly needs an overhaul relative to modern framework developer experience.&lt;/p&gt;
&lt;p&gt;I got incredibly lucky with Wiz. Wiz was designed to be small and nimble specifically for G+ on Desktop with the goal of making it faster without slowing it down too much from the added page weight of a new framework. Turns out we never really used Wiz for that, but it was perfect for mobile web UIs on underpowered devices at the time leading to its broad adoption.&lt;/p&gt;
&lt;p&gt;As the next thing, me and my team built a similarly widely adopted end-to-end frontend framework and serving system for Google’s internal microservice platform. I contributed its UI-and-data-component abstraction, but the main kudos goes to &lt;a href=&quot;https://twitter.com/shubhie&quot;&gt;@shubhie&lt;/a&gt; for really opening our eyes to the &lt;a href=&quot;https://web.dev/conformance/&quot;&gt;power of using application-level linting for scaled software engineering&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Taking this idea, I ended up making a little thing called AMP. Let’s just say I learned a lot from it, and I think we ended up very successfully taking those lessons and applying them to the Page Experience ranking system based on &lt;a href=&quot;https://web.dev/vitals/&quot;&gt;Core Web Vitals&lt;/a&gt;–helping make the web much faster in the process.&lt;/p&gt;
&lt;p&gt;From this I moved on to work on the &lt;a href=&quot;https://www.google.com/&quot;&gt;Search Engine proper&lt;/a&gt;. I just cannot emphasize enough what a humbling experience it has been to work with the absolute top of the world class on this problem space. This is especially true for incredible data science and quantitative UXR teams which uplevel the professionalism and excellence of the product operations to levels I had never witnessed before, and which deeply influence how I will work in the future. Also, I got to &lt;a href=&quot;https://twitter.com/cramforce/status/1443962459723755533&quot;&gt;turn off Internet Explorer for the biggest website on the planet&lt;/a&gt;, so that was cool. :)&lt;/p&gt;
&lt;p&gt;The time at Google has been an incredible learning experience that I’ll be forever grateful for, and I’ll dearly miss my amazing colleagues. Throughout my career I’ve tried to follow a thread of finding invariants that eliminate the trade-offs between making it easy to write programs, yet achieving excellent user experience. I’ve learned a lot and there is still so much more to do in this space.&lt;/p&gt;
&lt;p&gt;That was 11 years in a few 100 words. Was it a good time? Yes. Should you work at Google? Yes, I’d recommend it. But for me &lt;a href=&quot;https://twitter.com/cramforce/status/1501241760223137794&quot;&gt;it is time to try something new!&lt;/a&gt;.&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2F11-years-at-google%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=11%20years%20at%20Google&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in March, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/march-2022.html"/>
		<updated>2022-03-02T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/march-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1488787854562050048&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;For less snark and Malte-bias check out Rachel&amp;#39;s new series with the same theme&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1488787854562050048&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1489499864874500100&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;We&amp;#39;re CORSing private network requests. This will be painful but is badly needed for IOT security&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1489499864874500100&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1488575639288430592&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Chromium is looking to ship full network state partitioning. We have already lost the HTTP cache shared between sites; with this things like H2/H3 connections H3 TLS resumption, &amp;amp; DNS cache are also partitioned. This substantially increases the perf impact of 3P resources.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1488575639288430592&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1490704355745742851&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;BFCache, also known as the one weird trick to make LCP be 0 milliseconds for all back navigations on your site, now has a dedicated tab in Chrome DevTools&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1490704355745742851&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1491020820441108484&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Trigger global exception handlers without breaking execution flow&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1491020820441108484&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1491456838746791938&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Compatibility data in MDN is no longer manually maintained!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1491456838746791938&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1491650913441701896&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;An API rises from the dead ☠&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1491650913441701896&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1492341495491592194&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Certificate transparency is diversifying&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1492341495491592194&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1492398000500404227&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Required reading&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1492398000500404227&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1493640985724657665&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;My main pet-peeve is being addressed&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1493640985724657665&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1493269749475815426&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I was shocked to learn that this wasn&amp;#39;t supported. But, yaihh, I guess&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1493269749475815426&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1493861901561962505&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Users know which sites you really use. This should be used more to pre-qualify permission prompts, etc.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1493861901561962505&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1493960208019869697&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This effect is extremely common. If you make your website demonstrably faster while the performance metrics measured in the field go down BUT your revenue (or whatever end to end gross business success metric you are using) goes up, then this is probably what is happening.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1493960208019869697&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1496052808180772867&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;`@layer` is cool&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1496052808180772867&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1496168446790352906&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Core Web Vitals ranking on Google Search for Desktop is launching&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1496168446790352906&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1494009110282452993&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Is it web news that Google Docs is finally abandoning the pager-page metaphor?&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1494009110282452993&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1498290774043394050&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Godspeed to the good folks fighting the #AppleBrowserBan&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1498290774043394050&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fmarch-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in February, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/february-2022.html"/>
		<updated>2022-02-02T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/february-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1481400411907137540&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Awesome to see continued innovation on the good old link&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1481400411907137540&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1482393022193152004&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Safari did not have a good month&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1482393022193152004&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1486405357417103361&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Actually it was very bad&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1486405357417103361&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1484893652728135685&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Even though Igalia tried their best to help out&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1484893652728135685&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1486548507305525249&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;And Apple is *trying* to staff up&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1486548507305525249&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1488060229921218561&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The pressure works&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1488060229921218561&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1488076338485469184&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Accelerated animations in Safari are subject to OS capability. Thread has details on bail-outs. Every browser will have such bail-outs.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1488076338485469184&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1484320287847972866&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Navigation preload in Safari is a big deal for ServiceWorker viability&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1484320287847972866&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1483892375223414785&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Custom Elements in React are progressing&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1483892375223414785&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1485357927405920256&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1485357927405920256&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1487199480160030721&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…related data (thanks to [Zouhir!](https://twitter.com/_zouhir))&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1487199480160030721&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1486448813468434435&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Great article looking at statistical trends for web dev in 2022&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1486448813468434435&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1487475749477093380&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Great to see more web APIs landing in Node. Thanks Deno for the competition!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1487475749477093380&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1488219715398868994&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Prefetch in a privacy-safe web&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1488219715398868994&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Ffebruary-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in January, 2022</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/january-2022.html"/>
		<updated>2022-01-12T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/january-2022.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1468631542352207872&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Container queries are being standardized&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1468631542352207872&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1468631395274838022&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Hell freezing over&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1468631395274838022&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1471604621470846979&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Actually working app history is landing&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1471604621470846979&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1471787071606079491&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Chrome DevTools catching up on a11y&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1471787071606079491&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1471942556468584454&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;You probably want AVIF, but this is the choice for very high quality images&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1471942556468584454&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1472837533843214336&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Super insightful performance improvement journey&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1472837533843214336&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1479406388535345152&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Colored fonts in browsers&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1479406388535345152&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1480594796267937795&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I did not know this&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1480594796267937795&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjanuary-2022.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Viral software deadlines</title>
		<link href="https://www.industrialempathy.com/posts/viral-software-deadlines/"/>
		<updated>2022-01-03T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/viral-software-deadlines/</id>
		<content type="html">
		  
		    &lt;p&gt;&lt;a href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#unnecessary-tradeoffs-are-the-root-of-all-evil.&quot;&gt;Unnecessary trade-offs are the root of all evil&lt;/a&gt; in software engineering. This article is about one of the most common sources of such unnecessary trade-offs: The unrealistic deadline of a partner team leading to exponential growth of technical debt throughout the organization.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://scx2.b-cdn.net/gfx/news/hires/2017/virus.jpg&quot; alt=&quot;Picture of a virus representing the viral effect of software project deadlines.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In this scenario your team is building some kind of new feature requested by some other team (“CoolFeature Team”) who insists they need it by date Y so that they can ship their feature by later date X.&lt;/p&gt;
&lt;p&gt;The failure mode I’ve seen happen time and time again, is that the following happens:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You realize that the right way of building the new feature cannot be achieved by date Y and so you resort to some short-term hack to make it happen. You actually have your thing ready by date Y.&lt;/li&gt;
&lt;li&gt;However, as date Y arrives it becomes apparent that CoolFeature Team’s project has slipped their own deadline date X and they really don’t need you to be ready yet.&lt;/li&gt;
&lt;li&gt;Tragically you discover that you could have built the new feature the right way, without accruing major technical debt, if you had known when CoolFeature team &lt;em&gt;really&lt;/em&gt; needed you to be ready. However, now it is too late to start over and have the right way of doing it ready by the new deadline and the hack remains in place.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This case is distinct from you setting unrealistic deadlines for yourself. Sure, that also sucks, but at least you are in control of the impact and can make choices that you deem locally correct. But with partner teams coming into the picture that are doing work based on such deadlines it is important to realize how such bad planning can snowball through the organization. In fact, it can multiply the negative impact in an &lt;em&gt;exponential&lt;/em&gt; way: Each partner may in turn ask for changes down the stack proliferating the original unrealistic deadline further into the organization.&lt;/p&gt;
&lt;h2 id=&quot;what-can-we-do%3F&quot;&gt;What can we do? &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/viral-software-deadlines/#what-can-we-do%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This isn’t a post offering advice on how to avoid slipping deadlines of software projects. This will happen. In fact, the professional thing is to mitigate the impact of inevitable slippage rather than attempting to fully eliminate it.&lt;/p&gt;
&lt;p&gt;What we can do is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Realize when our deadlines have follow-on impact beyond the immediate reach of our team such as partner teams reprioritizing work and potentially accruing technical debt.&lt;/li&gt;
&lt;li&gt;Really, really be honest to ourselves what a realistic finish date for a project is. We will make planning mistakes, but more often than not it would have been possible to anticipate that a deadline was never going to happen.&lt;/li&gt;
&lt;li&gt;Especially as a leader who might be using deadlines as a &lt;em&gt;device&lt;/em&gt; to improve productivity, it is important to consider the “total cost of the deadline”, which may be bigger than what is immediately visible.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/viral-software-deadlines/#summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Deadlines in software projects can be viral in that they force partner teams to reprioritize work and accrue technical debt. In large organizations or complex stacks these partner teams may in turn “infect” their partner teams to work towards the same deadline leading to exponential growth of technical debt. As professional engineers we must consider the total cost of our decisions. When we fan out our deadlines into the organization it is important to be honest to ourselves about realistic deadlines to minimize unnecessary technical debt at the time of delivery.&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fviral-software-deadlines%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Viral%20software%20deadlines&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in December, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/december-2021.html"/>
		<updated>2021-12-01T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/december-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1456326083238760459&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Page experience ranking for Desktop&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1456326083238760459&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1455899805083971589&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Smoothness Web Vitals metric is in the works&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1455899805083971589&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1461030055438602246&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The web is getting faster quicker than ever!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1461030055438602246&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1461226012218249218&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Single browser engine per OS is a dangerous strategy&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1461226012218249218&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1461591131930517504&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;😬&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1461591131930517504&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1463904809300418561&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Container queries polyfill!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1463904809300418561&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1464315327899049988&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1464315327899049988&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1465675823994884110&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Path to safe local network HTTP&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1465675823994884110&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1465174060711751681&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The bad/wrong same-domain canonical URL check is gone!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1465174060711751681&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1465866773866106880&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Native AI on the web platform?&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1465866773866106880&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1465944206145253378&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Huge relatively-low-effort performance improvement potential!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1465944206145253378&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fdecember-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in November, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/november-2021.html"/>
		<updated>2021-11-03T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/november-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1446019462105346048&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;In-browser HTML Sanitizer API is coming&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1446019462105346048&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1403086459301765121&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Finally a browser will open semantically closed elements when their contents match a `find in page` query&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1403086459301765121&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1450540255665434627&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Mentioned last month, now shipped&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1450540255665434627&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1451443109162717188&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The `importance` attribute can be powerful&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1451443109162717188&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1451545433545785349&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;RIP&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1451545433545785349&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1451978791492853768&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Your monthly `content-visibility: auto` PSA&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1451978791492853768&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1452953019126067201&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;There might be auto dark mode in Chrome&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1452953019126067201&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1453021257214091273&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Photoshop and Illustrator are on the web. Not a big deal&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1453021257214091273&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1453349651919241217&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I&amp;#39;m mildly excited&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1453349651919241217&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1454087578404065283&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The web sometimes seems static but this is amazing adoption&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1454087578404065283&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1455177191046615046&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;It&amp;#39;s actually a blender&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1455177191046615046&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fnovember-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in October, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/october-2021.html"/>
		<updated>2021-10-06T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/october-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1436374668450177026&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Important change in preload ordering. Will help many, but may require re-testing of strategies&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1436374668450177026&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1437353724930822146&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The WASM killer app&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1437353724930822146&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1437818350810419211&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Easy way to make signed exchanges via Cloudflare&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1437818350810419211&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1438032768882069505&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Platforms are catching up on Core Web Vitals&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1438032768882069505&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1438322367655075840&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#AppleBrowserBan is becoming mainstream discussion&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1438322367655075840&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1440361195282657281&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Smoothness web vitals in the works&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1440361195282657281&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1440487186885869571&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Chromium is giving up on making C++ memory safe&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1440487186885869571&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1441095716227543042&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Your monthly reminder that AVIF is good&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1441095716227543042&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1442604023136333825&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Igalia is why we can have some nice things&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1442604023136333825&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1443154459878637572&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Actually deployable CSP is coming to Safari&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1443154459878637572&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1443293844292919304&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Narrator: It did not go well&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1443293844292919304&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1443954541997838338&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;New important(^Wnce) performance tuning primitive&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1443954541997838338&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1443962459723755533&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;It is time&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1443962459723755533&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1443961187083984901&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;💯&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1443961187083984901&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1445276599084060673&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;RIP AppCache&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1445276599084060673&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1445343874679984128&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Slightly more reasonable CORS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1445343874679984128&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1445137340175831053&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;All the ❤️ to jQuery. Also: Get rid of it if you can. You no longer need it&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1445137340175831053&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1445425210119704578&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Cool stats about installed PWAs.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1445425210119704578&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Foctober-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in September, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/september-2021.html"/>
		<updated>2021-09-01T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/september-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1431346377985036289&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Chrome ended up deciding not to break most AVIFs&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1431346377985036289&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1425377932420190209&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AVIFs in Fx&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1425377932420190209&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1431196643265757184&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The &amp;quot;best&amp;quot; post IE6 API is getting an &amp;quot;unneeded&amp;quot; makeover&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1431196643265757184&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1431239318631182344&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;An actual API to schedule tasks in the browser 😍&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1431239318631182344&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1430841760964612098&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;jQuery is nice. The module system was shit. And the selectors are as maintainable as CSS selectors. But it was nice.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1430841760964612098&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1430866897008988161&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Long-term V8 regex parsing bug is fixed. Might break your code&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1430866897008988161&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1430024585118949376&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I feel seen&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1430024585118949376&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1429746895010861056&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This is just so nice&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1429746895010861056&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1427151416616001540&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This post is showing how CSS selectors that are inherently O(n) where n is the DOM size stay O(1) in apps that are decomposed with Shadow DOM&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1427151416616001540&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1420775444287303680&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Custom protocol handling for Chromium PWAs&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1420775444287303680&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1433088829846536192&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1433088829846536192&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1432969851811794944&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;👀&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1432969851811794944&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1424807537547882498&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;🔥&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1424807537547882498&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fseptember-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in August, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/august-2021.html"/>
		<updated>2021-08-01T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/august-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1417675413292298243&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;A nice &amp;lt;b&amp;gt;sync&amp;lt;/b&amp;gt;, safe-for-thread-model API&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1417675413292298243&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1417562491844972549&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Another nail in the coffin of IE&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1417562491844972549&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1419225899019522050&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Good insight for finalizer use in cross-worker JS programs&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1419225899019522050&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1410577516943847424&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;You just can&amp;#39;t believe we put up with it for so many years&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1410577516943847424&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1412652133082714116&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Good pointers for what client-side privacy APIs could do&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1412652133082714116&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1414864884471373829&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Anti-layout-shift API tweet 1/3&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1414864884471373829&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1414727871382253568&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;2/3: No layout-shift with art directed images in picture&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1414727871382253568&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1415328343583494148&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;3/3: For when you really want the field-reported CLS to hit 0&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1415328343583494148&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1415381163871461380&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;DNS resolutions no longer considered a scarce resource&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1415381163871461380&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1420072006188376069&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Native nesting in CSS (proposal stage)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1420072006188376069&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Faugust-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in July, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/july-2021.html"/>
		<updated>2021-07-01T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/july-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1405554160339079169&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Virtual keyboard presence is finally exposed to the web platform&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1405554160339079169&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1408520127126114311&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Chromium is slowly modernizing all aspects of its rendering engine&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1408520127126114311&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1407326048526770176&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Theme colors now support the media attribute (for dark mode) in Safari and Chrome&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1407326048526770176&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1407039035600773128&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Responsiveness metrics need more work after FID&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1407039035600773128&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1406342606028775424&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;If you are reading this website, then AVIF is just fine for your use case&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1406342606028775424&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1405437361643790337&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Fixed in Chrome now. Pending in Safari and Fx&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1405437361643790337&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1405206831526449155&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Important early research into website memory usage&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1405206831526449155&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1404886100087246848&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Page experience ranking is shipping&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1404886100087246848&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1404801114810236932&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Native non-JS imports part 1&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1404801114810236932&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1403450416482816000&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Native non-JS imports part 2&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1403450416482816000&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1400983875665289216&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1400983875665289216&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1400455540522688518&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Domain sharding 2021&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1400455540522688518&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjuly-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in June, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/june-2021.html"/>
		<updated>2021-06-02T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/june-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1391394432432234498&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Yet another attempt at smooth transitions&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1391394432432234498&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1394693648122531842&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;A small step for the error object, a big step for debuggability&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1394693648122531842&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1394776921121067012&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Page experience ranking coming to desktop&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1394776921121067012&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1395045383810785282&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;More good news from the browser front. And global marketshare dropped another 13% last month&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1395045383810785282&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1395105349632499714&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This is significant in that a major cause of 3P JS slowness reacted to Core Web Vitals&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1395105349632499714&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1395741337387900930&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Iframes Anonymous&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1395741337387900930&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1397518983264411652&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The web is getting faster&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1397518983264411652&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1396519747760451586&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I nerded out on software design again&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1396519747760451586&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1395997862065053696&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;A ~solution for font-induced CLS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1395997862065053696&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1397945205198835719&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The proliferation of JS VM tiers continues&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1397945205198835719&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1399628849856532482&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;JXL is coming to browsers.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1399628849856532482&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjune-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>The Context Tree Design Pattern</title>
		<link href="https://www.industrialempathy.com/posts/context-tree-design-pattern/"/>
		<updated>2021-05-23T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/context-tree-design-pattern/</id>
		<content type="html">
		  
		    &lt;p&gt;The Context Tree Design Pattern is broadly used in framework design and fascinatingly appears in seemingly unrelated applications implemented with many different strategies. As far as I can tell, this pattern does not yet have a name and so I made one up. C2 documents the &lt;a href=&quot;https://wiki.c2.com/?ContextObject&quot;&gt;Context Object&lt;/a&gt; and &lt;a href=&quot;https://wiki.c2.com/?ContextObjectsAreEvil&quot;&gt;why it is bad&lt;/a&gt;, yet falls short of identifying the relationship to trees that push the pattern beyond a fancy bag of global variables.&lt;/p&gt;
&lt;h2 id=&quot;description-and-examples&quot;&gt;Description and examples &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#description-and-examples&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Context Tree Design Pattern appears whenever there is some kind of &lt;a href=&quot;https://en.wikipedia.org/wiki/Tree_(data_structure)&quot;&gt;tree&lt;/a&gt; (in the computer science sense) and ancestor nodes want to communicate state to all their transitive children. Such trees might be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A function call tree.&lt;/li&gt;
&lt;li&gt;A remote procedure call or multiple event invocation tree.&lt;/li&gt;
&lt;li&gt;A user interface tree such as a DOM tree.&lt;/li&gt;
&lt;li&gt;A transient render tree (such as found in React).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One common capability of setting context in a tree is the ability to shadow named context values that were specified by an ancestor with a different value for all children.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.industrialempathy.com/img/context-tree.svg&quot; alt=&quot;Example of a context tree with intermediate nodes shadowing a value&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;applications&quot;&gt;Applications &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#applications&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Common application of context in such trees would be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A reference to the current locale, HTTP request, or logger.&lt;/li&gt;
&lt;li&gt;The window or other container a UI object is inside of.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Tracing_(software)&quot;&gt;Tracing&lt;/a&gt; of complex but strongly related computer system behavior that spans multiple events, processes, and/or machines.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;implementation-strategies&quot;&gt;Implementation strategies &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#implementation-strategies&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;explicit-passing-of-context&quot;&gt;Explicit passing of context &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#explicit-passing-of-context&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This might seem like the most naive implementation strategy: One simply passes a context object argument to the next child.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;example_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;context&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arg1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arg2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;other_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;context&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arg1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;yet_another_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;context&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;123&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This method leads to significant boilerplate and leaks the existence of context to every participant in the call tree. However, sometimes, such as when crossing system boundaries, this may be the only implementation option. Frameworks can hide this from user code through mechanisms that pass context via standardized headers or side channels for remote procedure calls.&lt;/p&gt;
&lt;h3 id=&quot;context-stack&quot;&gt;Context stack &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#context-stack&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the simplest application of the Context Tree Design Pattern, the function call tree, the pattern is typically implemented using a stack. One pushes a value to store it, children read it by peeking at the top element of the stack, and then one pops the value when the calls to the children have completed. Interestingly, the Perl 5 programming language has native support for this pattern with the &lt;a href=&quot;https://perldoc.perl.org/functions/local&quot;&gt;&lt;code&gt;local&lt;/code&gt;&lt;/a&gt; keyword. Respectively, it becomes obvious that the Context Tree Design Pattern in a synchronous function call tree is the same concept as &lt;a href=&quot;https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scope&quot;&gt;dynamic scoping&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; context_stack &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Stack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;example_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  context_stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;context value&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;child_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  context_stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;child_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Actually read the context.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; context_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; context_stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;peek&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Shadow the value for a child.&lt;/span&gt;&lt;br /&gt;  context_stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;override&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;nested_child_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  context_stack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note, that user code would essentially never interact directly with this implementation. Instead they&#39;d use higher level APIs that hide the implementation detail of the stack and ensure that pushes and pops are well paired.&lt;/p&gt;
&lt;p&gt;This simple implementation, however, doesn’t work to more complex use cases of call trees, such as when they span threads, asynchronous invocations, or even physical machines; and the implementation strategy does not work for persistent trees such as DOM trees.&lt;/p&gt;
&lt;h3 id=&quot;thread-local-variables&quot;&gt;Thread local variables &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#thread-local-variables&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html&quot;&gt;Thread local variables&lt;/a&gt; may act as the host for the stack described above. In a system where threads are dedicated to a single execution context such as a HTTP request, thread local variables are useful to provide context that is isolated to handling that request.&lt;/p&gt;
&lt;h3 id=&quot;hooking-event-loop-entry-points&quot;&gt;Hooking event loop entry points &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#hooking-event-loop-entry-points&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Event driven systems (such as Node.js) cannot use thread local variables as there may only be a single thread and even if there are more than one, they may be used across many logically separate computations.&lt;/p&gt;
&lt;p&gt;A strategy to still get somewhat convenient context access in such a scenario is to change all points that represent the root of a call stack in an event loop invocation to properly restore context and to make each invocation that places work on the event loop store context such that it can be restored upon invocation.&lt;/p&gt;
&lt;h3 id=&quot;walking-up-the-tree&quot;&gt;Walking up the tree &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#walking-up-the-tree&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While function call trees do not typically allow inspection of the state of the caller (There are, of course, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Archive/Web/JavaScript/arguments.caller&quot;&gt;exceptions&lt;/a&gt;) this is very commonly possible in persistent trees such as the tree representing a user interface like a DOM tree. Nodes on the tree can walk up their parent nodes in reasonably efficient &lt;em&gt;O(k depth of the tree)&lt;/em&gt; to find context provided to them.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Visit parent elements of the start element and return the&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// context value if they provide it.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// We assume for this example that every parent element&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// has a context map.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parentElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;using-event-propagation&quot;&gt;Using event propagation &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#using-event-propagation&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Another way to implement the same approach is to rely on event bubbling that is commonly natively supported in UI systems. Here the target nodes sends a custom event up the tree. Ancestors intercept the event, and if they can provide the desired context, they send it down to the target and stop propagation of the event.&lt;/p&gt;
&lt;h4 id=&quot;context-in-react-style-frameworks&quot;&gt;Context in React-style frameworks &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#context-in-react-style-frameworks&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Context is commonly found in React-style frameworks, but they tend to implement context in terms of the function call tree that underlies the render tree rather than the persistent UI tree.&lt;/p&gt;
&lt;h3 id=&quot;trace-context&quot;&gt;Trace context &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#trace-context&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Many software systems have invested in observability through &lt;a href=&quot;https://en.wikipedia.org/wiki/Tracing_(software)&quot;&gt;tracing&lt;/a&gt;. As seen in the examples above, tracing is itself an application of the Context Tree Design Pattern. However, if one has a good tracing system, one can use (abuse) it to attach context to it that is unrelated to tracing.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;trace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// We store context in a weak map keyed by&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// the current trace.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; context_weak_map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;trace&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;an-anti-pattern%3F&quot;&gt;An anti-pattern? &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#an-anti-pattern%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Context Tree Design Pattern can easily be misused and has a long range of failure modes:&lt;/p&gt;
&lt;h3 id=&quot;messy-bag-of-quasi-global-variables&quot;&gt;Messy bag of quasi global variables &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#messy-bag-of-quasi-global-variables&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The context may grow to a messy bag of quasi global variables.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation&lt;/strong&gt;: Consider requiring an allow-list that requires engineering leadership approval for new values stored in context.&lt;/p&gt;
&lt;h3 id=&quot;action-at-a-distance&quot;&gt;Action at a distance &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#action-at-a-distance&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Context may create fragile, implicit, and undocumented dependencies between seemingly unrelated nodes in a tree.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation&lt;/strong&gt;: Consider introducing a type-system that requires context consumers to be only callable by callers that provide that context or which require their callers to provide that context (Note: I’m not sure such a type system exists; it smells a bit like checked exceptions in Java but might still be a good idea).&lt;/p&gt;
&lt;h3 id=&quot;unexpected-consumers&quot;&gt;Unexpected consumers &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#unexpected-consumers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Context may be read by unexpected consumers creating even more brittle dependencies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigation&lt;/strong&gt;: Consider protecting the keys to read context to be protected by some kind of access control mechanism such as an allow-list.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/context-tree-design-pattern/#summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I find it fascinating that this pattern has found such a wide range of applications and is implemented through seemingly unrelated implementation strategies. I probably missed use cases, alternative implementations, and failure modes. Comments with additions or corrections are very welcome!&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fcontext-tree-design-pattern%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=The%20Context%20Tree%20Design%20Pattern&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in May, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/may-2021.html"/>
		<updated>2021-05-05T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/may-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1382024004190547968&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;CLS no longer penalizes long-running sessions with unlimited cumulations&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1382024004190547968&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1382016481077170182&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Declarative Shadow DOM. And easily polyfillable&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1382016481077170182&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1384125303442706433&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Faster number crunching if you need to crunch numbers&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1384125303442706433&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1384173984334237699&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;New timing for page experience ranking&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1384173984334237699&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1385369724662403072&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Every web page can be a desktop app&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1385369724662403072&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1386932250391023619&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;HTML sanitization as a platform primitive&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1386932250391023619&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1387438286591905798&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Chrome continues to catch up on back-forward cache&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1387438286591905798&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1387762020397854726&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The IE11 death march continues&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1387762020397854726&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1388126660738830336&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;No excuses&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1388126660738830336&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1389493762129375232&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Fix committed but unclear if shipping&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1389493762129375232&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1389616375174467588&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Woke: FCP in Safari
Broke: Not actually reporting paint time&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1389616375174467588&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1389642353472851970&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1389642353472851970&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fmay-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in April, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/april-2021.html"/>
		<updated>2021-04-07T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/april-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1377220216233541632&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Top-level await in Firefox (It is already in Chrome/v8) …&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1377220216233541632&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1370142814034657280&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…and also coming to Safari&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1370142814034657280&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1370519891292254212&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;It is now 0.73%. Down and to the right! 📉&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1370519891292254212&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1374444547766329347&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Chrome going HTTPS-connect by default (falling back to HTTP if that fails)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1374444547766329347&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1373018017919950853&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1373018017919950853&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1373524844554326018&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Also in that release: Freeze dried tabs that take no memory but start up fast.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1373524844554326018&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1376940899905675266&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Page experience ranking is coming!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1376940899905675266&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1376958200705118208&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Balanced look at privacy-preserving interest-based ads&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1376958200705118208&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1376984684693962756&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Think AVIF, but with progressive loading&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1376984684693962756&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1378369728796823553&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;End of an era. Except the old era is still linked from the new era.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1378369728796823553&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1379075393446150150&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;APIs prevailed&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1379075393446150150&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1379581800754843650&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Safari uses proprietary image decoding, but this is still a good sign.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1379581800754843650&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1377245938104872964&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I wish browsers would handle these but until then:&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1377245938104872964&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fapril-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in March, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/march-2021.html"/>
		<updated>2021-03-11T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/march-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1360163149526282240&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;End of an era&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1360163149526282240&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1363182846731382790&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AVIF is good&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1363182846731382790&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1369431690842673157&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AVIF is shipping in Firefox&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1369431690842673157&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweethttps://twitter.com/jonsneyers/status/1363889625702543367&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;JPEG XL is also good&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/https://twitter.com/jonsneyers/status/1363889625702543367&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1364137928784543744&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Lighter embeds are a major trend&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1364137928784543744&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1364293782603202561&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This has strategic implication for long-term web design planning&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1364293782603202561&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1365892235074686976&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;`content-visibility: auto` is our most powerful new hammer. Use wisely.&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1365892235074686976&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1367334585592279043&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;It is amazing that jQuery is still being actively maintained&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1367334585592279043&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1367538670983663619&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;A new Chrome every 4 weeks&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1367538670983663619&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1368151716932247554&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Deep-dive on Post-Spectre web dev&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1368151716932247554&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1368471484910370818&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Please use this&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1368471484910370818&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1369709676271726599&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Framework-layer perf improvements are the best ones&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1369709676271726599&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fmarch-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>AVIF and WebP encoding quality settings</title>
		<link href="https://www.industrialempathy.com/posts/avif-webp-quality-settings/"/>
		<updated>2021-02-20T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/avif-webp-quality-settings/</id>
		<content type="html">
		  
		    &lt;style&gt;
.numberful strong {
  color: #8dff80;
}
main iframe {
  width: 100%;
  margin-top: -1.5em;
  margin-bottom: -1.5em;
}
&lt;/style&gt;
&lt;div class=&quot;numberful&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://jakearchibald.com/2020/avif-has-landed/&quot;&gt;AVIF&lt;/a&gt; and &lt;a href=&quot;https://developers.google.com/speed/webp&quot;&gt;WebP&lt;/a&gt; are modern image formats that generally produce smaller file sizes compared to the widely used JPEG format. This post explains what quality setting to pick when generating AVIF and WebP images as alternatives for serving JPEG on the web. The goal is to find the quality setting that will create images that look as good as the JPEG, but with a smaller size to optimize page load time without sacrifizing image quality.&lt;/p&gt;
&lt;p&gt;One more thing: This post is advice for tuning your automatic image optimization process where if you&#39;re anything like me you&#39;ll configure a global value once and then never look back. If you are the type of person who optimizes each image individually, then this post is probably not for you 😇. But you may still want to &lt;a href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/#visual-verification&quot;&gt;play with my tool&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-1-minute-version&quot;&gt;The 1 minute version &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/#the-1-minute-version&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you usually encode JPEGs with quality setting &lt;strong&gt;60&lt;/strong&gt;, then encode AVIF with quality setting &lt;strong&gt;50&lt;/strong&gt; and WebP with quality setting &lt;strong&gt;65&lt;/strong&gt;. You should expect your AVIF files to be on average &lt;strong&gt;36% smaller&lt;/strong&gt; and your WebP images &lt;strong&gt;15%&lt;/strong&gt; smaller than the equivalent JPEG image.&lt;/p&gt;
&lt;h2 id=&quot;quality-settings-for-a-range-of-jpeg-qualities&quot;&gt;Quality settings for a range of JPEG qualities &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/#quality-settings-for-a-range-of-jpeg-qualities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;More generally, this table maps quality settings for JPEG to the respective AVIF and WebP quality settings:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;&lt;th&gt;JPEG quality&lt;/th&gt;&lt;th&gt;50&lt;/th&gt;&lt;th&gt;60&lt;/th&gt;&lt;th&gt;70&lt;/th&gt;&lt;th&gt;80&lt;/th&gt;&lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;AVIF quality&lt;/td&gt;&lt;td&gt;48&lt;/td&gt;&lt;td&gt;51&lt;/td&gt;&lt;td&gt;56&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;WebP quality&lt;/td&gt;&lt;td&gt;55&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;72&lt;/td&gt;&lt;td&gt;82&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are some notable differences in how well the different image codecs perform for varying image dimensions (especially between very small images like thumbnails and highres images). If you want to fully optimize things, check out this &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1E29kPLR5_0PThsw6SVbco7HvMU0aynBLfVN0RfIXgPk/edit#gid=1107534790&quot;&gt;pivot table for the gory details&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;visual-verification&quot;&gt;Visual verification &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/#visual-verification&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Quality numbers are cool, but you might want to verify that I did not just pick them out of thin air. For a head-to-head comparison of images with the varying quality settings, check out this &lt;a href=&quot;https://avif-webp-quality-setting.industrialempathy.com/&quot;&gt;tool&lt;/a&gt;:&lt;/p&gt;
&lt;/div&gt;

&lt;iframe title=&quot;AVIF and WebP quality settings picker&quot; id=&quot;tool&quot; src=&quot;https://avif-webp-quality-setting.industrialempathy.com/embed.html&quot; height=&quot;1250&quot;&gt;&lt;/iframe&gt;
&lt;article&gt;
&lt;div class=&quot;numberful&quot;&gt;
&lt;h2 id=&quot;methodology&quot;&gt;Methodology &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/#methodology&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To generate the data above, for a set of sample images:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I generated JPEG, AVIF, and WebP images for various screen dimensions and with a multitude of quality settings.&lt;/li&gt;
&lt;li&gt;I then used &lt;a href=&quot;https://github.com/kornelski/dssim&quot;&gt;dssim&lt;/a&gt; to calculate how visually different each of these images are from the source images.&lt;/li&gt;
&lt;li&gt;And finally I picked those AVIF and WebP images in a given size and JPEG quality setting that were as different from the source image (again, as determined by dssim) as the respective JPEG.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the full details, check out this &lt;a href=&quot;https://github.com/cramforce/avif-webp-quality-setting&quot;&gt;GitHub project&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;caveats&quot;&gt;Caveats &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/#caveats&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;All quality settings are expressed on a range from 1 to 100.&lt;/li&gt;
&lt;li&gt;Images were encoded using the &lt;a href=&quot;https://sharp.pixelplumbing.com/&quot;&gt;sharp image processing library&lt;/a&gt;. Results with different encoders may vary.&lt;/li&gt;
&lt;li&gt;The underlying data was generated from only 4 images (showing a landscape, a person, flowers, and architecture). These sample images may not be representative for the images on your website and you may require different encoding settings (Although I don&#39;t think so 😛). You can easily rerun the same fully automated process that I used for this post through this &lt;a href=&quot;https://github.com/cramforce/avif-webp-quality-setting&quot;&gt;GitHub project&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you&#39;re like &amp;quot;LOL, why only 4 sample images&amp;quot;. The method explodes these out to over 2300 generated images. It is easy to add more samples, but it does cost a lot of CPU.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;browser-support&quot;&gt;Browser support &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All modern browsers support WebP. At the time of this writing (February 2021) &lt;a href=&quot;https://caniuse.com/avif&quot;&gt;not all browsers support AVIF yet&lt;/a&gt;. However, very broad browser suport for AVIF is a safe bet with Chromium and Firefox having already shipped support and Apple, maker of Safari and the WebKit engine, being part of the &lt;a href=&quot;https://en.wikipedia.org/wiki/AV1&quot;&gt;AV1 consortium&lt;/a&gt; that makes the AVIF codec.&lt;/p&gt;
&lt;p&gt;Check out my recent post on image optimization for how to &lt;a href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#avif&quot;&gt;load different image codecs with graceful degradation to JPEG using the picture element&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/#summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With my image sample set AVIF images were on average &lt;strong&gt;36% smaller&lt;/strong&gt; and WebP images were &lt;strong&gt;15% smaller&lt;/strong&gt; than the equivalent JPEG. If you are looking for ways to improve metrics like &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint&lt;/a&gt;, then supporting modern image formats may be a quick way to make progress.&lt;/p&gt;
&lt;p&gt;For a wider perspective on image loading optimization on the web, check out my post on &lt;a href=&quot;https://www.industrialempathy.com/posts/image-optimizations/&quot;&gt;image loading optimizations&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/article&gt;
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Favif-webp-quality-settings%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=AVIF%20and%20WebP%20encoding%20quality%20settings&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in February, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/february-2021.html"/>
		<updated>2021-02-10T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/february-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1351177998532309003&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Your timers might not fire. Deal with it😎&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1351177998532309003&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1351971596810940418&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1351971596810940418&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1351953283447984131&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;WorkerDOM but not in user land&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1351953283447984131&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1353831156098150400&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Inline threads in JS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1353831156098150400&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1354467854519738372&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1354467854519738372&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1354478933685637121&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Mozilla being short-sighted. Feb 21 edition&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1354478933685637121&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1354914430761529345&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AMP, but !AMP&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1354914430761529345&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1355823349641969664&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1355823349641969664&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1355569564461920259&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I wrote a blog post because my blog had bad CLS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1355569564461920259&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1356391660863811586&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Further progress on origin isolation&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1356391660863811586&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1356656668222885889&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;A proposal for a non-broken history API&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1356656668222885889&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1358060379000037377&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;TIL&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1358060379000037377&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1358590710966980608&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Dear my bank in particular&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1358590710966980608&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1359232986382798851&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Caja is both deprecated and has unfixed vulns. Use [DOMPurify](https://github.com/cure53/DOMPurify)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1359232986382798851&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1359200840876257287&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;NPM and other package registries dangerously allow private packages in the same namespace as public packages and prefer public packages&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1359200840876257287&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Ffebruary-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>More than you ever wanted to know about font loading on the web</title>
		<link href="https://www.industrialempathy.com/posts/high-performance-web-font-loading/"/>
		<updated>2021-01-29T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/high-performance-web-font-loading/</id>
		<content type="html">
		  
		    &lt;p&gt;When I started thinking about writing a post about web font loading my intention was to propose relatively sophisticated ideas that I&#39;ve been playing with for a while. However, as I was trying to use them in real-world websites I realized that deployment of the more advanced techniques is de-facto impossible without the creation of new web standards.&lt;/p&gt;
&lt;p&gt;With that the TL;dr of this post is: Use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display&quot;&gt;&lt;code&gt;font-display: optional&lt;/code&gt;&lt;/a&gt;. However, I and many others really like our custom fonts. See the rest of the post for how we can get our cake and eat it, too–with a &lt;a href=&quot;https://www.industrialempathy.com/perfect-ish-font-fallback/?font=Montserrat&quot;&gt;tool&lt;/a&gt; that automatically makes fallback fonts behave like their respective custom font counterpart.&lt;/p&gt;
&lt;h2 id=&quot;web-fonts-and-core-web-vitals&quot;&gt;Web fonts and Core Web Vitals &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#web-fonts-and-core-web-vitals&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;2 metrics in &lt;a href=&quot;https://web.dev/vitals/&quot;&gt;Google&#39;s Core Web Vitals&lt;/a&gt; are directly impacted by font loading:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt; measures (among other things) when text renders. With text rendering blocked behind the web font download, LCP may be delayed.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/cls/&quot;&gt;Cumulative Layout Shift (CLS)&lt;/a&gt; measures the document shifting around as the browser loads additional data. A browser switching from fallback font to a custom font leads to layout shift if fallback and custom font flow differently.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following video is showing the layout-shift created by font-loading.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://www.industrialempathy.com/perfect-ish-font-fallback/font-cls.mp4&quot; width=&quot;1062&quot; height=&quot;1052&quot; style=&quot;width: 100%; height: auto; aspect-ratio: 1062 / 1052&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; preload=&quot;auto&quot; aria-label=&quot;Video showing font CLS effect&quot;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;cls-and-invisible-text&quot;&gt;CLS and invisible text &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#cls-and-invisible-text&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Font-based layout shift doesn&#39;t require the fallback font ever having displayed. If the page renders without the custom font having loaded but the fallback text remains invisible (this happens with &lt;code&gt;font-display: auto&lt;/code&gt;, the default) then the space that is reserved for the invisible text depends on the space that &lt;em&gt;would&lt;/em&gt; be taken up by the &lt;em&gt;fallback text&lt;/em&gt;. Once the custom font comes in and the text becomes visible, there is a layout shift as the space taken up for text changes.&lt;/p&gt;
&lt;h2 id=&quot;stop-worrying-and-use-font-display%3A-optional&quot;&gt;Stop worrying and use &lt;code&gt;font-display: optional&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#stop-worrying-and-use-font-display%3A-optional&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With &lt;code&gt;font-display: optional&lt;/code&gt; the browser only renders the custom font if it is available extremely quickly. In most scenarios that requires it being cached locally.&lt;/p&gt;
&lt;p&gt;This leads to the best possible LCP: Your text always renders quickly, independent of network speed.&lt;/p&gt;
&lt;p&gt;And it leads to the best possible CLS: Your custom font loading never causes layout shift because it is only used when it is available for the first text paint.&lt;/p&gt;
&lt;h3 id=&quot;when-not-to-use-font-display%3A-optional&quot;&gt;When not to use &lt;code&gt;font-display: optional&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#when-not-to-use-font-display%3A-optional&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The one reason that makes usage of &lt;code&gt;font-display: optional&lt;/code&gt; impossible is if there is no viable fallback font: You need the custom font to load to make sense of the content. Generally that is the case for icon fonts. You probably shouldn&#39;t use these in the first place as they are bad for accessibility: You need to see the icons to comprehend them, and you cannot assign them alt-text.&lt;/p&gt;
&lt;h3 id=&quot;using-preload-with-font-display%3A-optional&quot;&gt;Using preload with &lt;code&gt;font-display: optional&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#using-preload-with-font-display%3A-optional&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Browsers will only download a font for a web page when CSS evaluation completes and it is determined that it is actually used on the page. That is much later than e.g. when image downloads are initiated which are done by the so-called pre-parser that does a quick scan of the HTML document as soon as it is available to the browser (and without blocking on synchronous scripts, stylesheets, etc.).&lt;/p&gt;
&lt;p&gt;The common work-around is to use a link-preload element like this which explicitly instructs the browser to start the font download as soon as it discovers the element.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;preload&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/fonts/Inter-Bold.woff2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;font&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;font/woff2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;crossorigin&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The question is: Should you use these together with &lt;code&gt;font-display: optional&lt;/code&gt;? The conventional wisdom is: No. The reason being that with &lt;code&gt;font-display: optional&lt;/code&gt; either your font is already in cache in which case this doesn&#39;t do anything, or the font download is likely not fast enough to make the short deadline and the browser would render the fallback font anyway. In the latter case you give bandwidth at the most urgent time to the font which will never render and that bandwidth could be used to download other critical resources instead.&lt;/p&gt;
&lt;h4 id=&quot;when-disk-caching-isn&#39;t-enough&quot;&gt;When disk caching isn&#39;t enough &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#when-disk-caching-isn&#39;t-enough&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;However, with &lt;code&gt;font-display: optional&lt;/code&gt; even users who have the font cached to disk might see the fallback font for the first page view of a new session because the custom font hasn&#39;t been loaded into the memory cache (Note, that while you might be developing your website on a laptop or phone with a very fast SSD, many of your users will have degraded storage devices with cache performance worse than a fast network). At least Chrome has a heuristic that if you preload the font, then it will hold painting for a few 100 of milliseconds and give the client a chance to fetch the font from disk or through a very fast internet connection. Whether you have a &amp;quot;budget&amp;quot; to spend those extra 100s milliseconds depends on your overall load performance.&lt;/p&gt;
&lt;h2 id=&quot;fonts-and-cdns&quot;&gt;Fonts and CDNs &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#fonts-and-cdns&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the big changes in the web ecosystem over the last few years is that browsers no longer cache resources across top level sites. That means if your site and my site both load the exact same Roboto from Google Fonts, the browser will download it twice as opposed to only once like they used to do. This is very sad. It is, however, also the right call in the short-term from a privacy &amp;amp; security perspective. In the long-term, maybe we can define web standards that eliminate the privacy &amp;amp; security threats from cross-origin caching for heavily shared resources like fonts.&lt;/p&gt;
&lt;p&gt;So, what are the consequences of this change in browser caching behavior? The main change is that font CDNs like Google Fonts and Adobe TypeKit now strictly make your site slower. They used to help with cross-site caching, but that benefit is gone. Instead they add expensive cross-origin requests (and their DNS lookups, TLS negotiations, etc.) into the critical path of loading your website.&lt;/p&gt;
&lt;p&gt;With that it is clear that we should self-host all fonts on our primary domain for maximum performance. With fonts this can sometimes be problematic for licensing reasons, etc. but there is a good middle ground: Instead of self-hosting the fonts, self-host the loading code. For all common Font CDNs (&lt;a href=&quot;https://blog.typekit.com/2017/10/11/advanced-web-font-loading-with-typekits-css-embed-code/&quot;&gt;even TypeKit with some digging&lt;/a&gt;, they default to JS based loading) this is simply a CSS file. Just download that CSS file. It won&#39;t bite 😄. Or, if your font provider likes to sometimes change it, just fetch the CSS file once during your build process. Then inline the CSS file into your HTML and you completely eliminate the expensive cross-origin request from your critical path. While this approach still downloads the fonts themselves from the CDNs this doesn&#39;t hurt when you are using our friend &lt;code&gt;font-display: optional&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-if-i-really-don&#39;t-want-to-use-font-display%3A-optional&quot;&gt;What if I really don&#39;t want to use &lt;code&gt;font-display: optional&lt;/code&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#what-if-i-really-don&#39;t-want-to-use-font-display%3A-optional&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So, I have a solution for you. It works remarkably well. This is based on &lt;a href=&quot;https://meowni.ca/font-style-matcher/&quot;&gt;an idea/tool by Monica Dinculescu&lt;/a&gt; that she published in 2016. It allows tweaking your fallback font such that it uses approximately as much space as the custom font.&lt;/p&gt;
&lt;p&gt;This is an awesome idea as it avoids the layout shift issues associated with loading the custom font: With the fallback already taking up the right amount of space, the custom font just swaps back into the same space when it loads.&lt;/p&gt;
&lt;h3 id=&quot;tool%3A-perfect-ish-font-fallbacks&quot;&gt;Tool: Perfect-ish font fallbacks &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#tool%3A-perfect-ish-font-fallbacks&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My contribution over Monica&#39;s idea is that &lt;a href=&quot;https://www.industrialempathy.com/perfect-ish-font-fallback/?font=Montserrat&quot;&gt;I made a tool&lt;/a&gt; that &lt;em&gt;automatically&lt;/em&gt; matches the fallback font to the custom font–because computers are good at that stuff. &lt;a href=&quot;https://www.industrialempathy.com/perfect-ish-font-fallback/?font=Montserrat&quot;&gt;Try it out here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The tool allows you to select every Google Font from a select menu. If you aren&#39;t using a Google Fonts, you can &lt;a href=&quot;https://glitch.com/edit/#!/perfect-ish-font-fallback&quot;&gt;remix this Glitch&lt;/a&gt; for a custom solution.&lt;/p&gt;
&lt;h4 id=&quot;samples&quot;&gt;Samples &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#samples&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The fallback-to-custom-font matching works really well in most cases. Here the left font is the custom font and on the right side is Arial:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.glitch.com/1dbd4ffb-3ccc-4469-8f76-d56f540a54d9%2FScreen%20Shot%202021-01-29%20at%2020.32.28.png?v=1611981250256&quot; alt=&quot;Comparison of rendering of Montserrat and Arial&quot; /&gt;&lt;/p&gt;
&lt;p&gt;However, the whole thing is just an approximation. It definitely happens that things do not match 100%. (The screenshot shows the same text/font as before, but uses a different viewport width). The solution works most of the time. It isn&#39;t perfect but better than always having a major layout jump.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.glitch.com/1dbd4ffb-3ccc-4469-8f76-d56f540a54d9%2FScreen%20Shot%202021-01-29%20at%2020.36.21.png?v=1611981425213&quot; alt=&quot;Same fonts as in previous image but showing that Arial flows one line shorter&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Finally, your mileage may vary with more extreme fonts. For very narrow fonts the fallback font may become unreadable. Having said that, for fonts that are commonly used this is not a problem.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.glitch.com/1dbd4ffb-3ccc-4469-8f76-d56f540a54d9%2FScreen%20Shot%202021-01-29%20at%2020.38.06.png?v=1611981501564&quot; alt=&quot;Text with negative letter spacing that has the characters flow into each other&quot; /&gt;&lt;/p&gt;
&lt;h4 id=&quot;deploying-fallback-corrections-to-the-website&quot;&gt;Deploying fallback corrections to the website &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#deploying-fallback-corrections-to-the-website&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Just add CSS like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* Make a custom fallback font based on the local Times New Roman */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@font-face&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CustomFont-fallback&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;size-adjust&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 116.19%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Times New Roman&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* Set the body to CustomFont, but if it is missing fallback &lt;br /&gt;  to our bespoke fallback &#39;CustomFont-fallback&#39;  */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CustomFont&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CustomFont-fallback&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;/* The value doesn&#39;t matter, but you must specify a line-height for all text with custom fonts to avoid CLS */&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…and that is it. This is possible as of July 2021&lt;/p&gt;
&lt;h3 id=&quot;a-new-web-standard&quot;&gt;A new web standard &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#a-new-web-standard&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With the &lt;code&gt;@font-face&lt;/code&gt; property &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/size-adjust&quot;&gt;&lt;code&gt;size-adjust&lt;/code&gt;&lt;/a&gt; a web standard solution is coming for the font-matching problem space. The tool in this article&lt;a href=&quot;https://www.industrialempathy.com/perfect-ish-font-fallback/?font=Judson&quot;&gt;(requires Chrome 92+ or Firefox 92+) here&lt;/a&gt; has been updated to rely on &lt;code&gt;size-adjust&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note, that there are additional related CSS properties &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/ascent-override&quot;&gt;&lt;code&gt;ascent-override&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/descent-override&quot;&gt;&lt;code&gt;descent-override&lt;/code&gt;&lt;/a&gt;. However, you do not need to worry about these if you set a &lt;code&gt;line-height&lt;/code&gt; of any non-default value for all text.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using &lt;code&gt;font-display: optional&lt;/code&gt; together with self-hosting the CSS for your web fonts gets you in really good shape with respect to LCP and CLS. However, with new web standards support for &lt;code&gt;size-adjust&lt;/code&gt; there is a feasible way to avoid CLS while still always eventually switching to the custom font.&lt;/p&gt;
&lt;h1 id=&quot;tools&quot;&gt;Tools &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/high-performance-web-font-loading/#tools&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is a list of known technologies and tools implementing all of these optimizations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/google/eleventy-high-performance-blog&quot;&gt;eleventy-high-performance-blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nextjs.org/docs/basic-features/font-optimization&quot;&gt;@next/font&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fhigh-performance-web-font-loading%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=More%20than%20you%20ever%20wanted%20to%20know%20about%20font%20loading%20on%20the%20web&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in January, 2021</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/january-2021.html"/>
		<updated>2021-01-13T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/january-2021.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1348635270762139650&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Avoid crashing your node process with unexpected RegExp behavior&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1348635270762139650&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1347221452643311616&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Your&amp;#39;s truly wrote a blog post over the Holidays&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1347221452643311616&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1338996596189630464&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;3rd time&amp;#39;s a charm&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1338996596189630464&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1339329690948022273&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;👀&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1339329690948022273&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1339621592826044418&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Tightly controlling your 🍪s is the future&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1339621592826044418&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1339609333353615364&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Easier URL routing in browsers&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1339609333353615364&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1341517946468720640&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AVIF generation is now [trivial](https://www.npmjs.com/package/sharp)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1341517946468720640&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1342624911672680450&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;COVID vaccines explained for engineers&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1342624911672680450&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1345029710506582020&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Cool/useful hack&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1345029710506582020&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1347096257051951104&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;We&amp;#39;re onto something&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1347096257051951104&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1346215485474443264&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;🎉🎉🎉🎉&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1346215485474443264&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet889928137970245633&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;This has now happened&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/889928137970245633&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjanuary-2021.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Maximally optimizing image loading for the web</title>
		<link href="https://www.industrialempathy.com/posts/image-optimizations/"/>
		<updated>2020-12-28T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/image-optimizations/</id>
		<content type="html">
		  
		    &lt;p&gt;In this post I&#39;ll outline 8 image loading optimization techniques to minimize both the bandwidth used for loading images on the web and the CPU usage for image display. I&#39;ll present them in the form of an annotated HTML example to make it easy for folks to reproduce the results. Some of these techniques are more established, while others are somewhat novel. Ideally, your favorite mechanism for publishing web documents (like a CMS, static site generator, or web application framework) implements all of these out-of-the-box. I&#39;ll keep a &lt;a href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#tools&quot;&gt;list updated at the end of this posts&lt;/a&gt; with technologies that provide &lt;em&gt;all&lt;/em&gt; of the optimizations outlined here.&lt;/p&gt;
&lt;p&gt;Together the techniques optimize all elements of &lt;a href=&quot;https://web.dev/vitals/&quot;&gt;Google&#39;s Core Web Vitals&lt;/a&gt; by&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Minimizing the &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt; through reducing bytes, caching, and lazy loading.&lt;/li&gt;
&lt;li&gt;Keeping &lt;a href=&quot;https://web.dev/cls/&quot;&gt;Cumulative Layout Shift (CLS)&lt;/a&gt; to zero.&lt;/li&gt;
&lt;li&gt;Reducing &lt;a href=&quot;https://web.dev/fid/&quot;&gt;First Input Delay(FID)&lt;/a&gt; through reduced (main-thread) CPU usage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;View the source of this sample image to see all the techniques in action:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.glitch.com/b6ff3d80-fd0f-4b44-bf64-04d944022e94%2FIMG_20191128_174024.jpg?v=1609184192662&quot; alt=&quot;Sample image illustrating the techniques outlined in this post.&quot; /&gt;&lt;/p&gt;
&lt;h1 id=&quot;optimization-techniques&quot;&gt;Optimization techniques &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#optimization-techniques&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id=&quot;responsive-layout&quot;&gt;Responsive layout &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#responsive-layout&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a well understood technique to make an image use the available horizontal space up until its maximum size while retaining the aspect ratio. New in 2020 is that web browsers will reserve the correct vertical space for the image before it loads if the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes are provided for the &lt;code&gt;img&lt;/code&gt; element. This avoids &lt;a href=&quot;https://web.dev/cls/&quot;&gt;Cumulative Layout Shift (CLS)&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Providing width and height is more important than ever. --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;853&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1280&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;…&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;lazy-rendering&quot;&gt;Lazy rendering &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#lazy-rendering&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The second technique is more cutting edge. The new CSS attribute &lt;code&gt;content-visibility: auto&lt;/code&gt; instructs the browser to not bother layouting the image until it gets near the screen. This has all kinds of benefits, but the most important one might be that the browser will not bother decoding our blurry placeholder image or the image itself unless it has to, saving CPU.&lt;/p&gt;
&lt;h3 id=&quot;update-01%2F27%2F2021-contain-intrinsic-size-no-longer-needed&quot;&gt;Update 01/27/2021 contain-intrinsic-size no longer needed &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#update-01%2F27%2F2021-contain-intrinsic-size-no-longer-needed&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An earlier version of this post explained how to use &lt;code&gt;contain-intrinsic-size&lt;/code&gt; to avoid CLS impact of &lt;code&gt;content-visibility: auto&lt;/code&gt; but as of Chromium 88 this is no longer needed for images that provide &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; as explained above. Other browser engines do &lt;a href=&quot;https://caniuse.com/?search=content-visibility&quot;&gt;not yet (01/27/2021) implement &lt;code&gt;content-visibility: auto&lt;/code&gt;&lt;/a&gt; and would presumably follow Chromium&#39;s lead on this special case. So, yaihh, this is much simpler now!&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* This probably only makes sense for images within the main scrollable area of your page. */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;main img&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;/* Only render when in viewport */&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;content-visibility&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;avif&quot;&gt;AVIF &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#avif&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://jakearchibald.com/2020/avif-has-landed/&quot;&gt;AVIF&lt;/a&gt; is the most recent image format that has gained adoption in web browsers. It is currently supported in Chromium browsers, and available behind a flag in Firefox. Safari support isn&#39;t available yet, but given that Apple is a member of the &lt;a href=&quot;http://aomedia.org/&quot;&gt;group&lt;/a&gt; that is behind the format, we can expect future support.&lt;/p&gt;
&lt;p&gt;AVIF is notable because it very consistently outperforms JPEG in a very significant way. This is different from WebP which doesn&#39;t always produce smaller images than JPEG and may actually be a net-loss due to lack of support for progressive loading.&lt;/p&gt;
&lt;p&gt;For more info on &lt;a href=&quot;https://www.industrialempathy.com/posts/avif-webp-quality-settings/&quot;&gt;AVIF encoding and quality settings, check out my dedicated blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To implement progressive enhancement for AVIF, use the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture&quot;&gt;&lt;code&gt;picture&lt;/code&gt; element&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The actual &lt;code&gt;img&lt;/code&gt; element is nested in the &lt;code&gt;picture&lt;/code&gt;. This can be quite confusing, because the &lt;code&gt;img&lt;/code&gt; is sometimes described as fallback for browsers without picture support but basically the &lt;code&gt;picture&lt;/code&gt; element only helps with &lt;code&gt;src&lt;/code&gt; selection but has no layout itself. The element that is drawn (and which you style) is the &lt;code&gt;img&lt;/code&gt; element.&lt;/p&gt;
&lt;p&gt;Until very recently it was relatively difficult to actually encode AVIF images on the server-side, but with the latest version of libraries like &lt;a href=&quot;https://github.com/lovell/sharp&quot;&gt;sharp&lt;/a&gt; it is now trivial.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 608px) 100vw, 608px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;br /&gt;      /img/Z1s3TKV-1920w.avif 1920w,&lt;br /&gt;      /img/Z1s3TKV-1280w.avif 1280w,&lt;br /&gt;      /img/Z1s3TKV-640w.avif   640w,&lt;br /&gt;      /img/Z1s3TKV-320w.avif   320w&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image/avif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- snip lots of other stuff --&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;load-the-right-number-of-pixels&quot;&gt;Load the right number of pixels &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#load-the-right-number-of-pixels&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You might have noticed the &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; attributes in the snippet above. Using the &lt;code&gt;w&lt;/code&gt; selector it tells the browser which URL to use based on the physical pixels that would be used if the image was drawn to the user&#39;s device given the width calculated from the &lt;code&gt;sizes&lt;/code&gt; attribute (which is a media query expression).&lt;/p&gt;
&lt;p&gt;With this the browser will always download the smallest possible image that provides the best image quality for the user. Or it may select a smaller image if, for example, the user has opted into some kind of data-saving mode.&lt;/p&gt;
&lt;h3 id=&quot;fallbacks&quot;&gt;Fallbacks &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#fallbacks&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Provide more source elements with &lt;code&gt;srcset&lt;/code&gt;s for browsers that only support legacy image formats.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 608px) 100vw, 608px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;br /&gt;    /img/Z1s3TKV-1920w.webp 1920w,&lt;br /&gt;    /img/Z1s3TKV-1280w.webp 1280w,&lt;br /&gt;    /img/Z1s3TKV-640w.webp   640w,&lt;br /&gt;    /img/Z1s3TKV-320w.webp   320w&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image/webp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(max-width: 608px) 100vw, 608px&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;br /&gt;    /img/Z1s3TKV-1920w.jpg 1920w,&lt;br /&gt;    /img/Z1s3TKV-1280w.jpg 1280w,&lt;br /&gt;    /img/Z1s3TKV-640w.jpg   640w,&lt;br /&gt;    /img/Z1s3TKV-320w.jpg   320w&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image/jpeg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;caching-%2F-immutable-urls&quot;&gt;Caching / Immutable URLs &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#caching-%2F-immutable-urls&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Embed a hash of the bytes in the image in the URL of the image. In the examples above I&#39;m doing that with the &lt;code&gt;Z1s3TKV&lt;/code&gt; in the image URLs. That way the URL will change if the image changes and respectively you can apply infinite cache expiration for your images. You want your caching headers to look something like this &lt;code&gt;cache-control: public,max-age=31536000,immutable&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;immutable&lt;/code&gt; is the semantically correct &lt;code&gt;cache-control&lt;/code&gt; value, but unfortunately it isn&#39;t widely supported in browsers (I&#39;m looking at you, Chrome). &lt;code&gt;max-age=31536000&lt;/code&gt; is the fallback to cache for a year. &lt;code&gt;public&lt;/code&gt; is important to allow your CDN to cache the image and deliver it from the edge. But only use that if it is appropriate from a privacy perspective.&lt;/p&gt;
&lt;h2 id=&quot;lazy-loading&quot;&gt;Lazy loading &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#lazy-loading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Adding &lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt; to the &lt;code&gt;img&lt;/code&gt; instructs the browser to only start fetching the image as it gets closer to the screen and is likely to actually be rendered.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;lazy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;…&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;asynchronous-decoding&quot;&gt;Asynchronous decoding &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#asynchronous-decoding&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Adding &lt;code&gt;decoding=&amp;quot;async&amp;quot;&lt;/code&gt; to the &lt;code&gt;img&lt;/code&gt; gives the browser permission to decode the image off the main thread avoiding user impact of the CPU-time used to decode the image. This should have no discernible downside except that it cannot always be the default for legacy reasons.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;decoding&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;async&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;…&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;blurry-placeholder&quot;&gt;Blurry placeholder &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#blurry-placeholder&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A blurry placeholder is an inline image that provides the user some notion of the image that will load eventually without requiring fetching bytes from the network.&lt;/p&gt;
&lt;img alt=&quot;Sample blurry placeholder&quot; src=&quot;https://www.industrialempathy.com/img/blurry.svg&quot; width=&quot;1280&quot; height=&quot;853&quot; /&gt;
&lt;p&gt;Some notes on the implementation provided here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It inlines the blurry placeholder as a &lt;code&gt;background-image&lt;/code&gt; of the image. This avoids using a second HTML element and it naturally hides the placeholder when the image loads, so that no JavaScript is needed to implement this.&lt;/li&gt;
&lt;li&gt;It wraps the data URI of the actual image in a data URI of a SVG image. That is done because the blurring of the image is done at the SVG level instead of through a CSS filter. The result is that the blurring is only performed once per image when the SVG is rasterized, instead of on every layout saving CPU.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;br /&gt;      …&lt;br /&gt;      background-size: cover;&lt;br /&gt;      background-image: &lt;br /&gt;        url(&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;data:image/svg+xml;charset=utf-8,%3Csvg xmlns=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;http%3A//www.w3.org/2000/svg\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;&lt;br /&gt;        xmlns%3Axlink=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;http%3A//www.w3.org/1999/xlink\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; viewBox=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;0 0 1280 853\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;%3E%3Cfilter id=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;b\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; color-interpolation-filters=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;sRGB\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;%3E%3CfeGaussianBlur stdDeviation=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;.5\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;%3E%3C/feGaussianBlur%3E%3CfeComponentTransfer%3E%3CfeFuncA type=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;discrete\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; tableValues=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;1 1\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;%3E%3C/feFuncA%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;url(%23b)\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; x=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;0\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; y=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;0\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; height=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;100%25\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; width=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;100%25\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; &lt;br /&gt;        xlink%3Ahref=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;data%3Aimage/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAGCAIAAACepSOSAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAs0lEQVQI1wGoAFf/AImSoJSer5yjs52ktp2luJuluKOpuJefsoCNowB+kKaOm66grL+krsCnsMGrt8m1u8mzt8OVoLIAhJqzjZ2tnLLLnLHJp7fNmpyjqbPCqLrRjqO7AIeUn5ultaWtt56msaSnroZyY4mBgLq7wY6TmwCRfk2Pf1uzm2WulV+xmV6rmGyQfFm3nWSBcEIAfm46jX1FkH5Djn5AmodGo49MopBLlIRBfG8yj/dfjF5frTUAAAAASUVORK5CYII=\&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;%3E%3C/image%3E%3C/svg%3E&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;);&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;…&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;(optional-ish)-javascript-optimization&quot;&gt;(Optional-ish) JavaScript optimization &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#(optional-ish)-javascript-optimization&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Browsers may feel obliged to rasterize the blurry placeholder even if the image is already loaded. By removing it on image load, we solve that problem. Also, if your images contain transparency, then this is actually &lt;em&gt;not&lt;/em&gt; optional as otherwise the placeholder would shine through.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;load&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tagName &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IMG&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Remove the blurry placeholder.&lt;/span&gt;&lt;br /&gt;      e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;backgroundImage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;/* capture */&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;tools&quot;&gt;Tools &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/image-optimizations/#tools&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is a list of known technologies and tools implementing all of these optimizations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/google/eleventy-high-performance-blog&quot;&gt;eleventy-high-performance-blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nextjs.org/docs/api-reference/next/image&quot;&gt;Next.js&#39; next/image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kaliber5/ember-responsive-image&quot;&gt;ember-responsive-image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you know of a technology (can be a combination of multiple &amp;quot;modules&amp;quot; or similar if they work well together) that should be on this list, please &lt;a href=&quot;https://twitter.com/cramforce&quot;&gt;ping me&lt;/a&gt;.&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fimage-optimizations%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Maximally%20optimizing%20image%20loading%20for%20the%20web&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in December, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/december-2020.html"/>
		<updated>2020-12-15T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/december-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1338850567565824001&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Best use of your time today&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1338850567565824001&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1336718249388625921&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1336718249388625921&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1337560178061963266&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Baseline import maps. No differential loading yet&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1337560178061963266&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1337818473368596481&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Partioned caches in all browsers&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1337818473368596481&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1330968468603039744&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;getUserMedia in WebKit!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1330968468603039744&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1332015868725891076&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Finally!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1332015868725891076&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1333711930004025346&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Preload in Firefox (Finally!!)&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1333711930004025346&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1334624616799559681&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;:not(:not(aspect-ratio))&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1334624616799559681&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1336211409714126848&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Privacy-preserving prefetch experiment&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1336211409714126848&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fdecember-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in November, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/november-2020.html"/>
		<updated>2020-11-18T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/november-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1320748313487048704&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Happy-ending for WASM team after Mozilla layoffs&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1320748313487048704&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1322671073893126144&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Incredible attack&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1322671073893126144&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1326307965884796928&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…and the mitigation&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1326307965884796928&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1324730352229863425&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Hell freezing over&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1324730352229863425&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1326192937164705797&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;PX launch date&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1326192937164705797&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1326557615019732992&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;RIP `Webmaster`&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1326557615019732992&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1326652757739180033&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;RIP H2 Push&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1326652757739180033&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fnovember-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in October, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/october-2020.html"/>
		<updated>2020-10-21T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/october-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1316434064392384512&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Auto-upgrade of mixed content&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1316434064392384512&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1316767692620267520&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Interesting blurry-image technique&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1316767692620267520&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1318298315096649728&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Also available on Android&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1318298315096649728&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1311443621267333120&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;RIP FTP&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1311443621267333120&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1311684961322242050&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1311684961322242050&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1313453703597355019&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;You don&amp;#39;t know HTML&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1313453703597355019&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1313568582274433025&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;New ways to not need 3P 🍪s&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1313568582274433025&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1313509725611253763&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Web Stories in Discover&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1313509725611253763&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1313881488572788737&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Aspect-ratio CSS is shipping in Chrome&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1313881488572788737&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Foctober-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in September, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/september-2020.html"/>
		<updated>2020-09-23T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/september-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1303290847958573057&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Now only the tooling needs to catch up&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1303290847958573057&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1308423009011732480&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;What devs want&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1308423009011732480&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1308463019312123904&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;WordPress Web Stories editor launched&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1308463019312123904&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1308301194020810752&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Worth the copy-paste&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1308301194020810752&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1307048452753362944&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;API for whether doing work now is OK&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1307048452753362944&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1306367936895086594&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Safari 14 is here&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1306367936895086594&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1303347360349609984&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Debug iOS browsers from MacOS/Windows&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1303347360349609984&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1301837938985177089&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I made something&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1301837938985177089&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1301262894617640960&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Focus is our friend&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1301262894617640960&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1300817754413510664&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Filter the worst ads&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1300817754413510664&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1299389616924000256&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;content-visibility is the most important Web API of our time&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1299389616924000256&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1298994931361411077&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1298994931361411077&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1298182564570693634&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Easy way to get on top of Chrome releases&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1298182564570693634&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1295444261928828930&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Monthly-ish IE update&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1295444261928828930&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1295390463038349312&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Fast page labeling in Chrome Beta&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1295390463038349312&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fseptember-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>A high-performance blog template for 11ty</title>
		<link href="https://www.industrialempathy.com/posts/eleventy-high-performance-blog/"/>
		<updated>2020-09-01T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/eleventy-high-performance-blog/</id>
		<content type="html">
		  
		    &lt;p&gt;I&#39;m excited to announce the beta-release of &lt;a href=&quot;https://github.com/google/eleventy-high-performance-blog&quot;&gt;eleventy-high-performance-blog&lt;/a&gt;–a high-performance blog template for &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;11ty&lt;/a&gt; based on this very website. The template itself is based on the awesome &lt;a href=&quot;https://github.com/11ty/eleventy-base-blog/&quot;&gt;eleventy-base-blog&lt;/a&gt; adding features centered around performance, accessibility and some SEO.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.glitch.com/db98564e-04da-47bf-a3d6-70803c3d0fe7%2FScreen%20Shot%202020-09-04%20at%2012.07.27.png?v=1599214260591&quot; alt=&quot;100 points in all relevant lighthouse categories&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Sites based on this template achieve 100 points on Lighthouse in the categories Performance, Accessibility, Best Practices, and SEO by default. Field-test performance in &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint&lt;/a&gt;, &lt;a href=&quot;https://web.dev/cls/&quot;&gt;Cumulative Layout Shift&lt;/a&gt;, is &lt;a href=&quot;https://web.dev/fid/&quot;&gt;First Input Delay&lt;/a&gt; is very well into the green area of &lt;a href=&quot;https://web.dev/vitals/&quot;&gt;Core Web Vitals&lt;/a&gt; given standard server performance.&lt;/p&gt;
&lt;p&gt;This website which is using the same template recently ranked #2 on the &lt;a href=&quot;https://www.11ty.dev/speedlify/&quot;&gt;Eleventy Speed Leaderboard.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/google/eleventy-high-performance-blog#getting-started&quot;&gt;Get started!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#features&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;performance-optimizations&quot;&gt;Performance optimizations &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#performance-optimizations&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;images&quot;&gt;Images &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#images&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Transcodes images to &lt;a href=&quot;https://en.wikipedia.org/wiki/AV1#AV1_Image_File_Format_(AVIF)&quot;&gt;AVIF&lt;/a&gt; (the latest widely supported next-gen image codec) and &lt;a href=&quot;https://developers.google.com/speed/webp&quot;&gt;webp&lt;/a&gt; and generates &lt;code&gt;picture&lt;/code&gt; element.&lt;/li&gt;
&lt;li&gt;Transcodes GIFs to muted looping autoplaying MP4 videos for greatly reduced file size.&lt;/li&gt;
&lt;li&gt;Generates multiple sizes of each image and uses them in &lt;strong&gt;&lt;code&gt;srcset&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Generates a &lt;strong&gt;blurry placeholder&lt;/strong&gt; for each image (without adding an HTML element or using JS).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lazy loads&lt;/strong&gt; images (using &lt;a href=&quot;https://web.dev/native-lazy-loading/&quot;&gt;native &lt;code&gt;loading=lazy&lt;/code&gt;&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Async decodes&lt;/strong&gt; images (using &lt;code&gt;decoding=async&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lazy layout&lt;/strong&gt; of images and placeholders using &lt;a href=&quot;https://web.dev/content-visibility/#skipping-rendering-work-with-content-visibility&quot;&gt;&lt;code&gt;content-visibility: auto&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoids CLS impact&lt;/strong&gt; of images by inferring and providing width and height (Supported in Chrome, Firefox and Safari 14+).&lt;/li&gt;
&lt;li&gt;Downloads remote images and stores/serves them locally.&lt;/li&gt;
&lt;li&gt;Immutable URLs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;css&quot;&gt;CSS &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#css&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Defaults to the compact &amp;quot;classless&amp;quot; &lt;a href=&quot;https://kimeiga.github.io/bahunya/&quot;&gt;Bahunya CSS framework&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Inlines CSS.&lt;/li&gt;
&lt;li&gt;Dead-code-eliminates / tree-shakes / purges (pick your favorite word) unused CSS on a per-page basis with &lt;a href=&quot;https://purgecss.com/&quot;&gt;PurgeCSS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Minified CSS with &lt;a href=&quot;https://www.npmjs.com/package/csso&quot;&gt;csso&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;miscellaneous&quot;&gt;Miscellaneous &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#miscellaneous&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Immutable URLs for JS.&lt;/li&gt;
&lt;li&gt;Sets immutable caching headers for images, fonts, and JS (CSS is inlined). Currently implements for Netflify &lt;code&gt;_headers&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Minifies HTML and optimizes it for compression. Uses &lt;a href=&quot;https://www.npmjs.com/package/html-minifier&quot;&gt;html-minifier&lt;/a&gt; with aggressive options.&lt;/li&gt;
&lt;li&gt;Uses &lt;a href=&quot;https://rollupjs.org/&quot;&gt;rollup&lt;/a&gt; to bundle JS and minifies it with &lt;a href=&quot;https://terser.org/&quot;&gt;terser&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Prefetches same-origin navigations when a navigation is likely.&lt;/li&gt;
&lt;li&gt;If an AMP files is present, &lt;a href=&quot;https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/optimize_amp/&quot;&gt;optimizes it&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;fonts&quot;&gt;Fonts &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#fonts&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Serves fonts from same origin.&lt;/li&gt;
&lt;li&gt;Preloads fonts.&lt;/li&gt;
&lt;li&gt;Makes fonts &lt;code&gt;display:optional&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;analytics&quot;&gt;Analytics &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#analytics&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Supports locally serving Google Analytics&#39;s JS and proxying it&#39;s hit requests to a Vercel Edge Function proxy (other proxies could be easily added).&lt;/li&gt;
&lt;li&gt;Support for noscript hit requests.&lt;/li&gt;
&lt;li&gt;Avoids blocking onload on analytics requests.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;dx-features&quot;&gt;DX features &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#dx-features&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Uses 🚨 as favicon during local development.&lt;/li&gt;
&lt;li&gt;Supports a range of default tests.&lt;/li&gt;
&lt;li&gt;Runs build and tests on &lt;code&gt;git push&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sourcemap generated for JS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;seo-%26-social&quot;&gt;SEO &amp;amp; Social &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#seo-%26-social&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Share button prefering &lt;code&gt;navigator.share()&lt;/code&gt; and falling back to Twitter. Using OS-like share-icon.&lt;/li&gt;
&lt;li&gt;Support for OGP metadata.&lt;/li&gt;
&lt;li&gt;Support for Twitter metadata.&lt;/li&gt;
&lt;li&gt;Support for &lt;a href=&quot;http://schema.org/&quot;&gt;schema.org&lt;/a&gt; JSON-LD.&lt;/li&gt;
&lt;li&gt;Sitemap.xml generation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;largely-useless-glitter&quot;&gt;Largely useless glitter &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#largely-useless-glitter&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Read time estimate.&lt;/li&gt;
&lt;li&gt;Animated scroll progress bar…&lt;/li&gt;
&lt;li&gt;…with an optimized implementation that should never cause a layout.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;security&quot;&gt;Security &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#security&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Generates a strong CSP for the base template.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Default-src is &lt;code&gt;self&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Disallows plugins.&lt;/li&gt;
&lt;li&gt;Generates hash based CSP for the JS used on the site.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting started &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/eleventy-high-performance-blog/#getting-started&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/google/eleventy-high-performance-blog#getting-started&quot;&gt;Hop on over to GitHub.&lt;/a&gt;&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Feleventy-high-performance-blog%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=A%20high-performance%20blog%20template%20for%2011ty&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in August, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/august-2020.html"/>
		<updated>2020-08-12T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/august-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1293270572424663041&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;MDN and Servo teams among those layed off&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1293270572424663041&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1293236234932846596&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Same-site cookies in Chrome to 100%&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1293236234932846596&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1291011672786767875&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Be in the DOM, but not rendered, but take space&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1291011672786767875&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1289679221313290240&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;WebGL2 in Safari&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1289679221313290240&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1289185313747697668&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Full referrers are now opt-in in Chrome&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1289185313747697668&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1282651980171804673&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Choose and fund your favorite browser feature&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1282651980171804673&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1288131729811574785&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Web Stories are exciting!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1288131729811574785&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1286042426818404354&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Strict-Soy as a web standard&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1286042426818404354&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Faugust-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in July, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/july-2020.html"/>
		<updated>2020-07-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/july-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1280348541076910083&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I wrote a thing&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1280348541076910083&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1280191704092426240&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;We&amp;#39;re continuing to fund browser compat&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1280191704092426240&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1278357702121381888&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;WYSIWYG is coming back to the web!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1278357702121381888&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1273806785497858049&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Related to previous entry&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1273806785497858049&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1277983235641761795&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;WeakRefs!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1277983235641761795&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1277601324557893632&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;We can&amp;#39;t have nice things 😿&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1277601324557893632&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1275171897244823553&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Some nice things&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1275171897244823553&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1280625051822436353&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;But they will stilll be WebKit wrappers&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1280625051822436353&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjuly-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Design Docs at Google</title>
		<link href="https://www.industrialempathy.com/posts/design-docs-at-google/"/>
		<updated>2020-07-06T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/design-docs-at-google/</id>
		<content type="html">
		  
		    &lt;p&gt;One of the key elements of Google&#39;s software engineering culture is the use of design docs for defining software designs. These are relatively informal documents that the primary author or authors of a software system or application create before they embark on the coding project. The design doc documents the high level implementation strategy and key design decisions with emphasis on the trade-offs that were considered during those decisions.&lt;/p&gt;
&lt;p&gt;As software engineers our job is not to produce code per se, but rather to solve problems. Unstructured text, like in the form of a design doc, may be the better tool for solving problems early in a project lifecycle, as it may be more concise and easier to comprehend, and communicates the problems and solutions at a higher level than code.&lt;/p&gt;
&lt;p&gt;Besides the original documentation of a software design, design docs fulfill the following functions in the software development lifecycle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Early identification of design issues when making changes is still cheap.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Achieving consensus around a design in the organization.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ensuring consideration of cross-cutting concerns.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scaling knowledge of senior engineers into the organization.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Form the basis of an organizational memory around design decisions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Acts as a summary artifact in the technical portfolio of the software designer(s).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;anatomy-of-a-design-doc&quot;&gt;Anatomy of a design doc &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#anatomy-of-a-design-doc&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Design docs are informal documents and thus don’t follow a strict guideline for their content. Rule #1 is: Write them in whatever form makes the most sense for the particular project.&lt;/p&gt;
&lt;p&gt;Having said that, a certain structure has established itself as really useful.&lt;/p&gt;
&lt;h3 id=&quot;context-and-scope&quot;&gt;Context and scope &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#context-and-scope&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This section gives the reader a very rough overview of the landscape in which the new system is being built and what is actually being built. This isn’t a requirements doc. Keep it succinct! The goal is that readers are brought up to speed but some previous knowledge can be assumed and detailed info can be linked to. This section should be entirely focused on objective background facts.&lt;/p&gt;
&lt;h3 id=&quot;goals-and-non-goals&quot;&gt;Goals and non-goals &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#goals-and-non-goals&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A short list of bullet points of what the goals of the system are, and, sometimes more importantly, what non-goals are. Note, that non-goals aren’t negated goals like “The system shouldn’t crash”, but rather things that could reasonably be goals, but are explicitly chosen not to be goals. A good example would be “ACID compliance”; when designing a database, you’d certainly want to know whether that is a goal or non-goal. And if it is a non-goal you might still select a solution that provides it, if it doesn’t introduce trade-offs that prevent achieving the goals.&lt;/p&gt;
&lt;h3 id=&quot;the-actual-design&quot;&gt;The actual design &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#the-actual-design&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This section should start with an overview and then go into details.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.pinimg.com/originals/fe/8f/26/fe8f26548e9c75575a0e0d25a88e58e4.jpg&quot; alt=&quot;Visualization of how to draw an owl. First picture: two circles labeled &amp;quot;1. Draw some circles&amp;quot;. Second picture: Picture of an own labeled &amp;quot;2. Draw the rest of the fucking owl&amp;quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The design doc is &lt;em&gt;the place to write down the trade-offs&lt;/em&gt; you made in designing your software. Focus on those trade-offs to produce a useful document with long-term value. That is, given the context (facts), goals and non-goals (requirements), the design doc is the place to suggest solutions and show why a particular solution best satisfies those goals.&lt;/p&gt;
&lt;p&gt;The point of writing a document over a more formal medium is to provide the flexibility to express the problem set at hand in an appropriate manner. Because of this, there is no explicit guidance for how to actually describe the design.&lt;/p&gt;
&lt;p&gt;Having said that, a few best practices and repeating topics have emerged that make sense for a large percentage of design docs:&lt;/p&gt;
&lt;h4 id=&quot;system-context-diagram&quot;&gt;&lt;strong&gt;System-context-diagram&lt;/strong&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#system-context-diagram&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In many docs a &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/System_context_diagram&quot;&gt;system-context-diagram&lt;/a&gt;&lt;/em&gt; can be very useful. Such a diagram shows the system as part of the larger technical landscape and allows readers to contextualize the new design given its environment that they are already familiar with.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.glitch.com/c009eee5-8b56-48f0-aca5-17e8616ed08c%2Fsystem%20context%20diagram1.png?v=1594062998536&quot; alt=&quot;Block diagram showing how various systems are related to each other. The actual text is just examples and not needed to be seen to understand the example.&quot; /&gt; &lt;br /&gt;
&lt;em&gt;Example of a system-context-diagram.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;apis&quot;&gt;APIs &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#apis&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;If the system under design exposes an API, then sketching out that API is usually a good idea. In most cases, however, one should withstand the temptation to copy-paste formal interface or data definitions into the doc as these are often verbose, contain unnecessary detail and quickly get out of date. Instead focus on the parts that are relevant to the design and its trade-offs.&lt;/p&gt;
&lt;h4 id=&quot;data-storage&quot;&gt;Data storage &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#data-storage&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Systems that store data should likely discuss how and in what rough form this happens. Similar to the advice on APIs, and for the same reasons, copy-pasting complete schema definitions should be avoided. Instead focus on the parts that are relevant to the design and its trade-offs.&lt;/p&gt;
&lt;h4 id=&quot;code-and-pseudo-code&quot;&gt;Code and pseudo-code &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#code-and-pseudo-code&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Design docs should rarely contain code, or pseudo-code except in situations where novel algorithms are described. As appropriate, link to prototypes that show the implementability of the design.&lt;/p&gt;
&lt;h4 id=&quot;degree-of-constraint&quot;&gt;Degree of constraint &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#degree-of-constraint&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;One of the primary factors that would influence the shape of a software design and hence the design doc, is the degree of constraint of the solution space.&lt;/p&gt;
&lt;p&gt;On one end of the extreme is the “greenfield software project”, where all we know are the goals, and the solution can be whatever makes the most sense. Such a document may be wide-ranging, but it also needs to quickly define a set of rules that allow zooming in on a manageable set of solutions.&lt;/p&gt;
&lt;p&gt;On the other end are systems where the possible solutions are very well defined, but it isn’t at all obvious how they could even be combined to achieve the goals. This may be a legacy system that is difficult to change and wasn’t designed to do what you want it to do or a library design that needs to operate within the constraints of the host programming language.&lt;/p&gt;
&lt;p&gt;In this situation you may be able to enumerate all the things you can do relatively easily, but you need to creatively put those things together to achieve the goals. There may be multiple solutions, and none of them are really great, and hence such a document should focus on selecting the best way given all identified trade-offs.&lt;/p&gt;
&lt;h3 id=&quot;alternatives-considered&quot;&gt;Alternatives considered &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#alternatives-considered&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This section lists alternative designs that would have reasonably achieved similar outcomes. The focus should be on the trade-offs that each respective design makes and how those trade-offs led to the decision to select the design that is the primary topic of the document.&lt;/p&gt;
&lt;p&gt;While it is fine to be succinct about solution that ended up not being selected, this section is one of the most important ones as it shows very explicitly why the selected solution is the best given the project goals and how other solutions, that the reader may be wondering about, introduce trade-offs that are less desirable given the goals.&lt;/p&gt;
&lt;h3 id=&quot;cross-cutting-concerns&quot;&gt;Cross-cutting concerns &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#cross-cutting-concerns&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is where your organization can ensure that certain cross-cutting concerns such as security, privacy, and observability are always taken into consideration. These are often relatively short sections that explain how the design impacts the concern and how the concern is addressed. Teams should standardize what these concerns are in their case.&lt;/p&gt;
&lt;p&gt;Due to their importance, Google projects are required to have a dedicated privacy design doc, and there are dedicated reviews for privacy and security. While the reviews are only required to be completed by the time a project launches, it is best practice to engage with privacy and security teams as early as possible to ensure that designs take them into account from the ground up. In case of dedicated docs for these topics, the central design doc can, of course, reference them instead of going into detail.&lt;/p&gt;
&lt;h3 id=&quot;the-length-of-a-design-doc&quot;&gt;The length of a design doc &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#the-length-of-a-design-doc&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Design docs should be sufficiently detailed but short enough to actually be read by busy people. The sweet spot for a larger project seems to be around 10-20ish pages. If you get way beyond that, it might make sense to split up the problem into more manageable sub problems. It should also be noted that it is absolutely possible to write a 1-3 page “mini design doc”. This is especially helpful for incremental improvements or sub tasks in an agile project–you still do all the same steps as for a longer doc, just keep things more terse and focused on a limited problem set.&lt;/p&gt;
&lt;h2 id=&quot;when-not-to-write-a-design-doc.&quot;&gt;When &lt;em&gt;not&lt;/em&gt; to write a design doc. &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#when-not-to-write-a-design-doc.&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Writing design docs is overhead. The decision whether to write a design doc comes down to the core trade-off of deciding whether the benefits in organizational consensus around design, documentation, senior review, etc. outweigh the extra work of creating the doc. At the center of that decision lies whether the solution to the design problem is ambiguous–because of problem complexity or solution complexity, or both. If it is not, then there is little value in going through the process of writing a doc.&lt;/p&gt;
&lt;p&gt;A clear indicator that a doc might not be necessary are design docs that are really &lt;em&gt;implementation manuals&lt;/em&gt;. If a doc basically says “This is how we are going to implement it” without going into trade-offs, alternatives, and explaining decision making (or if the solution is so obvious as to mean there were no trade-offs), then it would probably have been a better idea to write the actual program right away.&lt;/p&gt;
&lt;p&gt;Finally, the overhead of creating and reviewing a design doc may not be compatible with prototyping and rapid iteration. However, most software projects do have a set of &lt;em&gt;actually known problems&lt;/em&gt;. Subscribing to agile methodologies is not an excuse for not taking the time to get solutions to actually known problems right. Additionally, prototyping itself may be part of the design doc creation. “I tried it out and it works” is one of the best arguments for choosing a design.&lt;/p&gt;
&lt;h2 id=&quot;the-design-doc-lifecycle&quot;&gt;The design doc lifecycle &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#the-design-doc-lifecycle&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The steps in the lifecycle of a design document are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Creation and rapid iteration&lt;/li&gt;
&lt;li&gt;Review (may be in multiple rounds)&lt;/li&gt;
&lt;li&gt;Implementation and iteration&lt;/li&gt;
&lt;li&gt;Maintenance and learning&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;creation-and-rapid-iteration&quot;&gt;Creation and rapid iteration &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#creation-and-rapid-iteration&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You write the doc. Sometimes together with a set of co-authors.&lt;/p&gt;
&lt;p&gt;This phase quickly evolves into a time of rapid iteration where the doc is shared with colleagues who have the most knowledge about the problem space (often belonging to the same team) and through their clarifying questions and suggestions drive the doc to a first relatively stable version.&lt;/p&gt;
&lt;p&gt;While you certainly find engineers and even teams who prefer version control and code review tools for document creation, the vast majority of design docs at Google are created in Google Docs and make heavy use of its collaboration features.&lt;/p&gt;
&lt;h3 id=&quot;review&quot;&gt;Review &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#review&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the review phase a design doc gets shared with a wider audience than the original set of authors and close collaborators. Reviews can add a lot of value, but they are also a dangerous trap of overhead, so treat them wisely.&lt;/p&gt;
&lt;p&gt;A review can take many shapes: The more lightweight version is simply sending out the doc to the (wider) team-list to give folks a chance to take a look. Discussion then primarily happens in comment threads in the document. On the heavy side of reviews, are formal design review meetings in which the author presents the doc (often via a dedicated presentation) to an often very senior engineering audience. Many teams at Google have recurring meetings scheduled for this purpose to which engineers can sign up to for a review. Naturally waiting for such meetings to happen can significantly slow down the development process. Engineers can mitigate this by seeking the most crucial feedback directly and not blocking progress on wider review.&lt;/p&gt;
&lt;p&gt;When Google was a smaller company, it was customary to send designs to a single central mailing list, where senior engineers would review them at their own leisure. This may very well be a great way to handle things for your company. One benefit was that it did establish a relatively uniform software design culture across the company. But as the company scaled to a much larger engineering team, it became infeasible to maintain the centralized approach.&lt;/p&gt;
&lt;p&gt;The primary value that such reviews add is that they form an opportunity for the combined experience of the organization to be incorporated into a design. Most consistently, ensuring that designs take cross-cutting concerns such as observability, security and privacy into account is something that can be ensured in a review stage. The primary value of the review isn’t that issues get discovered per-se, but rather that this happens relatively early in the development lifecycle when it is still relatively cheap to make changes.&lt;/p&gt;
&lt;h3 id=&quot;implementation-and-iteration&quot;&gt;Implementation and iteration &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#implementation-and-iteration&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When things have progressed sufficiently to have confidence that further reviews are unlikely to require major changes to the design, it is time to begin implementation. As plans collide with reality, it is inevitable that shortcomings, unaddressed requirements, or educated guesses that turned out to be wrong surface, and require changing the design. It is strongly recommended to update the design doc in this case. As a rule of thumb: If the designed system hasn’t shipped yet, then definitely update the doc. In practice we humans are bad at updating documents, and for other practical reasons changes are often isolated into new documents. This leads to an eventual state more akin to the US constitution with a bunch of amendments rather than one consistent piece of documentation. Links to such amendments from the original doc can be immensely helpful for the poor future maintenance programmer trying to understand their target system through design doc archaeology.&lt;/p&gt;
&lt;h3 id=&quot;maintenance-and-learning&quot;&gt;Maintenance and learning &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#maintenance-and-learning&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When Google engineers get confronted with a system that they hadn’t previously touched their first question often is “Where is the design doc?”. While design docs, like all documentation, tend to get out of sync with reality over time, they still often present the most accessible entry point to learn about the thinking that guided the creation of the system.&lt;/p&gt;
&lt;p&gt;As the author, do yourself a favor and re-read your own design docs a year or 2 later. What did you get right? What did you get wrong? What would you do to decide differently today? Answering these questions is a great way to advance as an engineer and improve software design skills over time.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#conclusions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Design docs are a great way to gain clarity and achieve consensus around solving the hardest problems in a software project. They save money, because they avoid going down coding rabbit holes that fail to achieve project goals and could have been avoided using upfront investigation; and they cost money, because creation and review take time. So, choose wisely for your project!&lt;/p&gt;
&lt;p&gt;When considering writing a design doc, think about these points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Are you unsure about the right software design, and would it make sense to spend upfront time to gain certainty?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Relatedly, would it help to involve senior engineers, who might not be able to review every code-change, in the design?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is the software design ambiguous or even contentious such that achieving organizational consensus around it would be valuable?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Does my team sometimes forget to consider privacy, security, logging or other cross-cutting concerns in the design?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is there a strong need for documents that provide high-level insights into the design of legacy systems in the organization?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you answer yes to 3 or more of these questions, then a design doc is probably a great method to start your next software project.&lt;/p&gt;
&lt;h1 id=&quot;related-posts&quot;&gt;Related posts &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/#related-posts&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/&quot;&gt;Design docs – A design doc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fdesign-docs-at-google%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Design%20Docs%20at%20Google&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in June, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/june-2020.html"/>
		<updated>2020-06-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/june-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Intentionally left Black&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1266036920582156288&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Core Web Vitals as a ranking factor in Google&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1266036920582156288&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1265254160087334912&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Modern-ish form styles in Chrome&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1265254160087334912&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1263962713585319937&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Core Web Vitals correlate with business success&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1263962713585319937&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1261346444780290050&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Very few ads use a huge percentage of resources&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1261346444780290050&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1260980901934137345&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Hell freezing over: aspect-ration in CSS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1260980901934137345&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1260701643311583234&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1260701643311583234&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjune-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in May, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/may-2020.html"/>
		<updated>2020-05-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/may-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1257335633900601344&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;What would you do with 4GB of RAM?&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1257335633900601344&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1257701879242514433&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Core Web Vitals = LCP + CLS + FID&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1257701879242514433&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1253311071093473286&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;RFC: WebBundles&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1253311071093473286&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1252798128560001025&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Blink is prototyping a virtual keyboard API&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1252798128560001025&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1252184196426104832&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Staying still is a regression&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1252184196426104832&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1252015710244499456&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Be nice online&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1252015710244499456&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1251107357804900352&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;April 17, 2020&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1251107357804900352&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1248135249663574017&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;AV1 based image format&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1248135249663574017&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1248036628154601472&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1248036628154601472&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fmay-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in April, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/april-2020.html"/>
		<updated>2020-04-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/april-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1241619866475474946&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;🤯&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1241619866475474946&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1246151601556828161&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Reducing extra-disruption due to COVID&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1246151601556828161&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1244653541379182596&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1244653541379182596&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1242608727267696640&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Won&amp;#39;t be missed&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1242608727267696640&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1242512468414324737&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Safari: 3P cookies gone for good. Client-side storage flaky&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1242512468414324737&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1239598070100180994&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Microsoft buys the rest of the JS ecosystem&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1239598070100180994&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1238543879042789377&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The creators of WebRTC are modern day heros!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1238543879042789377&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fapril-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in March, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/march-2020.html"/>
		<updated>2020-03-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/march-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1237408016250687488&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Lighthouse is updating to modern metrics&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1237408016250687488&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1237393102635012101&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Major new a11y features in DevTools&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1237393102635012101&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1237084305920155650&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;On my own behalf&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1237084305920155650&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1235074048859635712&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;The concept GIF &amp;gt; The GIF format&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1235074048859635712&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1233497327031267331&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;🍺🦠&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1233497327031267331&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fmarch-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Designing Even Larger Applications</title>
		<link href="https://www.industrialempathy.com/posts/designing-even-larger-applications/"/>
		<updated>2020-02-16T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/designing-even-larger-applications/</id>
		<content type="html">
		  
		    &lt;p&gt;This is a mildly edited transcript of my &lt;a href=&quot;https://www.youtube.com/watch?v=z4mRkhhHdWo&quot;&gt;JSConf Hawaiʻi talk (video)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hey everyone! My name is &lt;a href=&quot;https://twitter.com/cramforce&quot;&gt;Malte&lt;/a&gt;, I’m a Principal Software Engineer at Google, and today I want to talk about &lt;em&gt;Designing Even Larger Applications.&lt;/em&gt; This is a &lt;a href=&quot;https://www.industrialempathy.com/posts/designing-very-large-javascript-applications/&quot;&gt;sequel to a talk I gave at JSConf Australia two years ago&lt;/a&gt;. And just like last time, I want to kind of ground this talk in our career progression as software engineers. I think many of you in the audience would call yourself &lt;em&gt;senior engineers&lt;/em&gt;; or, if you’re not there yet, you aspire to be one.&lt;/p&gt;
&lt;p&gt;The way I would describe what it means to be a senior engineer is that if someone comes to me and they say something like &lt;em&gt;“Hey, Malte, do this project in this domain that you are already familiar with”,&lt;/em&gt; I would say &lt;em&gt;“Yeah, that is actually something I know how to do. I don’t need to get anyone else’s help”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In my last talk I looked at how to go beyond that level of seniority in software engineering. It stops being only about yourself and instead your craft starts impacting other engineers. You’d say &lt;em&gt;“I can anticipate how others do things and design APIs accordingly.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this talk I want to go yet one more level beyond that. I want to reach the stage where I can say, &lt;em&gt;“I can design software such that for &lt;strong&gt;large groups of engineers&lt;/strong&gt; the &lt;strong&gt;probability&lt;/strong&gt; increases that the software that they produce is &lt;strong&gt;good&lt;/strong&gt;.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3404/1*74apT-vKvnyGLkrZyEUwvQ.png&quot; alt=&quot;Good = Maintainable, high-performance, low bug density, on-time, …. Further Beyond Seniority: &amp;quot;I can design software such that for large groups of engineers the probability increases that the software that they produce is good.&amp;quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There are three key words in this statement.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First of all, &lt;em&gt;large groups of engineers&lt;/em&gt;. If you work at a startup or a three-person company, then this talk may seem superfluous and boring. But I think many of you may work for insurance companies, banks, agencies, big tech, etc.–companies big enough that you have a bunch of folks and multiple teams and you need to coordinate stuff.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next I’m talking about &lt;em&gt;probability&lt;/em&gt;. There is no certainty here. You can only try to set things up so that they are likely to work. But there are no guarantees. There is no silver bullet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The third key word is &lt;em&gt;good&lt;/em&gt;. This is not a &lt;em&gt;product management&lt;/em&gt; talk. This is not a talk that will not help you write the &lt;em&gt;right&lt;/em&gt; program, but it will help you write that program well. What I mean is it being maintainable, high-performance, having low bug-density, being delivered on-time, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I want to clarify one more thing: I’m going to say the words &lt;em&gt;framework&lt;/em&gt; and &lt;em&gt;software infrastructure&lt;/em&gt; a lot. I treat them kind of interchangeably. What I mean is software that helps us build better software. For this talk, I would like you all to kind of put your mind into you being the person in your company who is responsible for defining how people write software and, then, build the infrastructure that they’re using to write software. And when I say, you &lt;em&gt;build a framework&lt;/em&gt;, I don’t mean that you necessarily make your own React or Angular. Instead I think whenever you have a set of teams you want to kind of standardize how they build applications. So, you put a literal framework around it.&lt;/p&gt;
&lt;p&gt;Again, think about you being the person who is responsible for your team’s software infrastructure. This is a talk about how to make you successful at that job. And I’m going to talk about that in three chapters.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The first one I call &lt;em&gt;understanding the degree of uncertainty&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;…and then we’re going to learn how to &lt;em&gt;solve all known problems&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, we’re going to learn about &lt;em&gt;deploying change&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;understanding-the-degree-of-uncertainty&quot;&gt;Understanding the degree of uncertainty &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#understanding-the-degree-of-uncertainty&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;How certain are we about the type of problems that we will need to solve in the future? This question is absolutely key for software engineering and I’m going to talk about a technique to understand how well we understand things.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3404/1*RgFoTMZKMMJzCN4D6xvGoQ.png&quot; alt=&quot;Photo of Werner Heisenberg, discoverer of the Heisenberg uncertainty principle. Source https://commons.wikimedia.org/wiki/File:Bundesarchiv_Bild183-R57262,_Werner_Heisenberg.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;What we’ll do is try to answer a set of questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;What is it in the existing infrastructure that users struggle with and how are they struggling with it?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What is the class of applications that folks will build using your work in broad terms?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What are the trends that influence the industry and how do those trends influence the software that folks are probably going to write in the future?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these may sound a bit like reading the tea leaves but I think that with a bit of experience there are many scenarios where you can actually answer them quite well. The key in this exercise is really to observe how easy or hard it is to answer the questions.&lt;/p&gt;
&lt;p&gt;If it is really easy and you write it down and everything is clear, then you have a low degree of uncertainty. If, however, you actually have no idea how to answer, then you have a high degree of uncertainty.&lt;/p&gt;
&lt;p&gt;Even more powerful than knowing what it is that you need to do is knowing what you &lt;em&gt;don’t&lt;/em&gt; need to do. Those are the &lt;em&gt;non-goals&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;What are non-goals? It is &lt;em&gt;not&lt;/em&gt; a non-goal if you’re working for a software company to say &lt;em&gt;“I don’t need to design surfboards”&lt;/em&gt;. That is not a non-goal, that is just ridiculous. Of course, you don’t want to do this. A non-goal is something that is actually super reasonable and even likely that you want to do it but you know you don’t need to do it (like “I need to support low-end devices”). If you can easily define your non-goals, you know that your degree of uncertainty is even lower.&lt;/p&gt;
&lt;p&gt;So, why is it important for the degree of uncertainty to be low? When uncertainty is high you’re going to have to make tradeoffs and be flexible. You may think &lt;em&gt;“I might need to support this special case so I better make sure that it would be possible”&lt;/em&gt;. You likely need to make a tradeoff to enable that special case. And the problem with tradeoffs is that they make stuff complex and less than ideal because you have to find the balance between conflicting concerns.&lt;/p&gt;
&lt;p&gt;Things really get unpleasant when a high degree of uncertainty leads you to make an unnecessary tradeoff.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;unnecessary-tradeoffs-are-the-root-of-all-evil.&quot;&gt;&lt;em&gt;Unnecessary tradeoffs are the root of all evil.&lt;/em&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#unnecessary-tradeoffs-are-the-root-of-all-evil.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s look at an example: imagine you’re building infrastructure for internal mobile apps at your company and maybe the salespeople all have old phones with low memory. Based on this you design things such that they work on low memory devices. But then your company goes out and buys everyone fancy new phones. All your work to support low-end devices was unnecessary, and even worse it probably made the software more complex in the future as well. Interestingly this is a generalization of Donald Knuth’s &lt;em&gt;“premature optimization is the root of all evil”&lt;/em&gt;. Premature optimization is a special case of an unnecessary tradeoff. Every time you design your software for something it didn’t really need to support that is likely an unnecessary tradeoff.&lt;/p&gt;
&lt;p&gt;This talk is being held at a web development conference, so I wanted to have one section on web development. We as a community have been building web frameworks for a few years. Over 20 years now. We actually understand how to build web frameworks really well. The degree of uncertainty for what people want to do with web frameworks is really low.&lt;/p&gt;
&lt;p&gt;Compare that to this scenario: imagine it is 2015 and your manager comes and says &lt;em&gt;“I want you to build infrastructure for deep learning”&lt;/em&gt;. You’re like, well, I have never done this before. No one in my company has done it before. There are like literally three blog posts on the topic in total. The degree of uncertainty is really high. You won’t be able to build infrastructure that is quite as nice as a web framework in 2020.&lt;/p&gt;
&lt;h3 id=&quot;dealing-with-uncertainty&quot;&gt;Dealing with uncertainty &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#dealing-with-uncertainty&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3392/1*YBsQBbL1_I-boHZcwP4wwA.png&quot; alt=&quot;Photo of surgeons putting on medical gloves&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And so the question is: what do we do if the degree of uncertainty is very high? We tailor the degree of abstraction.&lt;/p&gt;
&lt;p&gt;Let me get something out of the way: &lt;em&gt;abstractions are awesome.&lt;/em&gt; You want to abstract everything as much as possible because abstractions make everything really expressive, more correct, reusable, and generally, more awesome. However, things rapidly fall apart if the abstractions don’t quite allow us to do exactly what we’d like to do. We now have to work around it and beat them into doing what we want. Everything is suddenly painful and terrible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;if-uncertainty-is-high-then-reduce-the-degree-of-abstraction.&quot;&gt;&lt;em&gt;If uncertainty is high then reduce the degree of abstraction.&lt;/em&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#if-uncertainty-is-high-then-reduce-the-degree-of-abstraction.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2112/1*RJv7TMI_kOkZPLuZKHd3ZA.png&quot; alt=&quot;Graph showing very unscientifically how uncertainty and abstraction should be related to another.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That is why we need to understand the problem space really well: It allows us to tailor the abstraction to the degree of uncertainty. And if uncertainty is high then we &lt;em&gt;reduce&lt;/em&gt; the degree of abstraction.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/6666/1*nGFDnipyGFG8kSCWizHNyA.png&quot; alt=&quot;Photo of abstract art and photo of woman looking remarkably similar to the abstraction Source https://www.publicdomainpictures.net/en/view-image.php?image=44807&amp;amp;picture=abstract-art-face https://www.flickr.com/photos/justanothersheena/6304824201 by Sheena876 licensed under CC https://creativecommons.org/licenses/by-sa/2.0/&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;solving-all-known-problems&quot;&gt;Solving all known problems &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#solving-all-known-problems&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every software project is going to have some degree of uncertainty. And so it is useful to have a set of techniques in our back pocket that are always good–no matter how uncertain we are: we’ll solve all known problems of software engineering.&lt;/p&gt;
&lt;h3 id=&quot;iteration-velocity&quot;&gt;Iteration velocity &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#iteration-velocity&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first technique is optimizing iteration velocity. What I mean is: you write some code and hit save in your editor–how long does it take to go from that moment until you find out whether it was a good change? You might have super awesome hot code reloading and everything updates instantly like magic or you may need to manually kill your Java application server, recompile, and restart the server which takes like 20 minutes. I think many of us have probably been somewhere in between these two extremes.&lt;/p&gt;
&lt;p&gt;Slow iteration cycles actually introduce tradeoffs into our software design. If it takes a long time to find out that you made a mistake then as a software designer, the professional thing to do is to then go and say &lt;em&gt;“I have to design this API so that no one can ever get it wrong”&lt;/em&gt;. If on the other hand everything is super fast and folks can figure things out iteratively because the cost of failure is so low, then you as a designer of that API can say, maybe it is fine for people to do a little bit more exploring here.&lt;/p&gt;
&lt;h3 id=&quot;debuggability&quot;&gt;Debuggability &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#debuggability&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Next is debuggability. As a framework author we actually have a strong influence on how hard it is to debug a system. Maybe you designed this awesome but complex black box state machine that no one can figure out. Maybe your stack traces are super long and confuse people. Or maybe you put in a sensible logging and tracing system and people understand what is going on. They make a mistake, they debug it, they fix it. No problem.&lt;/p&gt;
&lt;h3 id=&quot;testability&quot;&gt;Testability &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#testability&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Similar to the debuggability you’re in control of how testable a system is. Maybe your framework makes it really hard to instantiate things to be in a given state that can be tested? Or you make that really easy. Folks will write more tests, have higher confidence, and be a happier customer of your framework.&lt;/p&gt;
&lt;h3 id=&quot;empathy&quot;&gt;Empathy &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#empathy&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3404/1*G-B2aNC3aPYExoBKIebejQ.png&quot; alt=&quot;Photo of two cats. One says “I don’t know everything”. The other says “That’s OK”.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;For the last technique to solve all known problems of software engineering we’ll move a little bit away from the pure software side of things. We’ll talk about empathy.&lt;/p&gt;
&lt;p&gt;And like I &lt;a href=&quot;https://www.industrialempathy.com/posts/designing-very-large-javascript-applications/&quot;&gt;mentioned in my last talk&lt;/a&gt;: As a software engineer having empathy with other software engineers is empathy in easy mode. Our intuition for how a software engineer feels about something is much more likely to be correct than with a random person where we know little about their background. Today I want to talk about a very special aspect of empathy: You as the designer of framework could build the perfect application with it. You know everything about it. You can get everything right. But every other person who uses your framework will know less about it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;think-about-what-it-means-to-not-know-everything-about-your-framework.&quot;&gt;&lt;em&gt;Think about what it means to not know everything about your framework.&lt;/em&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#think-about-what-it-means-to-not-know-everything-about-your-framework.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, think about what it means to &lt;em&gt;not&lt;/em&gt; know everything about your framework. And how you can make the framework be robust in the presence of such not-all-knowing users.&lt;/p&gt;
&lt;h2 id=&quot;deploying-change&quot;&gt;Deploying change &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#deploying-change&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we have learned to solve all known problems of software engineering, let’s go to the final chapter which is &lt;em&gt;deploying change&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;if-it-has-no-users-then-it-has-no-impact.&quot;&gt;&lt;em&gt;If it has no users then it has no impact.&lt;/em&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#if-it-has-no-users-then-it-has-no-impact.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;This part is really, really key. Software infrastructure, no matter how great it is, if it has no users then it has no impact. However, in this field it is incredibly common that people build &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Ivory_tower&quot;&gt;ivory towers&lt;/a&gt;&lt;/em&gt; with no real users in mind. They build something they’re excited about, and it was probably really fun to build. And then they come and say &lt;em&gt;“Hey, I have a thing”&lt;/em&gt; and you’re like &lt;em&gt;“But that thing doesn’t do what I need”&lt;/em&gt; and everyone is sad and they move on to build the next ivory tower.&lt;/p&gt;
&lt;p&gt;If you want to professionalize building software infrastructure then this is obviously not the right way to do it. Getting your stuff adopted is everything. It is a big part of your job. So much so that my first piece of advice on how to get this right is actually totally in the realm of marketing.&lt;/p&gt;
&lt;p&gt;Software engineers are human beings. They want to work on stuff that they think is cool and that they’ve heard about on Twitter (Think “Serverless”, “Machine Learning”, “Virtual DOM”, $HypedThingOfTheYear). I think it is fine to sprinkle some of that glitter into your framework. As long as it isn’t the worst unnecessary tradeoff in the world. Everyone will be a little happier and no harm is done. That was the marketing portion of this talk. Let’s go to a bit more serious topic.&lt;/p&gt;
&lt;h3 id=&quot;incremental-adoption&quot;&gt;Incremental adoption &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#incremental-adoption&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3404/1*SC4YJ492eXYpM4hiNykZ0g.png&quot; alt=&quot;Photo of parents with their adopted child.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Adopting software is easier if you can do it incrementally. What this means is that instead of going like &lt;em&gt;“Hey, try this new framework, rewrite everything from scratch in two years and hopefully it is good”&lt;/em&gt;, you migrate smaller parts step by step–and thus you see positive impact long before that 2 year full rewrite. What I’ve seen is that even projects that start out as a full rewrite will often pivot to ship at least a few parts early as the pressure from essentially having to do double-work (maintaining the legacy system and building the new one) increases and management wants to see results.&lt;/p&gt;
&lt;p&gt;The path to incremental adoption, however, can be difficult for the framework designer. The following techniques have been proven to work in such scenarios.&lt;/p&gt;
&lt;h3 id=&quot;legacy-composition&quot;&gt;Legacy composition &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#legacy-composition&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first technique is really simple and comes in two parts.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The first is composition of your new framework code into legacy code: Let’s say you haven’t gotten around to rewriting the app shell yet. The app is still built on the old architecture. But then the team comes and says, &lt;em&gt;“I’m going to build that new feature based on the new framework and put it into that old code base”&lt;/em&gt;. &lt;em&gt;That is composition of new code into legacy code&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And then there is the other side which is composition of legacy code into your new code base. Let’s say you have this super ultra-customized component, a jQuery date picker, and people want to keep it, right? And so you design your framework such that the jQuery thing, which probably violates all the assumptions you ever made, still works in your new code base. &lt;em&gt;That is composition of legacy code into new code.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Both of these strategies put tradeoff pressure on your system because suddenly all these assumptions are no longer valid. But the tradeoff is probably worth it because it allows people to incrementally adopt your software.&lt;/p&gt;
&lt;h3 id=&quot;temporary-imperfection&quot;&gt;Temporary imperfection &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#temporary-imperfection&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The second technique is what I call &lt;em&gt;temporary imperfection&lt;/em&gt;. As a framework author, you probably have this really idealized view of the world how people build software using your framework. But then it comes crashing down in the process of incremental adoption because not everything is ideal at all, but rather an entangled mess of old and new code.&lt;/p&gt;
&lt;p&gt;My advice would be to do the following: Write a literal lint rule using a tool like &lt;a href=&quot;https://eslint.org/&quot;&gt;ESLint&lt;/a&gt; that identifies the old way of doing something. And then when there is code in the code base that is not written to the new way, you get an error message. Hopefully the error message also says something helpful like &lt;em&gt;“This is no longer the right way of doing it. Here are pointers to documentation for how to do it right”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Step two is to then go and allow all existing violations using an allow-list. With that you’re in a position where no code is fixed, but where all new code has to comply with the new way of doing things. And this is really powerful because there might be all these engineers in the organization who have not read &lt;em&gt;the email&lt;/em&gt; where they were told they need to do something differently. Now they get an error message and will just turn around and fix it.&lt;/p&gt;
&lt;h3 id=&quot;a-ledger-of-technical-debt&quot;&gt;A ledger of technical debt &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#a-ledger-of-technical-debt&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4006/1*-VWLN3P6hfyHTUZQFn2CpA.jpeg&quot; alt=&quot;Photo of a ledger&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There is one more interesting insight. This allow-list which you check into your repository is, in fact, &lt;em&gt;a ledger of technical debt&lt;/em&gt;. Technical debt can be this abstract concept that you know you have. It is probably out there somewhere but it is really difficult to nail down where it is. The ledger allows you to literally know that &lt;em&gt;file X.js, line 15&lt;/em&gt; has technical debt in it.&lt;/p&gt;
&lt;p&gt;Knowing where the technical debt is, is the first step to paying it off. You can e.g. have a team fix-it where all you do is make the allow-list shorter. I think that is a powerful way to make tech debt very concrete just like debt from your bank account.&lt;/p&gt;
&lt;h3 id=&quot;automated-migration&quot;&gt;Automated migration &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#automated-migration&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The next technique is to enable automated migration. It is not going to get you all the way but it is pretty powerful. Tools like &lt;a href=&quot;https://github.com/facebook/codemod&quot;&gt;codemod&lt;/a&gt; from Facebook can help with such a process. You declare how to go from A to B and the computer does the rest of the work. It is great.&lt;/p&gt;
&lt;p&gt;As many things in this talk, designing for automated migration puts tradeoff pressure on your new API because now your new API must ideally only require information that is already available in the existing codebase. But it might be worth it because no one has to do that work manually and it is going to make people more happy than having to do everything by hand.&lt;/p&gt;
&lt;h3 id=&quot;customer-zero&quot;&gt;Customer Zero &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#customer-zero&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s talk a little bit more about humans. The one thing I would like everyone to take away from this talk is that when you’re in this role of being the person responsible for the software infrastructure, you always need a &lt;em&gt;customer zero&lt;/em&gt;. Your customer zero is the antidote to the ivory tower. They are your first customer and you’ll be helping them to build a real product.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;your-customer-zero-is-the-antidote-to-the-ivory-tower.&quot;&gt;&lt;em&gt;Your customer zero is the antidote to the ivory tower.&lt;/em&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#your-customer-zero-is-the-antidote-to-the-ivory-tower.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;What you need to do is go and literally write their software with them–become part of their team. This is all happening before you declare your framework to be shippable because in this step you can actually validate your assumptions. You can find corner cases and you can iterate on your framework until it is actually good. This first customer should &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; be a migration. It should be something that you built from scratch. Because migrations are always going to be somewhat painful and long winding and you really don’t want to migrate to something that hasn’t been proven to be good.&lt;/p&gt;
&lt;p&gt;One of the ironies of being an infrastructure engineer is that you rarely build anything with your infrastructure yourself. That makes it really difficult to actually write the documentation for how to get started with your infra. If you go and have a customer zero and you work with them, that is the best chance you get to write that onboarding doc for everyone who comes after. Don’t miss the chance!&lt;/p&gt;
&lt;p&gt;Actually finding a customer zero can be challenging in large organizations. You might not find the team that is cool with working with an unstable framework that might be pretty bad. I’ve found a few arguments that work well to convince a team to be your customer zero:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;There is typically a team that likes to be on the cutting edge. One of the things that you can pitch is to say &lt;em&gt;“Hey, you’ll eventually have to migrate to this because it is the future stack everyone will have to use. Why don’t you want to be on the new thing already and skip that migration?”.&lt;/em&gt; That could be very attractive for a team. And you can argue that because you’re actually going to work with the team, they are going to get a framework tailor made for them–as opposed to everyone else who will have to make do with what is there.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If that pitch doesn’t work, you’ll have to move on to harsher tactics. In that case the organization has to be mature enough to accept that you’ll have to have a mandate. Someone will have to decide which team is going to be customer zero and they’ll have to accept it. Because the alternative is that you’d build an ivory tower. And that would be bad for everybody, not just that one team.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;migration-zero&quot;&gt;Migration Zero &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#migration-zero&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Eventually we’ll have to do a first migration of an existing code base to our new infra. Once again it is actually your job to do this migration yourself. That is because your framework might not actually be a great migration target yet. Let’s assume your framework is at point B and some project is at point A. It might be super hard to go from A to B. Any given team would probably just go ahead and do it anyway. But you as the author of the framework might see chances to slightly change that point B such that it is easier to get there. And because you’re a lazy person, you’re going to make that migration really easy and that is going to help everyone that comes after you have a much better time.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/#summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These were the three things that I wanted to talk about. Just let me summarize really quickly:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The first thing that we need to do is to understand the degree of uncertainty and then tailor the degree of abstraction respectively.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Even if uncertainty is high, we want to solve all known problems: Increase iteration velocity, make things debuggable, testable and practice our empathy with a focus on what folks might not know.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And then finally, nothing here matters if you don’t focus on team adoption. Make your software likable, focus on incremental adoption, make a ledger of technical debt, and get that customer and migration zero done.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That is all I have today. Thank you very much.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/cramforce&quot;&gt;Malte Ubl&lt;/a&gt;, 2020&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://twitter.com/notestherkim&quot;&gt;Esther&lt;/a&gt;, Ryan, and &lt;a href=&quot;https://twitter.com/janl&quot;&gt;Jan&lt;/a&gt; for helping me copy-edit my verbal mess 🤣&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fdesigning-even-larger-applications%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Designing%20Even%20Larger%20Applications&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in February, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/february-2020.html"/>
		<updated>2020-02-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/february-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1227628203977605121&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Lazy loading merged into HTML&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1227628203977605121&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1225585408790036480&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1225585408790036480&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1222202681688719360&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Flash device via WebUSB 🤯&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1222202681688719360&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1220051332767174656&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Igalia did this as part of our sponsorship&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1220051332767174656&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1217872856429629441&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Performance assumptions will break&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1217872856429629441&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1217853928454414338&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1217853928454414338&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Ffebruary-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in January, 2020</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/january-2020.html"/>
		<updated>2020-01-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/january-2020.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1217177928762417152&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Edge-ium is launching today&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1217177928762417152&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1217052813081161728&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Chrome is deprecating the UA string&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1217052813081161728&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1217115664277803011&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;…and 3P cookies&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1217115664277803011&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1214255644661841920&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Desktop hover detection leads to click delay in mobile Safari&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1214255644661841920&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjanuary-2020.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in December, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/december-2019.html"/>
		<updated>2019-12-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/december-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1200070712121348096&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;An actual new browser engine&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1200070712121348096&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1202646663124402177&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Debugging FB Browser&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1202646663124402177&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1205484308808568834&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Scroll to fragment&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1205484308808568834&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1204551692018049024&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;ITP as an attack vector&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1204551692018049024&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1207323849861279746&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;V8 8.0&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1207323849861279746&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fdecember-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in November, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/november-2019.html"/>
		<updated>2019-11-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/november-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1196646260633210880&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;API freedom after all?&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1196646260633210880&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1196340839418650625&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;A rare, unexploitable XSS in AMP&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1196340839418650625&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1195759730490257410&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Intent to prototype&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1195759730490257410&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1192842910779228160&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Discover is being discovered&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1192842910779228160&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1191309373999636481&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Speed metrics in Search Console&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1191309373999636481&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fnovember-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in October, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/october-2019.html"/>
		<updated>2019-10-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/october-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1184862415596318721&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Site isolation on Android&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1184862415596318721&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1184155734797275136&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Apparently the answer is: Yes&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1184155734797275136&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1182327105239031808&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1182327105239031808&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1182106545531826182&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Align animations with video frame rate&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1182106545531826182&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1181984304567590913&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Ultimate XSS protection&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1181984304567590913&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1179535701781729285&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Aspect ratio inference outside of AMP!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1179535701781729285&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1177600702861971459&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Preload can now also pre-compile&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1177600702861971459&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Foctober-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in September, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/september-2019.html"/>
		<updated>2019-09-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/september-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1169765794743382016&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Responsive images&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1169765794743382016&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1169295741111566336&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Accelerometer on iOS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1169295741111566336&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1167643829278826497&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Death to smart quotes&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1167643829278826497&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1176151483840192512&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1176151483840192512&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1174775953316294658&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;HTTP3&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1174775953316294658&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1171332094347268096&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Bundled Signed Exchanges&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1171332094347268096&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1170687505542393858&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;How long is this string? 💩&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1170687505542393858&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1170000033728483328&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Reducing SPA pain&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1170000033728483328&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fseptember-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in August, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/august-2019.html"/>
		<updated>2019-08-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/august-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1166723359696130049&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Perf cliffs are real&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1166723359696130049&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1164527986604777472&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Privacy Sandbox in Chrome&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1164527986604777472&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1164245170868641794&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;JS in AMP launched&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1164245170868641794&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1164224746294169600&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1164224746294169600&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1161649929422376960&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;JSON is a valid subset of JS&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1161649929422376960&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1161698090157350912&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Pre-rendering works!&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1161698090157350912&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1160334321648934912&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;WebAuthN is a thing&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1160334321648934912&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1159505273033089024&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;LCP is shipping&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1159505273033089024&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Faugust-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in July, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/july-2019.html"/>
		<updated>2019-07-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/july-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1155920121841500160&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;A better allow-same-origin&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1155920121841500160&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1154421397797527552&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Everything seems to be working&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1154421397797527552&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1152139101325467648&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;SWR is actually here&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1152139101325467648&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1148862362406903808&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;WeakRefs in V8&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1148862362406903808&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjuly-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in June, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/june-2019.html"/>
		<updated>2019-06-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/june-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1136272674622201857&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;iOS13 unbreaks overflowed scrolling&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1136272674622201857&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1135542353169649664&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Federated alternative to npm announced&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1135542353169649664&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1130618854340669440&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1130618854340669440&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1131311528328814592&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;New layout engine in chrome&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1131311528328814592&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1132026447663640576&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;New FCP alternative&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1132026447663640576&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fjune-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in May, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/may-2019.html"/>
		<updated>2019-05-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/may-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1128000887056519169&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Don&amp;#39;t forget the wetsuit&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1128000887056519169&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1126136208235491329&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Portals behind a flag announced at IO&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1126136208235491329&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1125861035389403137&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Cookies in Chrome same-site by default&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1125861035389403137&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1125463332767428608&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;IE11 in Edge&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1125463332767428608&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1120342713843507201&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1120342713843507201&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1118743321558446080&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;No more flash of white&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1118743321558446080&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fmay-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>New on the web platform in April, 2019</title>
		<link href="https://www.industrialempathy.com/new-on-the-web/april-2019.html"/>
		<updated>2019-04-08T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/new-on-the-web/april-2019.html</id>
		<content type="html">
		  
			  
				
		&lt;script src=&quot;https://platform.twitter.com/widgets.js&quot;&gt;&lt;/script&gt;
		
		  &lt;section id=&quot;tweet1108015314971680770&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;I wrote a blog post&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1108015314971680770&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1112648806208888832&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Work we&amp;#39;re funding in WebKit is landing&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1112648806208888832&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1113790188772315141&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;Performance ranking is making a difference&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1113790188772315141&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1114777583302799360&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;OMG, native lazy-loading&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1114777583302799360&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1115215554753781762&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1115215554753781762&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1115525813670227968&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1115525813670227968&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
		  &lt;section id=&quot;tweet1115616909485989889&quot;&gt;
				&lt;hr&gt;
				&lt;h2&gt;#&lt;/h2&gt;
				&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/_____/status/1115616909485989889&quot;&gt;Tweet&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; 
		  &lt;/section&gt;
		
	
			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fnew-on-the-web%2Fapril-2019.html&amp;ul=en-us&amp;de=UTF-8&amp;dt=undefined&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Designing very large (JavaScript) applications</title>
		<link href="https://www.industrialempathy.com/posts/designing-very-large-javascript-applications/"/>
		<updated>2018-04-15T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/designing-very-large-javascript-applications/</id>
		<content type="html">
		  
		    &lt;p&gt;This is a mildly edited transcript of my JSConf Australia talk. &lt;a href=&quot;https://www.youtube.com/watch?v=ZZmUwXEiPm4&quot;&gt;Watch the whole talk on YouTube&lt;/a&gt;. A sequel to this post is available over here.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4024/1*DqvlkOgHSKmp5Tu1eX5mdw.png&quot; alt=&quot;Slide text: Hello, I used to build very large JavaScript applications.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Hello, I used to build very large JavaScript applications. I don’t really do that anymore, so I thought it was a good time to give a bit of a retrospective and share what I learned. Yesterday I was having a beer at the conference party and I was asked: “Hey Malte, what actually gives you the right, the authority, to talk about the topic?” and I suppose answering this is actually on topic for this talk, although I usually find it a bit weird to talk about myself. So, I build this JavaScript framework at Google. It is used by Photos, Sites, Plus, Drive, Play, the search engine, all these sites. Some of them are pretty large, you might have used a few of them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4032/1*v0r4OVf-RXr9ePakdmv5LQ.png&quot; alt=&quot;Slide text: I thought React was good.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This Javascript framework is not open source. The reason it is not open source is that it kind of came out at the same time as React and I was like “Does the world really need another JS framework to choose from?”. Google already has a few of those–Angular and Polymer–and felt like another one would confuse people, so I just thought we’d just keep it to ourselves. But besides not being open source, I think there is a lot to learn from it and it is worth sharing the things we learned along the way.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4032/1*LL3uYYDMT5uIFRxR_7JxPQ.png&quot; alt=&quot;Picture of lots of people.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So, let’s talk about very large applications and the things they have in common. Certainly that there might be a lot of developers. It might be a few dozens or even more–and these are humans with feelings and interpersonal problems and you may have to factor that in.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4032/1*WEH24kaBbar8-1gzN_AO3w.png&quot; alt=&quot;Picture of very old building.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And even if your team is not as big, maybe you’ve been working on the thing for a while, and maybe you’re not even the first person maintaining it, you might not have all the context, there might be stuff that you don’t really understand, there might be other people in your team that don’t understand everything about the application. These are the things we have to think about when we build very large applications.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*fzb42X35lNGmkQHhJLhEBQ.png&quot; alt=&quot;Tweet saying: A team of senior engineers without junior engineers is a team of engineers.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Another thing I wanted to do here is to give this a bit of context in terms of our careers. I think many of us would consider themselves senior engineers. Or we are not quite there yet, but we want to become one. What I think being senior means is that I’d be able to solve almost every problem that somebody might throw at me. I know my tools, I know my domain. And the other important part of that job is that I make the junior engineers eventually be senior engineers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*xpRJ1dXHMlFq1V4oDKU__w.png&quot; alt=&quot;Slide text: Junior -&amp;gt; Senior -&amp;gt; ?&quot; /&gt;&lt;/p&gt;
&lt;p&gt;But what happens is that at some point we may wonder “what might be the next step?”. When we reached that seniority stage, what is the next thing we are going to do? For some of us the answer may be management, but I don’t think that should be the answer for everyone, because not everyone should be a manager, right? Some of us are really great engineers and why shouldn’t we get to do that for the rest of our lives?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/6688/1*wL5wiTWICj1keue9YZOAhQ.png&quot; alt=&quot;Slide text: “I know how I would solve the problem”&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I want to propose a way to level up above that senior level. The way I would talk about myself as a senior engineer is that I’d say “I know how I would solve the problem” and because I know how I would solve it I could also teach someone else to do it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/6696/1*UyLoKH7y54JAYigVlwCJpQ.png&quot; alt=&quot;Slide text: “I know how others would solve the problem”&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And my theory is that the next level is that I can say about myself “I know how &lt;em&gt;others&lt;/em&gt; would solve the problem”.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*zBBGLRIZw94gp54pspvx-g.png&quot; alt=&quot;Slide text: “I can anticipate how API choices and abstractions impact the way other people would solve the problem.”&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Let’s make that a bit more concrete. You make that sentence: “I can anticipate how the API choices that I’m making, or the abstractions that I’m introducing into a project, how they impact how other people would solve a problem.” I think this is a powerful concept that allows me to reason about how the choices I’m making impact an application.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4004/1*LnDv6Ry0Hq2MaQEARaD8rg.png&quot; alt=&quot;Slide text: An application of empathy.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I would call this an application of empathy. You’re thinking with other software engineers and you’re thinking about how what you do and the APIs that you are giving them, how they impact how they write software.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*pnYiZTAfQqsbeS7kVkLe_g.png&quot; alt=&quot;Slide text: Empathy on easy mode.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Luckily this is empathy on easy mode. Empathy is generally hard, and this is still very hard. But at least the people that you are having empathy with, they are also other software engineers. And so while they might be very different from you, they at least have in common that they are building software. This type of empathy is really something you can get quite good at as you gain more experience.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*Op0wLWIqwZ-A5iSuWrqtKA.png&quot; alt=&quot;Slide text: Programming model&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Thinking about these topics there is one really important term that I want to talk about, which is the programming model–a word that I’m going to use a lot. It stands for “given a set of APIs, or of libraries, or of frameworks, or of tools–how do people write software in that context.” And my talk is really about, how subtle changes in APIs and so forth, how they impact the programming model.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4028/1*zuLA-tH9b8k4i1yfKMScmA.png&quot; alt=&quot;Slide text: Programming model impact examples: React, Preact, Redux, Date picker from npm, npm&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I want to give a few examples of things that impact the programming model: Let’s say you have an Angular project and you say “I’m going to port this to React” that is obviously going to change how people write software, right? But then you’re like “Ah, 60KB for a bit of virtual DOM munging, let’s switch to Preact”–that is an API compatible library, it is not going to change how people write software, just because you make that choice. Maybe then you’re like “this is all really complex, I should have something orchestrating how my application works, I’m going to introduce Redux.”–that is going to change how people write software. You then get this requirement “we need a date picker” and you go to npm, there are 500 results, you pick one. Does it really matter which one you pick? It definitely won’t change how you write software. But having npm at your fingertips, this vast collection of modules, having that around absolutely changes how you write software. Of course, these are just a few examples of things that might or might impact how people write software.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*KfcGnWC3WcwBqGYLPiybgw.png&quot; alt=&quot;Slide text: Code splitting&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now I want to talk about one aspect that all large JavaScript applications have in common, when you deliver them to users: Which is that they eventually get so big that you don’t want to deliver them all at once. And for this we’ve all introduced this technique called code splitting. What code splitting means is that you define a set of bundles for your application. So, you’re saying “Some users only use this part of my app, some users use another part”, and so you put together bundles that only get downloaded when the part of an application that a user is actually dealing with is executed. This is something all of us can do. Like many things it was invented by the closure compiler–at least in the JavaScript world. But I think the most popular way of doing code splitting is with webpack. And if you are using RollupJS, which is super awesome, they just recently added support for it as well. Definitely something y’all should do, but there are some things to think about when you introduce this to an application, because it does have impact on the programming model.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4028/1*vAR8HCbwiwX8bVa0xIsk6g.png&quot; alt=&quot;Slide text: Sync -&amp;gt; Async&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You have things that used to be sync that now become async. Without code splitting your application is nice and simple. There is this one big thing. It starts up, and then it is stable, you can reason about it, you don’t have to wait for stuff. With code splitting, you might sometimes say “Oh, I need that bundle”, so you now need to go to the network, and you have to factor in that this can happen, and so the applications becomes more complex.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*DqT7As1rm_M9cxyW1RIW6w.png&quot; alt=&quot;Slide text: Human&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Also, we have humans entering the field, because code splitting requires you to define bundles, and it requires you to think about when to load them, so these humans, engineers on your team, they now have to make decisions what is going into which bundle and when to load that bundle. Every time you have a human involved, that clearly impacts the programming model, because they have to think about such things.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4028/1*0jNa8A5ciY6pCJCN65vLiA.png&quot; alt=&quot;Slide text: Route based code splitting&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There is one very established way that solves this problem, that gets the human out of the mess when doing code splitting, which is called route based code splitting. If you’re not using code splitting yet, that is probably how you should do it as a first cut. Routes are the baseline URL structure of your application. You might, for example, have your product pages on &lt;code&gt;/product/&lt;/code&gt; and you might have your category pages somewhere else. You just make each route one bundle, and your router in your application now understands there is code splitting. And whenever the user goes to a route, the router loads the associated bundle, and then within that route you can forget about code splitting existing. Now you are back to the programming model that is almost the same as having a big bundle for everything. It is a really nice way to do this, and definitely a good first step.&lt;/p&gt;
&lt;p&gt;But the title of this talk is designing &lt;strong&gt;VERY&lt;/strong&gt; large JavaScript applications, and they quickly become so big that a single bundle per route might not be feasible anymore, because the routes themselves become very big. I actually have a good example for an application that is big enough.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*ox94bGuhxWXE-OubL7St6w.png&quot; alt=&quot;Google Search query screenshot for “public speaking 101”&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I was figuring out how to become a public speaker coming up to this talk, and I get this nice list of blue links. You could totally envision that this page fits well into a single route bundle.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4028/1*P-XiIPnuzq9_KLA1nG-uRA.png&quot; alt=&quot;Google Search query screenshot for “weath”&quot; /&gt;&lt;/p&gt;
&lt;p&gt;But then I was wondering about the weather because California had a rough winter, and suddenly there was this completely different module. So, this seemingly simple route is more complicated than we thought.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*Y7e5LoeBggY01aRkJAiwWA.png&quot; alt=&quot;Google Search query screenshot for “20 usd to aud”&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And then I was invited to this conference, and was checking out how much 1 US dollar is in Australian dollars, and there is this complex currency converter. Obviously there is about 1000s more of these specialized modules, and it infeasible to put them all in one bundle, because that bundle would be a few megabytes in size, and users would become really unhappy.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4024/1*qZhd4a0S-CCB5mUiN3fo5Q.png&quot; alt=&quot;Slide text: Lazy load at component level?&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So, we can’t just use route based code splitting, we have to come up with a different way of doing it. Route based code splitting was nice, because you split your app at the coarsest level, and everything further down could ignore it. Since I like simple things, how about doing super fine-grained instead of super coarse-grained splitting. Let’s think about what would happen if we lazy loaded every single component of our website. That seems really nice from an efficiency point of view when you only think about bandwidth. It might be super bad from other point of views like latency, but it is certainly worth a consideration.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*Lr2hIk4eH9uU33e77zeSmA.png&quot; alt=&quot;Slide text: React component statically depend on their children.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;But let’s imagine, for example, your application uses React. And in React components statically depend on their children. That means if you stop doing that because you are lazy loading your children, then it changes your programming model, and things stop being so nice.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*SWkk2vyn344qCNCPSIkXPA.png&quot; alt=&quot;ES6 import example.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Let’s say you have a currency converter component that you want to put on your search page, you import it, right? That is the normal way of doing it in ES6 modules.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*RxlHaYEav0OaODKYKiUubw.png&quot; alt=&quot;Loadable component example.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;But if you want to lazy load it, you get code like this where you use dynamic import, which is a new fancy thing to lazy load ES6 modules and you wrap it in a loadable component. There are certainly 500 million ways to do this, and I am not a React expert, but all of these will change how you write the application.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*N5AMAbobPjsO_lXCPt9-ZA.png&quot; alt=&quot;Slide text: Static -&amp;gt; Dynanic&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And things aren’t as nice anymore–something that was static, now becomes dynamic, which is another red flag for the programming model changing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*j9OB_yjli59MZMyIs9V0_A.png&quot; alt=&quot;Slide text: Who decides what to lazy load when?&quot; /&gt;&lt;em&gt;Slide text: Who decides what to lazy load when?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You have to suddenly wonder: “Who decides what to lazy load when” because that is going to impact the latency of your application.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*rsJ-C7ph0BrJiwTjHKv6_w.png&quot; alt=&quot;Slide text: Static or dynamic?&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The human is there again and they have to think about “there is static import, there is dynamic import, when do I use which?”. Getting this wrong is really bad because one static import, when it should have been dynamic suddenly may put stuff into the same bundle that shouldn’t be. These are the things that are going to go wrong when you have a lot of engineers over long periods of time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*QGoX4bYhEAuNjuKwQhQ0hg.png&quot; alt=&quot;Slide text: Split logic and rendering&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now I’m going to talk about how Google actually does this and what is one way to get a good programming model, while also achieving good performance. What we do is we take our components and we split them by rendering logic, and by application logic, like what happens when you press a button on that currency converter.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*vMskVnAwJgkZmvl4E-8E4Q.png&quot; alt=&quot;Slide text: Only load logic if it was rendered.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So, now we have two separate things, and we only ever load the application logic for a component when we previously rendered it. This turns out to be a very simple model, because you can simply server side render a page, and then whatever was actually rendered, triggers downloading the associated application bundles. This puts the human out of the system, as loading is triggered automatically by rendering.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4024/1*Doqt-GOkUp13Qgk5r7WR1g.png&quot; alt=&quot;Slide text: Currency converter on search result page.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This model may seem nice, but it does have some tradeoffs. If you know how server side rendering typically works in frameworks like React or Vue.js, what they do is a process called hydration. The way hydration works, is you server side render something, and then on the client you render it again, which means you have to load the code to render something that is already on the page, which is incredibly wasteful both in terms of loading the code and in terms of executing it. It is a bunch of wasted bandwidth, it is a bunch of wasted CPU–but it is really nice, because you get to ignore on the client side that you server side rendered something. The method we use at Google is not like that. So, if you design this very large application, you have think about: Do I take that super fast method that is more complicated, or do I go with hydration which is less efficient, but such a nice programming model? You will have to make this decision.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*uteTbmuKZF1wGvoysgsBYw.png&quot; alt=&quot;Slide text: 2017 Happy New Year&quot; /&gt;&lt;/p&gt;
&lt;p&gt;My next topic is my favorite problem in computer science–which is not naming things, although I probably gave this a bad name. It is the &lt;em&gt;“2017 holiday special problem”&lt;/em&gt;. Who here has ever written some code, and now it is no longer needed but it is still in your codebase? … This happens, and I think CSS is particularly famous for it. You have this one big CSS file. There is this selector in there. Who really knows whether that still matches anything in your app? So, you end up just keeping it there. I think the CSS community is at the forefront of a revolution, because they realized this is a problem, and they created solutions like CSS-in-JS. With that you have a single file component, the 2017HolidaySpecialComponent, and you can say “it is not 2017 anymore” and you can delete the whole component and everything is gone in one swoop. That makes it very easy to delete code. I think this is a very big idea, and it should be applied to more than just CSS.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4000/1*rkAN_sLohIO63JCOTZ1JgA.png&quot; alt=&quot;Slide text: Avoid central configuration at all cost&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I want to give a few examples of this general idea that you want to avoid central configuration of your application at all cost, because central configuration, like having a central CSS file, makes it very hard to delete code.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/6696/1*-OoPTo-xaxFr2YOGGFnapw.png&quot; alt=&quot;Slide text: routes.js&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I was talking before about routes in your application. Many applications would have a file like “routes.js” that has all your routes, and then those routes map themselves to some root component. That is an example of central configuration, something you do not want in a large application. Because with this some engineer says “Do I still need that root component? I need to update that other file, that is owned by some other team. Not sure I’m allowed to change it. Maybe I’ll do it tomorrow”. With that these files becomes addition-only.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/6704/1*NsqgsGwmgEcy_PedNzmnbQ.png&quot; alt=&quot;Slide text: webpack.config.js&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Another example of this anti-pattern is the webpack.config.js file, where you have this one thing that is assumed to build your entire application. That might go fine for a while, but eventually needing to know about every aspect of what some other team did somewhere in the app just doesn’t scale. Once again, we need a pattern to emerge how to decentralize the configuration of our build process.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/6696/1*L7ZmdS2JvqwWJySz-X50xw.png&quot; alt=&quot;Slide text: package.json&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here is a good example: package.json, which is used by npm. Every package says “I have these dependencies, this is how you run me, this is how you build me”. Obviously there can’t be one giant configuration file for all of npm. That just wouldn’t work with hundreds of thousands of files. It would definitely get you a lot of merge conflicts in git. Sure, npm is very big, but I’d argue that many of our applications get big enough that we have to worry about the same kind of problems and have to adopt the same kind of patterns. I don’t have all the solutions, but I think that the idea that CSS-in-JS brought to the table is going to come to other aspects of our applications.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*E_g_WgMXGuJtyG-F4AGTNg.png&quot; alt=&quot;Slide text: Dependency trees&quot; /&gt;&lt;/p&gt;
&lt;p&gt;More abstractly I would describe this idea that we take responsibility for how our application is designed in the abstract, how it is organized, as &lt;em&gt;taking responsibility of shaping the dependency tree of our application&lt;/em&gt;. When I say “dependency” I mean that very abstractly. It could be module dependencies, it could be data dependencies, service dependencies, there are many different kinds.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*DfOMmyxC4guVZkyQ4IlF7g.png&quot; alt=&quot;Slide text: Example dependency tree with router and 3 root components.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Obviously, we all have super complicated applications, but I’m going to use a very simple example. It has only 4 components. It has a router that knows how to go from one route of your application to the next, and it has a few root components, A, B, and C.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*CivPR-20NP0dXlIkWfBk6w.png&quot; alt=&quot;Slide text: The central import problem.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As I mentioned before this has the central import problem.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*Y9AgFj90bpFsKq6e7o7Jbw.png&quot; alt=&quot;Slide text: Example dependency tree with router and 3 root components. Router imports root components.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Because the router now has to import all the root components, and if you want to delete one of them you have to go to the router, you have to delete the import, you have to delete the route, and eventually you have the holiday special 2017 problem.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/6696/1*isSwE9e1XLiEw9sbZHwmQQ.png&quot; alt=&quot;Slide text: Import -&amp;gt; Enhance&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We at Google have come up with a solution for this, that I want to introduce to you, which I don’t think we have ever talked about. We invented a new concept. It is called enhance. It is something you use instead of import.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/6672/1*7yPG-uXeixsnQk3k-X9UXw.png&quot; alt=&quot;Slide text: Import -&amp;gt; Enhance&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In fact, it is the opposite of import. It is a reverse dependency. If you enhance a module, you make that module have a dependency on you.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*bDH4yzG0mrrYlrs2C9twsA.png&quot; alt=&quot;Slide text: Example dependency tree with router and 3 root components. Root components enhance router.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Looking at the dependency graph, what happens it that there are still the same components, but the arrows point in the opposite direction. So, instead of the router importing the root component, the root components announce themselves using enhance to the router. This means I can get rid of a root component by just deleting the file. Because it is no longer enhancing the router, that is the only operation you have to do to delete the component.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*HDW95QuGKQCsXqwXiUtB5g.png&quot; alt=&quot;Slide text: Who decides when to use enhance?&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That is really nice, if it wasn’t for the humans again. They now have to think about “Do I import something, or do I use enhance? Which one do I use under which circumstances?”.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4024/1*Hr47VQZYSKiBuDap2XgbbQ.png&quot; alt=&quot;Image: Danger. Hazardous chemicals.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This is particular bad case of this problem, because the power of enhancing a module, of being able to make everything else in the system have a dependency on you is very powerful and very dangerous if gotten wrong. It is easy to imagine that this might lead to really bad situations. So, at Google we decided it is a nice idea, but we make it illegal, nobody gets to use it–with one exception: generated code. It is a really good fit for generated code actually, and it solves some of the inherent problems of generated code. With generated code you sometimes have to import files you can’t even see, have to guess their names. If, however, the generated file is just there in the shadows and enhances whatever it needs, then you don’t have these problems. You never have to know about these files at all. They just magically enhance the central registry.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*od_6cmgitlBJk1g9QxU7Ng.png&quot; alt=&quot;Slide text: Single file component pointing to its parts that enhance a router.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Let’s take a look at a concrete example. We have our single file component here. We run a code generator on it and we extract this little route definition file from it. And that route file just says “Hey Router, here I am, please import me”. And obviously you can use this pattern for all kinds of other things. Maybe you are using GraphQL and your router should know about your data dependency, then you can just use the same pattern.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*Tg_CvUNzT9K0tbzIVC79kw.png&quot; alt=&quot;Slide text: The base bundle&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately this is not all we need to know. There is my second favorite problem in computer science which I call the “&lt;em&gt;Base bundle pile of trash”&lt;/em&gt;. The base bundle in your graph of bundles in your application is the one bundle that will always get loaded–independent of how the user interacts with the application. So, it is particularly important, because if it is big, then everything further down will also be big. If it small, then dependent bundles at least have a chance of being small as well. A little anecdote: At some point I joined the Google Plus JavaScript infrastructure team, and I found out that their base bundle had 800KB of JavaScript. So, my warning to you is: If you want to be more successful than Google Plus, don’t have 800KB of JS in your base bundle. Unfortunately it is very easy to get to such a bad state.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4024/1*wW_u72nFdPiKjEINH4ubDg.png&quot; alt=&quot;Slide text: Base bundle pointing to 3 different dependencies.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here is an example. Your base bundle needs to depend on the routes, because when you go from A to B, you need to already know the route for B, so it has to always be around. But what you really don’t want in the base bundle is any form of UI code, because depending on how a user enters your app, there might be different UI. So, for example the date picker should absolutely not be in your base bundle, and neither should the checkout flow. But how do we prevent that? Unfortunately imports are very fragile. You might innocently import that cool &lt;em&gt;util&lt;/em&gt; package, because it has a function to make random numbers. And now somebody says “I need a utility for self driving cars” and suddenly you import the machine learning algorithms for self driving cars into your base bundle. Things like that can happen very easily since imports are transitive, and so things tend to pile up over time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4008/1*myk-tffGyQx74OIZT4n0mw.png&quot; alt=&quot;Slide text: Forbidden dependency tests.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The solution we found for this are &lt;em&gt;forbidden dependency tests&lt;/em&gt;. Forbidden dependency tests are a way to assert that for example your base bundle does not depend on any UI.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*vDtioYTfzhCB9e7jc9A4pg.png&quot; alt=&quot;Slide text: Assert that base bundle does not depend on React.Component&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Let’s take a look at a concrete example. In React every component needs to inherit from React.Component. So , if your goal is that no UI could ever be in the base bundle just add this one test that asserts that React.Component is not a transitive dependency of your base bundle.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*s5rDafWJi90dcrlEQSAepg.png&quot; alt=&quot;Forbidden dependencies crossed out.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Looking at the previous example again, you just get a test failure when someone wants to add the date picker. And these test failures are typically very easy to fix right then, because usually that person didn’t really mean to add the dependency–it just crept in through some transitive path. Compare this to when this dependency would have been around for 2 years because you didn’t have a test. In those cases it is typically extremely hard to refactor your code to get rid of the dependency.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*ONmcxDRRdY9DpR8QfwMj4g.png&quot; alt=&quot;Slide text: The most natural path&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Ideally though, you find that most natural path.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*7XRIRO-_Y165Gn7Zff_fKQ.png&quot; alt=&quot;Slide text: Most straightforward way must be the right way.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You want to get to a state where whatever the engineers on your team do, the most straightforward way is also the right way–so that they don’t get off the path, so that they naturally do the right thing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4024/1*T6E-ExC2HWa0X--OiJ_vAA.png&quot; alt=&quot;Slide text: Otherwise add a test that ensure the right way,&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This might not always be possible. In that case just add a test. But this is not something that many people feel empowered to do. But &lt;strong&gt;please feel empowered to add tests to your application that ensure the major invariants of your infrastructure&lt;/strong&gt;. Tests are not only for testing that your math functions do the right thing. They are also for infrastructure and for the major design features of your application.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4020/1*y3COuLXS8b1vAQQESjp30Q.png&quot; alt=&quot;Slide text: Avoid human judgement outside of application domain.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Try to avoid human judgement whenever possible outside of the application domain. When working on an application we have to understand the business, but not every engineer in your organization can and will understand how code splitting works. And they don’t need to do that. Try to introduce these thing into your application in a way that is fine when not everybody understands them and keeps the complexity in their heads.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4008/1*CqeGbdnSFMRPtZWPIRZCvw.png&quot; alt=&quot;Slide text: Make it easy to delete code.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And really just make it easy to delete code. My talk is called “building very large JavaScript applications”. The best advice I can give: Don’t let your applications get very large. The best way to not get there is to delete stuff before it is too late.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4012/1*Mt_beSIamHND0E6NjBBetA.png&quot; alt=&quot;Slide text: No abstraction is better than the wrong abstraction.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I want to address just one more point, which is that people sometimes say that having no abstractions at all is better than having the wrong abstractions. What this really means is that the cost of the wrong abstraction is very high, so be careful. I think this is sometimes misinterpreted. It does not mean that you should have no abstractions. It just means you have to be very careful.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;we-have-to-become-good-at-finding-the-right-abstractions.&quot;&gt;W&lt;em&gt;e have to become good at finding the right abstractions&lt;/em&gt;. &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/designing-very-large-javascript-applications/#we-have-to-become-good-at-finding-the-right-abstractions.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4016/1*oNXlH0ththqRlPeRm2z0Sw.png&quot; alt=&quot;Slide text: Empathy and experience -&amp;gt; Right abstractions.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As I was saying at the start of the presentation: The way to get there is to use empathy and think with your engineers on your team about how they will use your APIs and how they will use your abstractions. Experience is how you flesh out that empathy over time. Put together, empathy and experience is what enables you to choose the right abstractions for your application&lt;/p&gt;
&lt;p&gt;If you found this interesting, consider reading my article on &lt;a href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/&quot;&gt;design documents&lt;/a&gt; or the &lt;a href=&quot;https://www.industrialempathy.com/posts/designing-even-larger-applications/&quot;&gt;sequel to this post “Designing Even Larger Applications”&lt;/a&gt;.&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fdesigning-very-large-javascript-applications%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Designing%20very%20large%20(JavaScript)%20applications&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Developer Experience VS User Experience?</title>
		<link href="https://www.industrialempathy.com/posts/developer-experience-and-user-experience/"/>
		<updated>2017-01-03T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/developer-experience-and-user-experience/</id>
		<content type="html">
		  
		    &lt;p&gt;A few days ago Jake Archibald &lt;a href=&quot;https://twitter.com/jaffathecake/status/814751108975489024&quot;&gt;ruffled some feathers&lt;/a&gt; with this observation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It seems the web community has decided that developer experience dwarfs user experience, and I&#39;m not sure what to do about that…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This strongly reminded me of the first and most important item in AMP&#39;s &lt;a href=&quot;https://github.com/ampproject/amphtml/blob/main/docs/design-principles.md&quot;&gt;design principles&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;h2 id=&quot;user-experience-%3E-developer-experience-%3E-ease-of-implementation&quot;&gt;User Experience &amp;gt; Developer Experience &amp;gt; Ease of Implementation &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/developer-experience-and-user-experience/#user-experience-%3E-developer-experience-%3E-ease-of-implementation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, given that my project is setting very similar guidelines compared to what Jake implied in his tweet, I thought it’d be useful to explain the thinking behind it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When creating systems for user facing software, then user experience is more important than developer experience.&lt;/strong&gt; We add a third item: “Ease of implementation” is less important then developer experience. The &lt;em&gt;implementation&lt;/em&gt; here refers to the creator of the underlying system and framework. The idea is that the framework creator should always strive to optimize developer experience, even if they have to work harder for it.&lt;/p&gt;
&lt;p&gt;Of course, there is &lt;strong&gt;a lot of nuance&lt;/strong&gt; to the statement that user experience is more important than developer experience. The most important nuance is that &lt;strong&gt;in many, many cases they do not stand in conflict at all&lt;/strong&gt;. Furthermore, in a large number of cases improving developer experience is the best way to improve user experience, so rather than being in conflict these goals are often in congruence. My favorite example is to improve developer experience by speeding up the iteration cycle (e.g. by improving build time or providing hot reloading): This is great for developers and it allows them to spend more time improving UX in any given day, thus leading to better results.&lt;/p&gt;
&lt;p&gt;Similarly, there are many cases where improved developer experience might just enable a piece of software being build in the first place. The UX might not be perfect, but at least the thing exists. That should typically be a net win :)&lt;/p&gt;
&lt;p&gt;Having said all this, there are trade offs where improved developer experience, just leads to bad UX. My favorite example is&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;img src=”./image.jpg”&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;which has much better developer experience, than&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;img src=”./image.jpg” width=400 height=300&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The first image tag is missing the dimensions. (Ignoring the complexities of responsive sizing that do not impact the point) This is great for the developer. They literally do not need to write the piece of software that determines the dimensions, which saves a little bit of time. Now what happens is that the browser will assume: “Ah, no dimensions, the image is probably 0 pixels big”. Then it will download the image and realize “Ah, it is actually 400x300, lets redraw the page”. This creates a lot of jank for the user every single time a page is looked at.&lt;/p&gt;
&lt;p&gt;A system that favors user experience over developer experience would always make sure that the image dimensions are known when the page is downloaded. Now, of course, one could improve developer experience again, by somehow making it very easy (or automatic) to provide the image dimensions. Another case, where one can have the best of both worlds, but getting good UX does require going the extra mile during framework development.&lt;/p&gt;
&lt;p&gt;Server side rendering, lazy loading of JavaScript bundles and splitting up CSS files are all optimizations of user experience that do incur a cost on developers. Again, a given framework can chose to make them as automatic as possible, but such abstractions tend to be at least a little bit leaky and add visible complexity.&lt;/p&gt;
&lt;p&gt;My post about &lt;a href=&quot;https://medium.com/google-developers/tradeoffs-in-server-side-and-client-side-rendering-14dad8d4ff8b#.52um3u2br&quot;&gt;tradeoffs in server and client side rendering&lt;/a&gt; tries to dive into that topic in particular. The React style hydration of a server side render right upon initial load is a user experience and developer experience trade off: It is better than not doing server side rendering at all, but it is strictly worse than lazily initializing the JS on the client (because it does an initial eager diff and installs event handlers). User experience may not be ideal, but going the extra mile may not be worth it or delay shipment indefinitely for a large class of applications (maybe that class includes everything except &lt;a href=&quot;http://google.com/&quot;&gt;google.com&lt;/a&gt;, &lt;a href=&quot;http://twitter.com/&quot;&gt;twitter.com&lt;/a&gt;, and &lt;a href=&quot;http://facebook.com/&quot;&gt;facebook.com&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Having said all this, the premise that user experience is more important than developer experience is still an important thing to keep in mind as a framework developer. We always need to ask ourselves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;What is the right thing to do for user experience?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can I provide the best possible DX given my UX goals?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What is the smallest possible UX tradeoff given my DX goals?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can I make tradeoffs that improve &lt;strong&gt;DX while sacrificing UX, but only in development mode?&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can I &lt;strong&gt;document things for developers&lt;/strong&gt;, so they can make informed tradeoffs between UX and DX?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fdeveloper-experience-and-user-experience%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Developer%20Experience%20VS%20User%20Experience%3F&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Design docs - A design doc</title>
		<link href="https://www.industrialempathy.com/posts/design-doc-a-design-doc/"/>
		<updated>2015-05-20T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/design-doc-a-design-doc/</id>
		<content type="html">
		  
		    &lt;p&gt;Design docs are a fundamental tool for communicating software design decisions–but communicating things is hard and so is writing design docs. Time for an overly detailed exploration into what would happen if one wrote a design doc for design docs.&lt;/p&gt;
&lt;p&gt;May 19th, 2015&lt;br /&gt;
Status: Draft&lt;br /&gt;
Authors: Malte Ubl&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: While this post continues to be independently useful, I have published a more approachable write-up about Google&#39;s use of design docs in &lt;a href=&quot;https://www.industrialempathy.com/posts/design-docs-at-google/&quot;&gt;Design Docs at Google&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context-and-scope&quot;&gt;Context and scope &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#context-and-scope&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Software_design&quot;&gt;Software design&lt;/a&gt; is an important element of software engineering in which, after we established the requirements of the product or system we are building, we make plans and decisions how to best implement those requirements in software.&lt;/p&gt;
&lt;p&gt;This document describes how a design document is used to facilitate the process of coming to an agreement on a software design and to document it for current and future implementers, maintainers and other stakeholders of the software.&lt;/p&gt;
&lt;h3 id=&quot;goals&quot;&gt;Goals &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#goals&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Document the software design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clarify the problem being solved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Act as discussion platform to further refine the design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Explain the reasoning behind those decisions and tradeoffs made in that decision.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;List alternative designs and why they were not chosen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Support future maintainers and other interested parties in understanding why the original design was chosen.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;non-goals&quot;&gt;Non-goals &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#non-goals&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Establish non-technical requirements of the software.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be independently understandable by a person with no background in the software (but links should guide to documentation that covers missing parts).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Act as user documentation for the product or system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Suitable to document non-software-designs such as the design of a design doc.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#overview&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Our core design idea is that we use a document to informally describe the software design. This extra step before the implementation is chosen, because it has proven inefficient to evolve early software design in terms of fully working implementations. For similar reasons maintainers who try to understand an existing software system often struggle to understand the fundamental design decisions just by looking at the source code.&lt;/p&gt;
&lt;p&gt;The design doc starts with explaining the objective of the software design, how it fits into the wider landscape and why the problem at hand was sufficiently complex to warrant a design document. Explicitly listing goals and non-goals is done to encourage thinking about them.&lt;/p&gt;
&lt;p&gt;The document then continues with a short overview of the design without describing all the details. This overview is followed by the detailed design section that contains the bulk of the content describing why the design was chosen and what the software design is.&lt;/p&gt;
&lt;p&gt;Several sections on cross cutting concerns such as privacy and security directly address how the design relates to them.&lt;/p&gt;
&lt;p&gt;We finish by quickly describing what alternatives were considered and why they were not chosen.&lt;/p&gt;
&lt;p&gt;Design documents are designed to be an efficient design documentation and discussion platform. As such the writer may take great liberties in the actual content and form to best express the design.&lt;/p&gt;
&lt;h2 id=&quot;detailed-design&quot;&gt;Detailed design &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#detailed-design&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The process of designing software should ideally have the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Draws on the experience of experts of the topic matter from within and around the team.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is flexible to changing requirements of the software.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Produces a guideline for the initial implementation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Produces accurate documentation of the software design behind the actually implemented software.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Produces a design that is implementable within the given constraints such as time and resources.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Quickly establishes that a chosen design is viable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Quickly establishes that a chosen design is not viable and then produces a viable design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reduces the risk that a design is not viable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Produces simple designs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If applicable comes to the conclusion that an existing solution exists and no design is necessary.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While some of the requirements in this (incomplete) list may seem redundant, some cannot be achieved at the same time.&lt;/p&gt;
&lt;p&gt;The most direct way to show whether a system can be implemented is to implement it, but that may take too long to quickly establish what the right design is and requirements may have changed by the time the viability of the design under the old requirements was proven.&lt;/p&gt;
&lt;p&gt;In this trade-off-space the design doc plays a vital role by being easy to collaborate on and informal, yet relatively exhaustive and updateable over time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;By using modern collaborative software, such as Google Docs, experts from the team and beyond can collaborate on the final document.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Being informal allows the content and form to be tailored to the design issue at hand making it an efficient way to document designs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The same informality reduces the “cost of change”.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The software design toolbox contains things such as “the proof of concept”, “the micro benchmark” and “the white board discussion”. While it is beyond the scope of this design doc to explain all of them they should be considered as part of the software design process. E.g. pointing to a proof of concept can be a great way in a design doc to establish the viability of the design.&lt;/p&gt;
&lt;h3 id=&quot;relationship-to-other-systems&quot;&gt;Relationship to other systems &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#relationship-to-other-systems&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2524/1*XtqDpOUvryaVCnzI4l7Qmw.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The design doc is written as part of the development of the software design. It gets informed and refined through other elements of software design such as whiteboard sessions and design reviews.&lt;/p&gt;
&lt;p&gt;Software design is primarily driven by the project requirements and if applicable by the user interface design. The requirements, independent of how they are expressed, define what a piece of software should do while the design establishes how that is achieved and why that design was chosen. The design then informs the implementation and the implementation feeds back into the design (through updates of the design when it confronts with reality).&lt;/p&gt;
&lt;h3 id=&quot;structure&quot;&gt;Structure &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#structure&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2416/1*WXJkFVzgjuuQRriPSBaSEw.png&quot; alt=&quot;Meta information &amp;gt; Context, scope &amp;amp; goals &amp;gt; Overview &amp;gt; Detailed design &amp;gt; Cross cutting concerns &amp;gt; Alternatives&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The structure of a design doc is chosen, so that a reader can efficiently and effectively dive into the subject matter. The document starts out relatively high level and then dives deeper into the details of the design.&lt;/p&gt;
&lt;p&gt;This “funnel” is chosen so readers&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;can quickly evaluate the context, scope and goals of the design and get a basic understanding of the design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;and can then choose to read the entire document.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;meta-information&quot;&gt;Meta information &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#meta-information&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Design docs should always have a title and immediately state their authors as primary contacts and a last updated date. Stating the status is helpful for setting expectations for the reader as to the completeness and definiteness of the document. Useful states are:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;enum[ ] DesignDocState { UNKNOWN = 0; INCOHERENT_RAMBLING = 1; DRAFT = 2; FINAL = 3; IMPLEMENTED = 4; OBSOLETE = 5; };&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;(The above code snippet was inserted to illustrate the point further down that copy pasting irrelevant code snippets is not a great idea.)&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;context%2C-scope-%26-goals&quot;&gt;Context, scope &amp;amp; goals &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#context%2C-scope-%26-goals&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The document should first establish the context and scope of the design. This may be done across multiple or a single paragraph. This section should include bullet point lists of “Goals” and “Non-goals” for three reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It is an efficient way for the reader to establish what the design tries to achieve and what it doesn’t want to achieve.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It can be used to evaluate whether the detailed design establishes how those goals are achieved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It forces the authors to actually make decisions about the scope.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2000/1*_HJawJ-Vps3U8u99fBZKMQ.png&quot; alt=&quot;Bart system writing on blackboard: I will not invent a new storage system&quot; /&gt;&lt;/p&gt;
&lt;h4 id=&quot;overview-2&quot;&gt;Overview &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#overview-2&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Next the document gives an overview of the design. This helps readers gain an understanding of the overall approach, which will make it much easier to evaluate how the details relate to the design. It is important to realize that the design doc should not build up tension when being read from start to the end. Quite the opposite, information is given as fast as possible and the structure should aim to avoid putting related information too far apart.&lt;/p&gt;
&lt;h4 id=&quot;detailed-design-2&quot;&gt;Detailed design &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#detailed-design-2&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This section explains the design, its trade offs and consequences as appropriate. The concrete contents are greatly determined by what is being designed and will vary widely between various types of systems, APIs, front ends, etc. The authors are explicitly empowered to choose a form that best fits their design.&lt;br /&gt;
See “Level of detail” below for guidance as to what should determine the contents of the detailed design section.&lt;/p&gt;
&lt;h4 id=&quot;cross-cutting-concerns&quot;&gt;Cross cutting concerns &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#cross-cutting-concerns&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;There may be one or multiple chapters that talk about specific concerns from their specific point of view. While the entire design should have them in mind the dedicated chapters ensure that they are addressed and highlight how the design applies to them. Examples for such concerns are privacy, security, scalability and monitoring.&lt;/p&gt;
&lt;h4 id=&quot;alternatives-considered&quot;&gt;Alternatives considered &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#alternatives-considered&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This section is a fixed part of the document structure as it forces the authors to think about what alternatives would have been available to achieve the goals of the design. Alternatives may be other possible designs or the use of an existing system that does almost what is needed, the purchase of a standard software or to do nothing at all.&lt;/p&gt;
&lt;h3 id=&quot;level-of-detail&quot;&gt;Level of detail &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#level-of-detail&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As stated before a design doc should be an efficient platform for design discussion and documentation. The longer the document gets the harder it becomes to consume and change. The document should thus be as short as possible and as long as necessary.&lt;/p&gt;
&lt;p&gt;No definite guidance can be given when a document is too detailed, but there are some signs when this is the case:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Specification of APIs that are not vital to the design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy pasted source code that is only partially relevant to the design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Raw data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bullet point lists that contain an extra item for no good reason beside meta referentiality.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given the design doc a software engineer who either has existing experience in the subject matter or is willing to invest to get that experience should be able to implement the design doc.&lt;/p&gt;
&lt;p&gt;In a similar manner a “reasonable software engineer” with experience in the subject matter should be able to follow why the design was chosen even if they do not agree with the conclusion.&lt;/p&gt;
&lt;p&gt;The design document itself is not responsible to give any reader independent of their prior experience full context into the subject matter but it should provide links that enable the reader to establish the full context necessary to follow the rest of the doc.&lt;/p&gt;
&lt;h3 id=&quot;lifecycle&quot;&gt;Lifecycle &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#lifecycle&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;document-creation&quot;&gt;Document creation &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#document-creation&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Early in the lifecycle of a design doc major changes are more likely than later in the project when the design is more settled. Early iterations of the document should thus be as lightweight as possible so that changes are quick and the author’s resistance to change it minimized.&lt;/p&gt;
&lt;p&gt;Techniques such as whiteboarding and sketching out chapters with bullet point lists may be employed in early phases of the doc.&lt;/p&gt;
&lt;p&gt;While the document itself is informal, initial setup can be sped up through the use of templates or by the time proven technique of copy pasting the last design doc one has written. The usage of these templates helps ensure a minimum level of coverage and reduces boilerplate.&lt;/p&gt;
&lt;h4 id=&quot;canary-rollout&quot;&gt;Canary rollout &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#canary-rollout&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When the document has stabilized it is advisable to first share it with a small set of canary readers. These will often be peers who participated in early whiteboard sessions and design discussions. By incorporating their feedback into the design doc we ensure that no major questions are unaddressed and ensure general soundness of the design before circulating it with a wider audience.&lt;/p&gt;
&lt;h4 id=&quot;rollout&quot;&gt;Rollout &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#rollout&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;At this time the document is shared with the wider team and other stakeholders. Readers are encouraged to ask questions and make suggestions via inline comments and authors reply. If warranted the document should be updated to address the feedback.&lt;/p&gt;
&lt;p&gt;Eventually the design is declared final. Often this happens informally signaled by the fact that people start implementing the design.&lt;/p&gt;
&lt;h2 id=&quot;security-and-privacy-considerations&quot;&gt;Security and privacy considerations &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#security-and-privacy-considerations&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The design doc has dedicated sections for security and privacy considerations and other such cross cutting concerns if applicable to ensure that they are sufficiently addressed.&lt;/p&gt;
&lt;h2 id=&quot;alternatives-considered-2&quot;&gt;Alternatives considered &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/design-doc-a-design-doc/#alternatives-considered-2&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Meet in front of a whiteboard, draw stuff on it, take a photo.&lt;/strong&gt;&lt;br /&gt;
It is great when this is sufficient to document a design, but often systems are too complex to be expressed through a single whiteboarding session and people who did not themselves take part in the discussion may be missing context.&lt;br /&gt;
Having said that, whiteboarding sessions are a great start to flesh out the major points of a design in a lightweight process before diving in to actually write it down.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Agile Scrum KISS™, just winging it.&lt;/strong&gt;&lt;br /&gt;
Doing the simplest thing that could possibly work is generally a great idea but it stops being fun when that includes a lot of boilerplate or in aggregate becomes so complex that everyone loses track what is going on. If the simplest thing that could work is still complex a design doc may help document that simplest thing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Verbal design review&lt;/strong&gt;&lt;br /&gt;
Design reviews are another way to discuss a design and spread knowledge about it. It can be a great addition to every design doc but is insufficient to serve as long term evolving documentation of a project’s design.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fdesign-doc-a-design-doc%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Design%20docs%20-%20A%20design%20doc&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>The cost of failure</title>
		<link href="https://www.industrialempathy.com/posts/the-cost-of-failure/"/>
		<updated>2015-05-11T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/the-cost-of-failure/</id>
		<content type="html">
		  
		    &lt;p&gt;In UI engineering the path to an excellent product is often not clearly set. Especially if we push the boundaries of hardware across numerous devices experimentation and tweaking are an integral part of polishing the experience. Experimentation is an iterative process, a string of small failures, that eventually leads to the desired result. Minimizing the cost of these failures can materially impact the quality of the final product.&lt;/p&gt;
&lt;p&gt;We know from the &lt;a href=&quot;http://en.wikipedia.org/wiki/The_Mythical_Man-Month&quot;&gt;mythical man month&lt;/a&gt; that adding more engineers to a projects doesn’t necessarily increase output and every project will want to eventually ship. This is 2015 so we ship MVPs, but we still have to ship them at some point.&lt;/p&gt;
&lt;p&gt;My thesis is that quality/excellence/fidelity of that final product given time and resource constraints is a function of the number of iterations the team was able to make within the available time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;within-those-constraints-the-remaining-way-to-improve-product-excellence-is-to-increase-the-iteration-speed.&quot;&gt;Within those constraints the remaining way to improve product excellence is to increase the iteration speed. &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/the-cost-of-failure/#within-those-constraints-the-remaining-way-to-improve-product-excellence-is-to-increase-the-iteration-speed.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lets consider the following example: The product spec calls for an animation where state A of the product morphs into state B. Cool, most talented UI engineers will be able to implement it given enough time. But will it be good? Slight variations in how the animations are performed will dramatically affect how the GPU handles the task, etc. It may need to be tested with various forms of content and one 4–5 different devices. The iteration speed determines how long it takes to tweak the animation and complete each experiment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;engineers-will-typically-spend-a-fixed-amount-of-time-tweaking-a-particular-part-of-the-ui.-if-they-were-able-to-do-more-tweaks-within-that-fixed-time-the-fidelity-will-be-better.&quot;&gt;Engineers will typically spend a fixed amount of time tweaking a particular part of the UI. If they were able to do more tweaks within that fixed time the fidelity will be better. &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/the-cost-of-failure/#engineers-will-typically-spend-a-fixed-amount-of-time-tweaking-a-particular-part-of-the-ui.-if-they-were-able-to-do-more-tweaks-within-that-fixed-time-the-fidelity-will-be-better.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;So what is iteration speed in concrete terms? The length of the cycle of:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Having the idea that a change may improve fidelity.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Implementing that change.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compiling the program.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Deploying it onto the target device.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reinstating the state of the program to where the behavior-under-improvement is exhibited.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Observing/measuring whether the fidelity is improved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Optionally repeat 4–6 on N devices.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Differing development environments exhibit vastly differing times for each elements of the cycle.&lt;/p&gt;
&lt;p&gt;Steps 1, 2 and 6 are the only steps that are necessary. All other steps would ideally take 0 seconds and there are, indeed, systems that do not require these steps at all.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/7800/1*OfniTBae22oCGP5ZrXObrw.jpeg&quot; alt=&quot;Image of a horse carousel https://cdn-images-1.medium.com/max/7800/1*OfniTBae22oCGP5ZrXObrw.jpeg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The get-off-my-lawn old person in me remembers the golden days of the 90s where in VisualWorks SmallTalk one would just stop the UI, unwind to some previous state, change the running program and rerun the relevant part.&lt;/p&gt;
&lt;p&gt;However, it isn’t the 90s and things are much worse. There are web developers who not only have to compile their program for dozens of seconds, they even have to manually invoke that compilation; there are native mobile developers who have to compile and transfer a program to the device and then have to touch their app’s icon to start it and then manually click through their app to get back to the part they were working on. And then they put another device on the USB cable and repeat.&lt;/p&gt;
&lt;p&gt;Lets do some hypothetical calculations:&lt;/p&gt;
&lt;p&gt;Assume it takes about 5 minutes to come up with an idea for an improvement, implement it and measure whether there was an improvement.&lt;/p&gt;
&lt;p&gt;If the overhead (Steps 3, 4 and 5) takes 0 seconds we can make a program better 12 times per hour. What is more important because there are no context switches it is actually feasible to do so and we can take 15 minutes out of the hour for a nice coffee break.&lt;/p&gt;
&lt;p&gt;What happens when compilation, or deployment or state recreation take 2 minutes? In theory we could still do 8 iterations per hour, but now we have those frequent 2 minute breaks. Reddit, HackerNews and Twitter will get in the way. 5 iterations are more realistic under this setting, but things get even worse if testing has to be repeated on multiple devices.&lt;/p&gt;
&lt;p&gt;As a consequence even what may seem to be relatively short breaks can fast cut the number of iterations that can be done on a given product in half. And it just won’t be as good.&lt;/p&gt;
&lt;p&gt;So what can be done to improve iteration speed?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Cut human interaction out of tasks: The system should sense when a task needs to be done, not wait for user invocation.&lt;br /&gt;
Can eliminate or shorten steps 3 &amp;amp; 4.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cut all tasks that do not need to block iteration out of the critical path. Type checking? Its nice, but doesn’t have to block running the program.&lt;br /&gt;
Eliminates step 3.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Invest in hot code replacement.&lt;br /&gt;
Eliminates step 3 &amp;amp; 4 and shortens step 5.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Invest in time traveling debuggers.&lt;br /&gt;
Together with hot code replacement eliminates steps 3, 4 &amp;amp; 5.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fan out hot code replacement: Do just in time hot code replacement on N devices concurrently.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even if a system trades off being able to do these things against a lesser maximum performance (a classic choice between lower and higher level programming constructs. E.g. late binding VS. early binding), the increased fidelity through higher iteration speed will quickly make the net performance better.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;a-productive-stack-wins-over-an-unproductive-stack-even-if-the-unproductive-stack-has-better-theoretical-best-case-performance.&quot;&gt;A productive stack wins over an unproductive stack even if the unproductive stack has better theoretical best case performance. &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/the-cost-of-failure/#a-productive-stack-wins-over-an-unproductive-stack-even-if-the-unproductive-stack-has-better-theoretical-best-case-performance.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;Obviously the above is only true within certain limits, but I feel that we as a software engineering community are underinvested in increasing development productivity. This is the one part of the equation that we can directly influence ourselves by building better tools and we should make it a priority.&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fthe-cost-of-failure%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=The%20cost%20of%20failure&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Anecdotes about frontend and backend engineering</title>
		<link href="https://www.industrialempathy.com/posts/anecdotes-about-frontend-and-backend-engineering/"/>
		<updated>2015-04-06T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/anecdotes-about-frontend-and-backend-engineering/</id>
		<content type="html">
		  
		    &lt;p&gt;This is the story about how I became what some people would call a frontend engineer and an exploration into what that even means.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;i%E2%80%99m-a-frontend-engineer-because-i-was-really-mad-and-really-full-of-myself.&quot;&gt;I’m a frontend engineer because I was really mad and really full of myself. &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/anecdotes-about-frontend-and-backend-engineering/#i%E2%80%99m-a-frontend-engineer-because-i-was-really-mad-and-really-full-of-myself.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was October 2008 and I just joined a new company and was leading a team of 11 or so engineers in a company of roughly 200.&lt;/p&gt;
&lt;p&gt;I was also really excited about this new company but then I discovered the thing that made me really mad:&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;almost-all-the-experienced%2C-senior-and-well-respected-engineers-called-themselves-%E2%80%9Cbackend-developers%E2%80%9D-and-refused-to-do-client-side-work-and-so-the-client-side-was-left-to-the-inexperienced%2C-junior-and-not-as-well-respected-engineers-(with-a-few-exceptions%2C-of-course).&quot;&gt;&lt;em&gt;Almost all the experienced, senior and well-respected engineers called themselves “backend developers” and refused to do client side work and so the client side was left to the inexperienced, junior and not as well-respected engineers (with a few exceptions, of course).&lt;/em&gt; &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/anecdotes-about-frontend-and-backend-engineering/#almost-all-the-experienced%2C-senior-and-well-respected-engineers-called-themselves-%E2%80%9Cbackend-developers%E2%80%9D-and-refused-to-do-client-side-work-and-so-the-client-side-was-left-to-the-inexperienced%2C-junior-and-not-as-well-respected-engineers-(with-a-few-exceptions%2C-of-course).&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;Me being the new manager for the team I decided to do some pair programming with each person on the team to kinda get a feel for what their work was like. When I eventually got to work with the first dev doing client side work I went completely What The Fuck?!?! Their work flow for JS and CSS was to make the changes and then click the deploy button in Eclipse, which would then&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Start up ant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cleanly shutdown tomcat&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Recompile the Java project to include the updated files as a resource&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Startup tomcat&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overall a cool few minutes would pass by only to see a new background color.&lt;/p&gt;
&lt;p&gt;So, I was yelling &lt;em&gt;“What The Fuck?!?&lt;/em&gt;” or probably something more along the lines &lt;em&gt;“How do you put up with this? This is completely unacceptable! We should stop doing anything else and make this better first”.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Luckily it turned out the person responsible for the Java build process was sitting right next to us. He was like: &lt;em&gt;“Wait, go to Eclipse and from the build menu select the ‘Deploy resources’ item. Does the job and only takes 1–2 seconds. I made this because I was annoyed when I needed to make a JS change, but I guess I never really told anyone else.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There were 2 major fails here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The client side dev didn’t go on strike the second they realized there was no reload-to-refresh in the system they were working on.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;While the “backend dev” realized there was a problem, they didn’t actually communicate this to the “frontend dev” sitting literally a chair to the right.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The reality was that those 2 people were sitting on the same desk but they had essentially never talked to each other nor were they aware of each other’s problems.&lt;/p&gt;
&lt;p&gt;This was just one of several similar experiences and so I was really mad: The work product was not good and it seemed so obvious how to fix it. We were building consumer facing ecommerce web apps and I was feeling like we weren’t able to deliver the type of experience that the consumers deserved. While there are definitely cases where backend work leads to hard-to-copy differentiating features, this is not what happens in many areas. Backend systems are often commodities (vast majority of ecommerce sites work this way), and real differentiation is achieved through excellent user experience.&lt;/p&gt;
&lt;p&gt;Now we come to the part where I was full of myself. I was thinking: &lt;em&gt;“While all the senior people do backend work, I’m like the best senior engineer and from now on I am going to be a frontend engineer”.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So, I did a presentation at the next engineering all hands meeting talking about the anecdote above and how that is unacceptable and: &lt;em&gt;“If you want to join the new cool kids, better do work on the client. We need the best of you all doing work closest to our users.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Needless to say that actually worked. While there was certainly larger changes at play at the company that shifted the perception and role of the non-engineering work in UX, etc. as well, the baseline quality of the work product the entire company delivered has risen very significantly since.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;if-your-engineering-organization-does-not-value-and-invest-in-user-facing-engineering-your-product-will-be-replaced-by-one-that-does.&quot;&gt;If your engineering organization does not value and invest in user facing engineering your product will be replaced by one that does. &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/anecdotes-about-frontend-and-backend-engineering/#if-your-engineering-organization-does-not-value-and-invest-in-user-facing-engineering-your-product-will-be-replaced-by-one-that-does.&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;I just made up the term “user facing engineering”; I’m not personally a fan of using the word frontend as a category of engineering. I now work at Google where like 98% of engineers build &lt;a href=&quot;http://en.wikipedia.org/wiki/BigTable&quot;&gt;bigtable&lt;/a&gt; frontends or frontends to those frontends and bigtable itself is basically just a physical storage frontend. The term is relative and thus meaningless without context. The Chrome browser has a backend team: it implements the actual HTML rendering on the client.&lt;/p&gt;
&lt;p&gt;On the other hand “backend engineer” as typically used is also hard to define. In my cynical mind it means: ”spends most of their time with data migrations from the legacy system to the future legacy system.”&lt;/p&gt;
&lt;p&gt;So, should everyone be a &lt;em&gt;“full stack engineer”&lt;/em&gt;? The answer is a clear &lt;strong&gt;No&lt;/strong&gt;. What is important is that skills are equally distributed across disciplines and that communication across engineers on different layers of the stack happens regularly. If you talk to a colleague on a different layer all the time, eventually you will know enough about that layer to be a little more “full stack” and you’ll be able to design systems that impact or span multiple layers of the stack. To me that is one of the most important aspects of “seniority”.&lt;/p&gt;
&lt;p&gt;But you will still be an expert for probably just one of the layers and that is completely fine. Each layer of software engineering is deep enough to spend many many years in perfecting its craft and really hard problems require specialists.&lt;/p&gt;
&lt;p&gt;Coming back to the “frontend” or the “client side” or the “user facing engineering”: As the medium “computer” matures, the discipline of engineering that deals with computer user interfaces has become so “deep” that I would not want to leave it to my least experienced engineers. We need people who are really good at applied matrix math, deeply understand how GPUs and networks work, can design multi-million-lines-of-code systems, understand accessibility requirements and maybe even have a sense for design aesthetics (I so wish I would fall into that latter category). To me all of these seem sufficiently hard and interesting that I dedicated my career to getting better at them and maybe eventually actually be a senior engineer ☺&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Fanecdotes-about-frontend-and-backend-engineering%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Anecdotes%20about%20frontend%20and%20backend%20engineering&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>10x engineer 10% of the time</title>
		<link href="https://www.industrialempathy.com/posts/10x-engineer/"/>
		<updated>2015-02-05T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/10x-engineer/</id>
		<content type="html">
		  
		    &lt;p&gt;I’ve lately been thinking about what patterns could explain perceived differences in individual productivity in software engineering. I’m using the word perceived because productivity is really a complex topic and I can think of few ways how to effectively measure it within the complex social structure of a larger engineering team.&lt;/p&gt;
&lt;p&gt;So, this is the list of things I came up with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;be-really-good-at-debugging&quot;&gt;Be really good at debugging &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/10x-engineer/#be-really-good-at-debugging&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;Programming languages, tools and frameworks come and go, but having a great debugging instinct and skill set will pay back for the rest of one’s career. Debugging can and must be practiced. I personally think that for someone new to software engineering who asks “What should I focus on in my career” debugging should be the #1 answer. It is the one thing that will always be there in our jobs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;never-be-blocked&quot;&gt;Never be blocked &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/10x-engineer/#never-be-blocked&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;Manage your work load and make sure that whenever a given task can not be continued there is something else waiting to be done already.&lt;/p&gt;
&lt;p&gt;During the typical software engineering job there are millions of reasons why one may not be able to proceed working on the current task: waiting on a designer, product manager, another team making a release, etc.. The ability to embrace this situation and switch to a different task while the other is waiting is I think the most hated, stress producing and still helpful skill for using a larger percentage of the time available for actual programming. The key is finding the sweet spot between reduced productivity from task switching and increased productivity from larger utilization. Everyone will have a different sweet spot but I think that professionally embracing the fact that task switches are part of everyday work allows us to get better at it over time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;know-when-to-do-redundant-work-or-build-a-tool&quot;&gt;Know when to do redundant work or build a tool &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/10x-engineer/#know-when-to-do-redundant-work-or-build-a-tool&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;In software engineering we often face the decision whether to automate a piece of work or just do it manually. Some examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Create a scaffolding script or write the boilerplate by hand?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Improve the error message after debugging found what was wrong, so the problem is obvious next time it happens, or let the next person search for it again?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set up hotswapping or restart the server all the time?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Knowing when to do one or the other is in my experience one of the greatest signals of seniority in software engineering.&lt;/p&gt;
&lt;p&gt;In my experience most engineers tend to overestimate the amount of work to build the tool and thus choose to do manual labor when they could have saved hours, days or weeks of engineering time with a tool that takes 8 hours to build. But there is certainly also the other extreme: Automating everything while creating a maintenance burden for tools that almost never run.&lt;/p&gt;
&lt;p&gt;Having good intuition as to what way to go can be learned. I know I was certainly in the “too much manual work” camp, but I learned to correct myself for that, and it seems from hindsight I’ve been able to chose correctly more often.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1 id=&quot;be-really-good-at-reading-code&quot;&gt;Be really good at reading code &lt;a class=&quot;direct-link&quot; href=&quot;https://www.industrialempathy.com/posts/10x-engineer/#be-really-good-at-reading-code&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;/blockquote&gt;
&lt;p&gt;It could be argued that the reading code is more important than writing code; it gives perspective and insights into our fellow engineer’s brilliant minds but the truly most important reason that reading code is so important: documentation is bad and always will be bad. So making oneself independent of docs as much as possible is super important for getting things done. Not enough is being talked about good code reading techniques: I personally always try to empathize with the authors based on the code I’m seeing and try to get a feel for how they write software, so I can more quickly start to make correct assumptions from scanning other code in the same project.&lt;/p&gt;
&lt;p&gt;Programming is often seen as this magical thing where some people are just better than others by talent or whatever; instead it is a craft, a craft that one can get better at. Getting better takes practice and with limited time practice should focus on the most important aspects of the craft. This posts focuses on the workflow side of things — there are obviously many more important fields like coding itself and software design. I’m very interested in feedback and maybe I’ll eventually get to talk about the other topics in another posts.&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2F10x-engineer%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=10x%20engineer%2010%25%20of%20the%20time&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
	
	<entry>
		<title>Tradeoffs in server side and client side rendering</title>
		<link href="https://www.industrialempathy.com/posts/tradeoffs-in-server-side-and-client-side-rendering/"/>
		<updated>2015-01-15T00:00:00Z</updated>
		<id>https://www.industrialempathy.com/posts/tradeoffs-in-server-side-and-client-side-rendering/</id>
		<content type="html">
		  
		    &lt;p&gt;For a long time there has been a debate in web development as to whether web apps and sites should be rendered on the server or the client — or, of course, both.&lt;/p&gt;
&lt;p&gt;With a &lt;a href=&quot;http://www.quirksmode.org/blog/archives/2015/01/angular_and_tem.html&quot;&gt;recent post by PPK&lt;/a&gt; the debate flamed up again and one thing that struck me as particularly unhelpful was the argument that where something is rendered would be automatically determine whether a given framework is (one dimensionally) good or bad. In my opinion such an simplistic view on things hides the real underlying tradeoffs that should drive decisions.&lt;/p&gt;
&lt;p&gt;For some perspective: My day job is building web frameworks for Google. The one I’m designing is from the ground up build to support server side rendering very well (it isn’t open source mostly because I felt Google had enough open source web frameworks already and I didn’t want to make the choice even harder, but I also never want to say never). So, it may seem that I’d be somewhat “partisan” with this respect, but the opposite of true. My framework comes with a disclaimer saying that it is particularly designed for very large consumer-facing web applications. Anything that doesn’t fit that description might still be happy, but there will be tradeoffs made that make their life more difficult than otherwise necessary.&lt;/p&gt;
&lt;p&gt;First I’d like to establish that server side rendering is hard beyond the pure ability to render on the server. Assuming you are building a complex app that wants to render initial responses on the server and then update subsequent state using XHR, there are several challenges that a good server side rendering solution needs to overcome and complexity that is added in any case:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Client side decoration. It is great that you can render a chunk of HTML on the server, but you also need to do things like registering events handlers on the client. Many modern frameworks do that during rendering. One approach is to just immediately after load do a client side render using the same data that was used for server side rendering. React makes this quite nice. But this now means that loading the code that is necessary to make the page interactive includes the code that is necessary for client side rendering (read your templates!) and with that a major benefit of server side rendering is gone.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I would assume that your templating language (or whatever you use to eventually have a DOM) runs equally well on the client and the server. This isn’t everything, of course: You need to duplicate the data fetching logic and other code. Now one could argue that with e.g. Node.js you could reuse the code but in reality the difference in code you write when your database is 10ms away VS. 100–2000+ms is so big that unless you have a very big abstraction layer there will be significant duplication.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Both render paths need to be tested and integration tested.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On a client side render you always know how wide or high the screen is. For very high fidelity sites you at some point will want to make a rendering decision based on something that you cannot express in CSS. There are work arounds for this that still work with server rendering but they will require major discipline by engineers to walk on the thin path of only using information available on the server during rendering even if rendering happens on the client.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For very high fidelity you may need to sometimes fall back from server side rendering to client side rendering: That is because on the client you can retry and give the user some feedback when a backend is temporarily unavailable while on the server you’d need to show an error page.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The approach to render everything on the server, even incremental updates to the page is very dangerous and will be make you unhappy, so you need to plan with being able to server and client side render everything. E.g. Rails TurboLinks and I hear &lt;a href=&quot;http://twitter.com/&quot;&gt;Twitter.com&lt;/a&gt; uses a similar approach where server side rendered pages are incrementally merged into a running web app: This means that your 5 days old JS may need to be able to handle HTML rendered today. This type of forward and backward compatibility will eventually (or rather really soon) go wrong.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I could go on, but the gist is: server side rendering comes at complexity cost because while all of the issues above can be eliminated the solutions will add very significant complexity to your project.&lt;/p&gt;
&lt;p&gt;So why would you do server rendering:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Some people say that search engines still like it better.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Or that it is the right thing to do because web.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You might need to print out some OGP, Twitter Card and &lt;a href=&quot;http://schema.org/&quot;&gt;Schema.org&lt;/a&gt; markup anyway, so some of the extra complexity is not optional.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It is faster. But only sometimes (&lt;a href=&quot;http://www.onebigfluke.com/2015/01/experimentally-verified-why-client-side.html&quot;&gt;Recent data by Brett Slatkin&lt;/a&gt;). Yes, you can do really well with client side rendering but the reality is that due to high latency between web client and server it is extremely hard to keep the critical path so ideal that you have a fighting chance of staying competitive with server rendering. I’m not saying it can’t be done, but I’d argue that with a team of 10 people and a year of frequent feature additions the server rendered app will stay significantly faster than the same app rendered only on the client.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Looking at the benefits of server rendering there are entire classes of apps that don’t benefit from it at all:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Your intranet ERP, HR, Financial, blah software will not want &lt;a href=&quot;http://schema.org/&quot;&gt;Schema.org&lt;/a&gt; markup. In reality most software that is being written falls into this category.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Slightly hipper things like bug tracking, todo management, or whatever every other startup is building really falls in the same category.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Google Inbox renders the list of emails on the server when you first go to it. That is kind of nice compared to how GMail loads, but amortized over an entire day the benefit is really marginal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The more general case is almost all “Information and Business Systems” : If the typical user loads it at most once a day and then uses it for hours, initial load performance will not be the most important thing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;All native apps on your phone and tablet are client side rendered. Seems to be alright.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most obvious class of apps where server side rendering would have major benefits are content publishing sites like the New York Times or, you know, Medium as well as other user generated content sites that rely on referral traffic for perma link pages (Think Instagram, Youtube, Twitter, etc). As one of these the amount of engineering I’d be willing to take on to make my pages just a bit faster, friendlier to BingBot and easier shareable on other social networks may be pretty high. That it may not be high enough can be seen on Instagram which is not server rendered (Update 2016: It is now server rendered using the fastboot pattern. Faster but requires a lot of CPU per page load); I’d not be suprised if that changes in the future, but it seems for them shipping was more important than ultra high fidelity.&lt;/p&gt;
&lt;p&gt;I’m excited that &lt;a href=&quot;http://emberjs.com/blog/2014/12/22/inside-fastboot-the-road-to-server-side-rendering.html&quot;&gt;Ember.js is adding server rendering&lt;/a&gt;. I’m sure they’ll do a great job hiding the complexity, but this decision will still impact their project in the long term:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Some stuff just won’t work on the server. That has to be documented somewhere. People have to read those docs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the above isn’t true, some stuff just will no longer be possible at all.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Future and present features may need to be slightly tweaked to support server rendering thus getting an ever so slightly worse API than would be possible for client rendering only.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the more general case there are dozens of tradeoff spaces in which frameworks can make decisions as to what they want to optimize for. Some frameworks have data binding which is awesome if your app has lots of forms and getting shit done is super important and more important than making UX absolutely perfect— in that case adding each event handler one-by-one may not be cool — on the other hand if your job is to build the Facebook image upload dialog you may have a UX team and 2 engineers twiddling every last aspect for multiple months. These are very different types of software and even though both may be rendered from HTML, I’d use a very different underlying system to build them.&lt;/p&gt;
&lt;p&gt;In conclusion: Server rendering is great, use it where applicable but be conscious about the hit in productivity due to extra complexity and decide whether it makes sense for your app.&lt;/p&gt;

			
			
			
			&lt;img src=&quot;https://www.industrialempathy.com/.netlify/functions/ga?v=1&amp;_v=j83&amp;t=pageview&amp;dr=https%3A%2F%2Frss-feed-reader.com&amp;_s=1&amp;dh=www.industrialempathy.com&amp;dp=%2Fposts%2Ftradeoffs-in-server-side-and-client-side-rendering%2F&amp;ul=en-us&amp;de=UTF-8&amp;dt=Tradeoffs%20in%20server%20side%20and%20client%20side%20rendering&amp;tid=UA-141920860-1&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display:none&quot; alt=&quot;&quot;&gt;
		</content>
	</entry>
</feed>