Switching from Netlify to Cloudflare Pages

I love static pages. Just generate a bunch of HTMLs, select a service to host them and that's pretty much it. No need to worry about server updates and it's blazing fast thanks to CDNs. Plus a lot of services provide free hosting for static pages.

I used to have my static pages on S3, but switched to Netlify since they provide additional features that I wanted:

Netlify worked great for this blog and it still works fine for my other sites. However I've started experimenting with Cloudflare Workers recently and they provide a great way to add dynamic functionality to static pages, like A/B testing or location dependent logic.

In order to test workers I started to route my blog through Cloudflare, which led to CDN stacking issues. Neltify was not able to renew the SSL certificates anymore and the page had caching issues as well. Since I want to keep experimenting with workers, I've decided to give Cloudflare Pages a try.

Cloudflare Pages is Cloudflare's own solution for hosting static sites. In theory serving HTML pages should work from any provider, but there were a few changes I needed to do before migrating to Cloudflare Pages. As of now Netlify provides way more features out of the box (e.g. minifying CSS files or Javascript) and the documentation is more detailed.

Pretty URLs

Both Netlify and Cloudflare Pages provide the Pretty URL functionality, which is about removing the .html extension from your URLs. Instead of ptrlaszlo.com/seo.html you end up having shorter URLs like ptrlaszlo.com/seo.

The difference is in how Netlify and Cloudflare prettify URLs. Netlify precompiles your HTML pages and strips the .html extensions from the actual links. Cloudflare doesn't change the content of the HTML, but redirects with the 308 Permanent Redirect status code. As an example, if you have <a href="/posts/seo.html">SEO</a>, Netlify will turn that into <a href="/posts/seo">SEO</a> (No .html inside href). Cloudflare keeps it as <a href="/posts/seo.html">SEO</a>, but redirects to /posts/seo after opening the link.

I don't like the idea of having a redirect for every internal link, so I had to change my HTML files and remove the .html extension from the anchor tags. This however led to another problem.

Local development

The setup for this blog is pretty simple: a file containing the post contents and a simple ruby script to generate HTML from them.

To test my changes locally, I run python3 -m http.server in the folder where the HTML files are and have the page available on localhost:8000 by default. I can't test the HTML files directly, since assets are not loading properly with relative paths.

The problem is, that now my internal links are pointing to the extensionless pages (/seo), but the actual page is /seo.html. Trying to open a link locally leads to a 404.

Testing the site locally is a must have, but I couldn't find an easy way to solve this with the python HTTP server. As a workaround I used nginx with a rewrite rule to add the .html extensions, when the given file exists:

server {
    listen       9998;
    server_name  0.0.0.0;

    location / {
        root   /Users/user/path/to/ptrlaszlo.com/generated;
        index  index.html;
        default_type text/html;

        if ($request_filename ~* ^.+.html$) {
          break;
        }
        # add .html to URI and serve file, directory, or symlink if it exists
        if (-e $request_filename.html) {
          rewrite ^/(.*)$ /$1.html last;
          break;
        }
    }
}

With nginx configured the page can be tested on localhost:9998 and the local files are the same as the ones served by Cloudflare.

Conclusion

Cloudflare provides great services, but for now Pages lags behind other providers in terms on functionality. As an example I couldn't find an option to turn off the URL prettify functionality or turning on CSS minification.

I wouldn't migrate any big projects for now, but for a small blog like this it's worth a try.

P.S. I'm ptrlaszlo on twitter, follow me for more stories.