<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/cdn/</id>
  <link href="https://www.endpointdev.com/blog/tags/cdn/"/>
  <link href="https://www.endpointdev.com/blog/tags/cdn/" rel="self"/>
  <updated>2023-01-20T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>Bypassing a CDN to browse a website directly on your origin host</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/"/>
      <id>https://www.endpointdev.com/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/</id>
      <published>2023-01-20T00:00:00+00:00</published>
      <author>
        <name>Seth Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/winter-mountains.webp&#34; alt=&#34;A pale winter morning, looking out over a valley from a mountainside&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen, 2023 --&gt;
&lt;p&gt;Using a content distribution network (CDN) has many advantages over serving a website directly, and for any reasonably large website, you should use one. Those advantages include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Caching at each of the CDN&amp;rsquo;s PoPs (points of presence).&lt;/li&gt;
&lt;li&gt;Often thousands of PoPs around the world, so traffic will be quick for everyone regardless of how far away they are from your origin server.&lt;/li&gt;
&lt;li&gt;Blocking of some Bad Guys automatically at the edge, including DDoS (distributed denial of service attacks) mitigation help.&lt;/li&gt;
&lt;li&gt;Origin IP address insulation. Hiding the origin IP address is useful to protect against DDoSes, since CDNs are generally well-defended against DDoS and your origin server probably is not as much.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should generally be cautious about revealing your websites&amp;rsquo; origin IP address. We serve other sites from our origin directly, so we don&amp;rsquo;t worry too much about sharing it here.&lt;/p&gt;
&lt;h3 id=&#34;straight-to-the-source&#34;&gt;Straight to the source&lt;/h3&gt;
&lt;p&gt;Sometimes, though, you need to bypass your CDN and test your website directly on its origin server. For example, if you need to test that your website would still work if the CDN goes down, or to sidestep CDN caching or content modification when troubleshooting a problem.&lt;/p&gt;
&lt;p&gt;It can be surprisingly confusing to bypass the CDN by yourself and not for the rest of your visitors, especially with newer features like Secure DNS in Chrome and Firefox muddying up traditional DNS resolution behaviors.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll use a browser extension called IPvFoo (available for Chrome and Firefox) to see which IP address our hostname resolves to. Install IPvFoo from the &lt;a href=&#34;https://chrome.google.com/webstore/detail/ipvfoo/ecanpcehffngcegjmadlcijfolapggal&#34;&gt;Chrome Web Store&lt;/a&gt; or Firefox&amp;rsquo;s &lt;a href=&#34;https://addons.mozilla.org/en-US/firefox/addon/ipvfoo-pmarks/&#34;&gt;addons.mozilla.org&lt;/a&gt; and then click on its indicator next to the search bar.&lt;/p&gt;
&lt;p&gt;Before we change anything, www.endpointdev.com resolves to 104.21.30.147:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/cloudflare.webp&#34; alt=&#34;IPvFoo showing Cloudflare&amp;rsquo;s IP address&#34;&gt;&lt;/p&gt;
&lt;p&gt;After a quick &lt;code&gt;whois&lt;/code&gt; search, we see that this IP address belongs to Cloudflare, our CDN:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ whois 104.21.30.147
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✀
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OrgName:        Cloudflare, Inc.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✀&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also check the certificate issuer by clicking on the padlock icon in our browser&amp;rsquo;s search bar, then clicking on &amp;ldquo;Connection is secure&amp;rdquo; or similar to see all the details about the certificate issuer.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/cert-issuer-chrome-before.webp&#34; alt=&#34;Chrome showing Cloudflare as the certificate-issuing authority, before sidestepping the CDN.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Before we change anything, we see the TLS/SSL certificate presented is issued by Cloudflare, as expected.&lt;/p&gt;
&lt;h3 id=&#34;make-the-hosts-file-point-directly-to-our-server&#34;&gt;Make the hosts file point directly to our server&lt;/h3&gt;
&lt;p&gt;Common desktop and server operating systems typically come with a &amp;ldquo;hosts file&amp;rdquo; that can be used to provide hostname to IP address translation that happens before your designated DNS servers are consulted.&lt;/p&gt;
&lt;p&gt;This is useful to test a hostname without ever adding it to DNS, or to override a DNS entry with your own IP address.&lt;/p&gt;
&lt;p&gt;We want to change our hosts file so that www.endpointdev.com points directly to our site&amp;rsquo;s origin server. How to do this depends on your operating system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux/macOS: Open /etc/hosts as root (using &lt;code&gt;sudo&lt;/code&gt; or &lt;code&gt;su&lt;/code&gt;) in your favorite editor such as vim or nano.&lt;/li&gt;
&lt;li&gt;Windows: Open C:\Windows\System32\drivers\etc\hosts as administrator in a decent plain text editor, not a word processor — I used Notepad++.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you have your hosts file open, add a line to point your domain name directly to your origin server. For www.endpointdev.com:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;23.239.26.161 www.endpointdev.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;disable-dns-over-tls--dns-over-https&#34;&gt;Disable DNS-over-TLS &amp;amp; DNS-over-HTTPS&lt;/h3&gt;
&lt;p&gt;You may also need to disable any &amp;ldquo;secure DNS&amp;rdquo; in your browser, such as DNS-over-TLS or DNS-over-HTTPS.&lt;/p&gt;
&lt;h4 id=&#34;chrome&#34;&gt;Chrome&lt;/h4&gt;
&lt;p&gt;In Chrome, this is called Secure DNS, and you can disable it by going to Settings &amp;gt; Privacy and Security &amp;gt; Security &amp;gt; Use secure DNS, and disabling it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/secure-dns-chrome.webp&#34; alt=&#34;Chrome settings, navigated to Settings &amp;gt; Privacy and Security &amp;gt; Security &amp;gt; Use secure DNS with a radio button disabling Secure DNS&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;firefox&#34;&gt;Firefox&lt;/h4&gt;
&lt;p&gt;In Firefox, go to Network Settings, then disable DNS over HTTPS.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/dns-over-https-firefox.webp&#34; alt=&#34;Firefox preferences, navigated to Network Settings &amp;gt; Enable DNS over HTTPS, with a check box unchecked.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Then close any open tabs in your browser and quit it completely. Then start it again.&lt;/p&gt;
&lt;h3 id=&#34;browse-the-website-directly&#34;&gt;Browse the website directly&lt;/h3&gt;
&lt;p&gt;Now go to www.endpointdev.com.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/origin.webp&#34; alt=&#34;IPvFoo showing the origin&amp;rsquo;s IP address&#34;&gt;&lt;/p&gt;
&lt;p&gt;IPvFoo is now showing the origin IP address we gave it, so we know that we&amp;rsquo;re being served data directly from that server.&lt;/p&gt;
&lt;p&gt;We can also run &lt;code&gt;whois&lt;/code&gt; on our origin server, for good measure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ whois 23.239.26.161
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✀
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OrgName:        Linode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✀&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we&amp;rsquo;re getting the Linode IP address, not Cloudflare&amp;rsquo;s. This is expected, since our origin site is hosted on a server at Linode.&lt;/p&gt;
&lt;h3 id=&#34;check-certificate-issuer&#34;&gt;Check certificate issuer&lt;/h3&gt;
&lt;p&gt;You can also check that the certificate issuer changed. Keep in mind that sometimes your certificate issuer might be the same when serving directly as when serving through a CDN, if you got a certificate signed by the CDN, or if you gave your CDN your TLS key &amp;amp; certificate to use.&lt;/p&gt;
&lt;p&gt;But if there &lt;em&gt;is&lt;/em&gt; a different certificate being served, we will likely see it was signed by a different certificate authority (CA):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/bypassing-a-cdn-to-browse-a-website-directly-on-your-origin-host/cert-issuer-chrome-after.webp&#34; alt=&#34;Chrome showing Sectigo as the certificate-issuing authority, after sidestepping the CDN.&#34;&gt;&lt;/p&gt;
&lt;p&gt;After sidestepping Cloudflare our certificate is issued by Sectigo, so this is more proof our changes are working.&lt;/p&gt;
&lt;h3 id=&#34;clean-up&#34;&gt;Clean up&lt;/h3&gt;
&lt;p&gt;When you&amp;rsquo;re all done, open /etc/hosts again and either delete the line you added or comment it out by putting a # at the beginning of the line.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# 23.239.26.161 www.endpointdev.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Save.&lt;/p&gt;
&lt;p&gt;Then close all browser windows, quit, and restart, and when you go to www.endpointdev.com, Cloudflare should be in the middle again.&lt;/p&gt;
&lt;h3 id=&#34;mobile&#34;&gt;Mobile&lt;/h3&gt;
&lt;p&gt;Note that there is no easy way to do something like this on iOS with an iPhone or iPad, as far as I can tell. And on Android, you either need a rooted phone, or a fancy VPN that lets you change your hostname mapping. I tried &lt;a href=&#34;https://play.google.com/store/apps/details?id=dns.hosts.server.change&amp;amp;hl=en_US&amp;amp;gl=US&#34;&gt;Hosts Go&lt;/a&gt; and it worked, despite some annoying ads which you don&amp;rsquo;t have to deal with in an /etc/hosts file 😁.&lt;/p&gt;
&lt;p&gt;If you need to test on mobile, or on multiple devices, you could also use a DNS server on your local network, and configure any device to point to your local DNS. &lt;a href=&#34;https://pi-hole.net/&#34;&gt;Pi-hole&lt;/a&gt; is a great option for this; see our &lt;a href=&#34;https://www.endpointdev.com/blog/2020/12/pihole-great-holiday-gift/&#34;&gt;blog post&lt;/a&gt; from a couple years ago for some of its other features.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Jamstack Conf Virtual 2020: Thoughts &amp; Highlights</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2020/06/jamstack-conf-virtual-may-2020/"/>
      <id>https://www.endpointdev.com/blog/2020/06/jamstack-conf-virtual-may-2020/</id>
      <published>2020-06-16T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2020/06/jamstack-conf-virtual-may-2020/conference.jpg&#34; alt=&#34;Conference&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;welcome-to-jamstack-conf-virtual-2020&#34;&gt;Welcome to Jamstack Conf Virtual 2020&lt;/h3&gt;
&lt;p&gt;Last week I attended &lt;a href=&#34;https://jamstackconf.com/2020/may/&#34;&gt;Jamstack Conf Virtual 2020&lt;/a&gt;. It had originally been slated to take place in London, UK but was later transformed into a virtual event in light of the COVID-19 pandemic. The conference began at 2pm London time (thankfully I double-checked this the night before!)—​6am for those of us in the Pacific Time Zone.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Up early for &lt;a href=&#34;https://twitter.com/hashtag/jamstackconf?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#jamstackconf&lt;/a&gt; 😎☕️ &lt;a href=&#34;https://t.co/ydjvrHWCZH&#34;&gt;pic.twitter.com/ydjvrHWCZH&lt;/a&gt;&lt;/p&gt;— Greg Davidson (@syncopated) &lt;a href=&#34;https://twitter.com/syncopated/status/1265637434638778368?ref_src=twsrc%5Etfw&#34;&gt;May 27, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;p&gt;Before getting too much further I wanted to mention that if you are not familiar with the Jamstack, You can read more about it at &lt;a href=&#34;https://jamstack.org/&#34;&gt;jamstack.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To virtually participate in the conference we used an app called &lt;a href=&#34;https://hopin.com/&#34;&gt;Hopin&lt;/a&gt;. I had not heard of it before but was impressed with how well it worked. There were over 3000 attendees from 130+ countries one of the times I checked. &lt;a href=&#34;https://www.hawksworx.com/&#34;&gt;Phil Hawksworth&lt;/a&gt; was the Host/​MC for the event and did a great job. There were virtual spaces for the stage, sessions, expo (vendors), and networking. If you opted to, the networking feature paired you with a random attendee for a video chat. I’m not sure what I expected going into it but I thought it was fun. I met a fellow developer from the Dominican Republic. The experience was very similar though more serendipitous than the hallway track or lunch line at an in-person conference.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/06/jamstack-conf-virtual-may-2020/phil-welcome.png&#34; alt=&#34;Phil Hawksworth welcoming the attendees&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;keynote&#34;&gt;Keynote&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/biilmann&#34;&gt;Matt Biilmann&lt;/a&gt; opened the conference with a keynote address about the challenges we face as a developer community trying to improve access to accurate, timely and locally relevant information to a global audience. Many billions of users with all kinds of devices and varying levels of connectivity. He moved on to share how Netlify is trying to enable developers to “build websites instead of infrastructure” and “ensure all the best practices become common practices” through features like git-based deployments, build plugins, and edge handlers (more on those later).&lt;/p&gt;
&lt;h3 id=&#34;state-of-the-jamstack-survey-results&#34;&gt;State of the Jamstack Survey results&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/06/jamstack-conf-virtual-may-2020/laurie-voss-talk.png&#34; alt=&#34;Laurie Voss reporting findings from the Jamstack Survey 2020&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://seldo.com/&#34;&gt;Laurie Voss&lt;/a&gt; &lt;a href=&#34;https://slides.com/seldo/jamstack-survey-2020#/&#34;&gt;walked us through&lt;/a&gt; the results of the &lt;a href=&#34;https://www.netlify.com/blog/2020/05/27/state-of-the-jamstack-survey-2020-first-results/&#34;&gt;Jamstack Survey 2020&lt;/a&gt;. There were some interesting findings and surprises. Later on I read &lt;a href=&#34;https://seldo.com/posts/you-will-never-be-a-full-stack-developer/&#34;&gt;Laurie’s post&lt;/a&gt; (which Matt had mentioned in his talk) and found that very interesting as well.&lt;/p&gt;
&lt;h3 id=&#34;fireside-chat-with-harper-reed&#34;&gt;Fireside chat with Harper Reed&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/06/jamstack-conf-virtual-may-2020/harper-phae-talk.png&#34; alt=&#34;Frances Berriman interviewed Harper Reed - fireside chat style&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://fberriman.com/&#34;&gt;Frances Berriman&lt;/a&gt; chatted with &lt;a href=&#34;https://harperreed.com/&#34;&gt;Harper Reed&lt;/a&gt; and asked him about his application of Jamstack principles from years ago when he led the technology team for Barack Obama’s election campaign. He described the need to “get far with very limited resources” and spoke about experimenting with serving HTML from Google App Engine and Amazon S3. Using pre-built HTML allowed them to scale very efficiently and he opted to use message queues rather than interacting with the database to keep things very quick for users.&lt;/p&gt;
&lt;p&gt;Another benefit Harper noted was how quickly and easily new team members could be onboarded. Folks who knew HTML, CSS and JavaScript would be up to speed and productive in no time. He admitted it’s more complicated today 😀. Speed is another benefit—he just loves when he comes across a super-fast web site (often mostly static).&lt;/p&gt;
&lt;h3 id=&#34;lightning-launch-netlify-&#34;&gt;Lightning Launch: Netlify ⚡&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/calavera&#34;&gt;David Calavera&lt;/a&gt; gave a demo of Netlify’s new Edge Handlers feature which lets developers add logic to their code at the edge (e.g. the CDN servers geographically closest to the user). He demonstrated how Edge Handlers make it possible to examine the headers of the request to tailor the response to that unique request. Check out the &lt;a href=&#34;https://www.youtube.com/watch?v=D44n8YVb5iI&#34;&gt;video of his talk&lt;/a&gt; to watch him live code an example. I believe &lt;a href=&#34;https://workers.cloudflare.com/&#34;&gt;Cloudflare Workers&lt;/a&gt; and Fastly’s &lt;a href=&#34;https://www.fastly.com/products/edge-compute/serverless&#34;&gt;Edge Compute&lt;/a&gt; are operating in a similar problem space. I plan to look into each of these offerings more thoroughly in future.&lt;/p&gt;
&lt;h3 id=&#34;lightning-launch-prismic-&#34;&gt;Lightning Launch: Prismic ⚡&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/RenaudBressand&#34;&gt;Renaud Bressand&lt;/a&gt; from Prismic demoed &lt;a href=&#34;https://www.slicemachine.dev/&#34;&gt;Slicemachine&lt;/a&gt;—​a new feature from Prismic which lets you combine &lt;a href=&#34;https://nuxtjs.org/&#34;&gt;nuxt&lt;/a&gt;/​Vue components with content managed in Prismic. It looked like a very compelling way of enabling better collaboration between developers and content creators.&lt;/p&gt;
&lt;h3 id=&#34;lightning-launch-redwoodjs-&#34;&gt;Lightning Launch: RedwoodJS ⚡&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://tom.preston-werner.com/&#34;&gt;Tom Preston-Werner&lt;/a&gt; demoed his latest project &lt;a href=&#34;https://redwoodjs.com/&#34;&gt;RedwoodJS&lt;/a&gt;. I had heard Tom speak about this on a few podcasts recently and it was nice to see him demo it for us. It looks interesting and feels reminiscent of &lt;a href=&#34;https://rubyonrails.org/&#34;&gt;Rails&lt;/a&gt;. RedwoodJS simplifies wiring up your database to a &lt;a href=&#34;https://graphql.org/&#34;&gt;GraphQL&lt;/a&gt; API (they use &lt;a href=&#34;https://www.prisma.io/&#34;&gt;Prisma&lt;/a&gt; for this) and integrating it into a React application. Tom is also the creator of &lt;a href=&#34;https://jekyllrb.com/&#34;&gt;Jekyll&lt;/a&gt;—​a Jamstack-style tool which has been around for many years. It was nice to see several speakers give him some recognition for his work on that project.&lt;/p&gt;
&lt;h3 id=&#34;the-covid-tracking-project-0-to-2m-api-requests-in-3-months&#34;&gt;The COVID Tracking Project: 0 to 2M API requests in 3 months&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/06/jamstack-conf-virtual-may-2020/kissane.png&#34; alt=&#34;Erin Kissane presenting The COVID Tracking Project&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://incisive.nu/&#34;&gt;Erin Kissane&lt;/a&gt; gave an inspiring talk about her work on &lt;a href=&#34;https://covidtracking.com&#34;&gt;The COVID Tracking Project&lt;/a&gt;. She described it as an “interim public data rescue project”. Erin and some friends, journalists and volunteers worked together to create the site. They started by scraping COVID data from each state’s web site and storing it in a Google Sheet. They used &lt;a href=&#34;https://www.gatsbyjs.com/&#34;&gt;Gatsby&lt;/a&gt;, &lt;a href=&#34;https://www.contentful.com/&#34;&gt;Contentful&lt;/a&gt;, and &lt;a href=&#34;https://css-tricks.com/introducing-sass-modules/&#34;&gt;Sass modules&lt;/a&gt; and hosted the site on Netlify. Using the Jamstack approach allowed the site to remain performant and continue to be responsive under some huge traffic spikes. Over time, they iterated on the design and continue to improve the site daily. I highly recommend checking out the &lt;a href=&#34;https://www.youtube.com/watch?v=ryngYoHXNfQ&#34;&gt;video of the talk&lt;/a&gt; when you get a chance.&lt;/p&gt;
&lt;h3 id=&#34;jamstack-for-emerging-markets&#34;&gt;Jamstack for emerging markets&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://www.codebeast.dev/&#34;&gt;Christian Nwamba&lt;/a&gt; described some of the challenges of building sites for users in Nigeria (low power devices, spotty connectivity, unreliable power). He shared that 55% of the most visited sites in Nigeria are global companies (Google, Facebook/​Instagram, Netflix, Stack Overflow etc.). Christian reviewed a large, popular banking site in Nigeria and noted its many shortcomings.&lt;/p&gt;
&lt;p&gt;To demonstrate how the bank might do better he built &lt;a href=&#34;https://proud-flower-060c1e01e.azurestaticapps.net/&#34;&gt;an app&lt;/a&gt; for transferring money between friends &amp;amp; family built in the Jamstack style and using serverless functions. The most interesting thing I picked up from this was his method of using serverless functions to protect the app secrets (API keys, etc.). The front end of the application did not need to concern itself with this—​the serverless functions kept the secrets safe and acted as a proxy between the frontend and the backend APIs. Be sure to take a look at &lt;a href=&#34;https://github.com/christiannwamba/quickbank&#34;&gt;Christian’s code&lt;/a&gt; if you are interested.&lt;/p&gt;
&lt;h3 id=&#34;managing-diabetes-with-jamstack&#34;&gt;Managing diabetes with Jamstack&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://jamiebradley.dev/&#34;&gt;Jamie Bradley&lt;/a&gt; taught us about diabetes and the Jamstack app he built to help himself and others manage it. He built &lt;a href=&#34;https://heysugar.health/&#34;&gt;HeySugar&lt;/a&gt; with Gatsby and Sanity, hosted it on Netlify. He’s making it easier for others to deploy their own instances as well.&lt;/p&gt;
&lt;h3 id=&#34;selling-tickets-without-servers-or-frameworks-or-cookies&#34;&gt;Selling tickets without servers. Or frameworks. Or cookies.&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://jvhellemond.nl/&#34;&gt;Jan van Hellemond&lt;/a&gt; has volunteered for years at a very popular conference in Europe (&lt;a href=&#34;https://fronteers.nl/congres&#34;&gt;Fronteers&lt;/a&gt; I think). In previous years tickets sold out in 6 minutes one year, and 30 seconds in another! Their ticket vendor was struggling to handle to the load and this caused them to oversell early bird tickets. Jan built a Jamstack site to sell their tickets and was very pleased with the performance. He used simple, single-purpose vanilla JavaScript components and simple, single-purpose API handlers (serverless functions).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/06/jamstack-conf-virtual-may-2020/tickets.png&#34; alt=&#34;Jan presenting his Jamstack ticket selling app&#34;&gt;&lt;/p&gt;
&lt;p&gt;Jan prerendered as much as possible and seeded a relational database with the tickets available for sale. As the tickets were sold, they were marked sold with a database update. Webhooks were used as customers stepped through the checkout flow. Jan joked about deploying to production on a Friday afternoon because of how safe and simple the deployment process was. There were no services to restart, etc. because “it’s just files”. It was cool to see a practical example and that Jan used the basic building blocks of the web (HTML, JavaScript, CSS, old school links) successfully without reaching for a large JavaScript framework.&lt;/p&gt;
&lt;h3 id=&#34;the-business-side-of-the-jamstack&#34;&gt;The business side of the Jamstack&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/_anarossetto_&#34;&gt;Ana Rossetto&lt;/a&gt; shared how her company has been having great success with the Jamstack. Previously, the agency had been building projects for clients with Drupal. She walked through a project she and the team built to encourage people to buy from small, locally-owned businesses. She was impressed with what they were able to create in a very short amount of time.&lt;/p&gt;
&lt;h3 id=&#34;build-plugin-authors-session&#34;&gt;Build plugin authors’ session&lt;/h3&gt;
&lt;p&gt;After the main talks there were several sessions. In the Hopin app, I was able to peek into some of these and the presenters and attendees were chatting (both text chat and video). This was very much like the experience of peeking into conference rooms at a physical venue and choosing whether to stay and participate or move on. After some wandering I chose to attend a session with three Netlify build plugin authors.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/06/jamstack-conf-virtual-may-2020/subfont.png&#34; alt=&#34;Peter telling us about subfont&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://mntr.dk/&#34;&gt;Peter Müller&lt;/a&gt; built &lt;a href=&#34;https://github.com/Munter/netlify-plugin-subfont&#34;&gt;Subfont&lt;/a&gt; with a friend. He demonstrated how subsetting web fonts (i.e. only loading the characters &amp;amp; glyphs you really need) can dramatically improve frontend performance. He compared the &lt;a href=&#34;https://webpagetest.org/&#34;&gt;WebPageTest&lt;/a&gt; results for Google Fonts with and without Subfont and Subfont was seconds faster! I have subset and locally hosted webfonts in several client projects here at End Point. It takes time and is a manual process. Peter’s plugin makes this excellent performance improvement relatively painless.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://darn.es/&#34;&gt;David Darnes&lt;/a&gt; demoed his build plugin to &lt;a href=&#34;https://github.com/daviddarnes/netlify-plugin-ghost-markdown&#34;&gt;turn Ghost content into Markdown files&lt;/a&gt;. Very interesting and it seemed flexible enough to work with other tools as well.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/bahmutov&#34;&gt;Gleb Bahmutov&lt;/a&gt; presented the build plugin he created to run &lt;a href=&#34;https://www.cypress.io/&#34;&gt;Cypress&lt;/a&gt; tests as part of your Netlify build process. It was amazing to see how simple it was (single devDependency and single line in the netlify.toml config file).&lt;/p&gt;
&lt;h3 id=&#34;videos-from-the-conference&#34;&gt;Videos from the conference&lt;/h3&gt;
&lt;p&gt;Netlify has already put all of the &lt;a href=&#34;https://www.youtube.com/playlist?list=PL58Wk5g77lF8jzqp_1cViDf-WilJsAvqT&#34;&gt;Jamstack Conf Virtual 2020 talks&lt;/a&gt; on YouTube so head over there and check those out if you’d like to. Thanks very much to the team at Netlify for organizing the conf, all of the speakers, vendors and attendees!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Cloudflare and Vue SSR; Client Hydration Failures</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2019/06/cloudflare-vue-ssr-significant-comments/"/>
      <id>https://www.endpointdev.com/blog/2019/06/cloudflare-vue-ssr-significant-comments/</id>
      <published>2019-06-11T00:00:00+00:00</published>
      <author>
        <name>David Christensen</name>
      </author>
      <content type="html">
        &lt;img src=&#34;/blog/2019/06/cloudflare-vue-ssr-significant-comments/banner.jpg&#34; alt=&#34;Camera and instant photos&#34; /&gt;
&lt;p&gt;&lt;a href=&#34;https://www.flickr.com/photos/freestocks/29163583261&#34;&gt;Photo&lt;/a&gt; by &lt;a href=&#34;https://www.flickr.com/photos/freestocks&#34;&gt;freestocks&lt;/a&gt;, used under &lt;a href=&#34;https://creativecommons.org/publicdomain/zero/1.0/&#34;&gt;CC0 1.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I recently worked on getting a client’s Vue application converted to use Server Side Rendering (SSR). SSR works by generating the app’s initial HTML structure using a server-side process and then using client-side JavaScript to initialize or “hydrate” the application state on the client-side.&lt;/p&gt;
&lt;p&gt;This worked out well in development and testing, however when it came time to roll things out to production, we ended up with a non-functioning application. While the server-rendered content was displaying inline, the client hydration piece was failing, and I was seeing browser console errors that I had never encountered before:&lt;/p&gt;
&lt;p&gt;The error in Chrome:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chunk-vendors.342a7610.js:21 Uncaught DOMException: Failed to execute &amp;#39;appendChild&amp;#39; on &amp;#39;Node&amp;#39;: This node type does not support this method.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The error in Safari:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[Error] HierarchyRequestError: The operation would yield an incorrect node tree.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	get (chunk-vendors.342a7610.js:27:30686)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	er (chunk-vendors.342a7610.js:27:30565)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	Le (chunk-vendors.342a7610.js:27:27806)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	xe (product-listing.0773c46e.js:1:18553)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[Error] TypeError: undefined is not an object (evaluating &amp;#39;t.$scopedSlots&amp;#39;) — chunk-vendors.342a7610.js:27:27998
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	on (chunk-vendors.342a7610.js:27:12025)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	rn (chunk-vendors.342a7610.js:27:11937)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	nn (chunk-vendors.342a7610.js:27:11584)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	(anonymous function) (chunk-vendors.342a7610.js:27:12759)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	fn (chunk-vendors.342a7610.js:27:12135)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	promiseReactionJob&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since the client hydration was failing, this resulted in a non-functioning front-end application which we had to quickly roll back. I’d scratched my head over this quite a bit, as this had been well-tested in development and staging.&lt;/p&gt;
&lt;p&gt;After testing direct access to the origin server via &lt;code&gt;/etc/hosts&lt;/code&gt; modification, we determined that the server itself was returning content that was working fine, so this pointed to something about the caching layer.&lt;/p&gt;
&lt;p&gt;The errors being generated were similar to errors I’d encountered before during development where the generated DOM in the SSR content was mismatched with the version of the client-side Vue application.&lt;/p&gt;
&lt;p&gt;One of the big differences here was that production was being served via Cloudflare (CF), however we had not run into any issues with stale versions (i.e., older versions of code being returned) and the like in the past. Our resources were stamped hashes via webpack, so per-application version shouldn’t have been utilizing cached old versions of the generated resources in question.&lt;/p&gt;
&lt;p&gt;Because we could not really debug this issue on production and this was still just a theory that CF was the issue, we ended up setting up a development environment behind Cloudflare.&lt;/p&gt;
&lt;p&gt;Sure enough, the same issue started occurring in the development environment with Cloudflare fronting it; now, however, we had time to debug/diagnose without affecting production users.&lt;/p&gt;
&lt;p&gt;After comparing the static JS for the app returned through CF against the raw source files, I noticed that they were slightly smaller. We had already minified the source as part of our production build, but CF was further minifying things, removing newlines and JS comments that had been left in the prod build. This made me realize that something on the CF side was minifying resources further.&lt;/p&gt;
&lt;p&gt;After some research, it turns out the CF has an &lt;code&gt;AutoMin&lt;/code&gt; setting to allow the automatic minification of served resources (JS, CSS, and HTML). This setting was contributing to the minification that I was seeing. However, this could not explain what I was seeing on the JS minification alone; these were verified non-functional changes that should not affect how the app ran.&lt;/p&gt;
&lt;p&gt;I turned my attention to the HTML of the page itself. Comparing the CF-returned version with the version returned by the app, I quickly saw that minification was affecting this returned HTML as well, cleaning up spacing/formatting and HTML comments as well.&lt;/p&gt;
&lt;p&gt;And herein lay the issue; Vue SSR sticks in HTML comments as placeholders for nodes which are non-visible at server render time. So for example, if you had a Vue component like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;template&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    My component!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;v-if&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;display&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;v-for&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;l in list&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {{ l }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;template&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;default&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;MyComponent&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  data () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      list: [&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  props: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    display: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      type: &lt;span style=&#34;color:#038&#34;&gt;Boolean&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;default&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This would render in Vue SSR as the following HTML (assuming the component was not shown by the calling app):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;My component!&lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!-----&amp;gt;&lt;/span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, the &lt;code&gt;&amp;lt;!-----&amp;gt;&lt;/code&gt; placeholder is a &lt;em&gt;significant&lt;/em&gt; HTML comment, standing in for a non-visible component in the virtual DOM (the false condition in the &lt;code&gt;v-if&lt;/code&gt; directive). Rehydration requires this to be in place for proper handling, so when CF stripped out HTML comments from the returned page output this disrupted the generated server-side DOM. This meant that the server-side DOM no longer matched what Vue was expecting and the client-side hydration failed and the app failed to init properly.&lt;/p&gt;
&lt;p&gt;I tested disabling &lt;code&gt;AutoMin&lt;/code&gt; for the test site, which resulted in a functioning application, verifying this was the issue. We did not want to turn off &lt;code&gt;AutoMin&lt;/code&gt; globally, so I looked around for ways to narrow this down to only the affected pages (all of which had a common URL prefix).&lt;/p&gt;
&lt;p&gt;I came across CF’s &lt;code&gt;Page Rules&lt;/code&gt; settings, which let you modify its handling of specific URLs. I added an exception for the pages in question, turning off only the &lt;code&gt;AutoMin&lt;/code&gt; setting for these pages, and voilà, the app worked while leaving this setting on for the rest of the site.&lt;/p&gt;
&lt;h3 id=&#34;tldr&#34;&gt;TL;DR:&lt;/h3&gt;
&lt;p&gt;Cloudflare’s &lt;code&gt;AutoMin&lt;/code&gt; setting can interfere with Vue SSR output by removing significant HTML comments. The fix is to disable &lt;code&gt;AutoMin&lt;/code&gt; on the relevant pages using &lt;code&gt;Page Rules&lt;/code&gt;.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
