Posts about Web Dev

The rock and the hard place for Wordpress

Let’s imagine you want to start blogging, or need to make a small website. Where do you start?

For many years, the default recommendation was WordPress. It was ​“easy to install,” ​“easy to update,” and ​“easy to use” for people who weren’t familiar with CMS technology. But I’m not sure this is true anymore, and I no longer recommend WordPress to clients.

If you’re not a developer, WordPress is not where you should start with your website. You would be better served by Squarespace, Ghost, et al. Squarespace lets you design an entire website with drag and drop features, and Ghost lets you start blogging with beautiful themes and a premium hosted service. There’s no need to install anything with either platform. And if you need to set up an online store, both Squarespace and Shopify will make your life much easier than WordPress and WooCommerce.

I’ve also noticed something else in the past couple years: WordPress is not easy to use. The backend is a monster, and Gutenberg has made it harder for my clients to use — not easier. Almost any other CMS I’ve tried has been easier for my clients to grasp than WordPress.

If you are technically proficient, it’s getting harder and harder to recommend WordPress. Thanks to Gutenberg and the increasing use of Rest APIs and Javascript, along with the old PHP core, developing for WordPress becomes more nightmarish seemingly with every passing week. 

And if you have any opinions about web development at all, WordPress’s attempts to get you to code ​“the WordPress way” will frustrate or anger you, depending on your tolerance levels. 

If you’re a modern PHP developer, you could use Bedrock to build WordPress, but it’s still WordPress. Bedrock doesn’t solve the problems that Gutenberg and the plugin architecture create. (Trust me: I built this blog with Bedrock, and as of January 2020, I plan on getting off WordPress as soon as possible.)

The problem is this: inevitably, nearly every WordPress site eventually becomes a mess of spaghetti code and plugins that make actually using the site impossible.

Developers (or technically-minded people) would be better off with almost any of the myriad CMSes that are available: Ghost, Craft, Kirby, Grav, Statamic, Shopify, and more are all typically easier to develop for than WordPress. (I haven’t even mentioned static generators.) The options are limitless.

All of this puts WordPress between a rock and a hard place. If developers and regular people should avoid it, who is it for?

I no longer have an answer.

Caching a Craft CMS site with Nginx

I recently wrapped up building my first client website with Craft CMS, and am very nearly ready to launch my new portfolio with the service as well. Craft is amazing, and completely blows away the competition for any sort of visually intensive website with complicated layouts.

That being said, one of the things I really like about the WordPress setup I use is my caching setup. I wanted something similar for Craft — something that doesn’t require a ton of work to set up or maintain.

This is largely based on Tim de Pater’s existing gist for WordPress caching, but customized to deal with Craft’s requirements. I’m also borrowing liberally from NYStudio107’s excellent article.

A couple things that are worth noting: I’m using Forge by Laravel, along with Linode, for my basic hosting needs. So some of this code will be related to that setup in particular. I’ve also removed some of this code for the sake of streamlining what you see here.

You’ll also need a Craft plugin to handle busting the cache whenever you update your site. I’m using FastCGI Cache Bust(once again from NYStudio107) to get it done, but if you wanted to write your own script or use somebody else’s plugin, I’m sure you could. (And if you’re a masochist who wants to SSH in every time you make a chance and bust the cache yourself, that’s between you and God.)

The only other thing you’ll need to do is bust the cache whenever you pull from git and run composer update on the server. I use a simple bash script for this, which you’ll find all over the web.

Everything you need to tweak in your Nginx config file should be visible below in ALL CAPS. This has been working seamlessly for me so far, and has been an even stronger solution than what I was doing for my WordPress sites.

fastcgi_cache_path /etc/nginx/cache/yourfolder/ levels=1:2 keys_zone=ZONENAME:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name YOURURL.com;
    root /home/forge/YOURURL.com/web;

    # Your SSL settings will go right here

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    # Directives to send expires headers and turn off 404 error logging.
    location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|woff2|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
           access_log off; log_not_found off; expires max;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/YOURURL.com-error.log error;

    error_page 404 /index.php?$query_string;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_cache ZONENAME;
        fastcgi_cache_valid 200 1w;
        fastcgi_cache_bypass $no_cache;
        fastcgi_no_cache $no_cache;
        fastcgi_cache_use_stale updating error timeout invalid_header http_500;
        fastcgi_cache_lock on;
        fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
    
    # Troll WordPress bots/users
    location ~ ^/(wp-login|wp-admin|wp-config|wp-content|wp-includes|(.*)\.exe) {
        return 301 https://wordpress.com/wp-login.php;
    }
    
    #Cache everything by default
    set $no_cache 0;
    
    #Don't cache POST requests
    if ($request_method = POST)
    {
        set $no_cache 1;
    }
    
    #Don't cache if the URL contains a query string
    if ($query_string != "")
    {
        set $no_cache 1;
    }
    
    #Don't cache the following URLs
    if ($request_uri ~* "/(admin/|cpresources/)")
    {
        set $no_cache 1;
    }
    
    # Don't cache uris containing the following segments
    if ($request_uri ~* "/feed/|sitemap(_index)?.xml") {
        set $no_cache 1;
    }   
    
}

# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/YOURURL.com/after/*;

Side note: I’ve been building websites professionally for close to a decade now, and this is the first time I’ve ever included a snippet of code on my blog. I’ll have to do this more often.