Cache Bust WordPress Assets Based On Git Revision

Cache busting is to rewrite a URL for an asset (JS, CSS, images, etc) so that is unique. This way, you can cache them for as long as you want. If the URL changes, it will use the new file.

I am using deployments tool to checkout the latest version of a given branch, therefore I know that there will be a .git folder on my production server.

The idea is to use the current Git commit as a version number using git head reference.

function project_get_current_git_commit( $branch = 'master', $length = false ) {
  if ( ! defined( 'PROJECT_CURRENT_GIT_COMMIT' ) ) {
    $hash = file_get_contents( sprintf( '%srefs/heads/%s', dirname(__FILE__), $branch ) );
 
    define( 'PROJECT_CURRENT_GIT_COMMIT', ( $hash ? $hash : false ) );
  }
 
  return ( $length ? substr( PROJECT_CURRENT_GIT_COMMIT, 0, $length ) : PROJECT_CURRENT_GIT_COMMIT );
}
 
// Enqueue WordPress asset
wp_enqueue_script('application','/assets/javascripts/application.min.js', array('), project_get_current_git_commit( 'master', 8 ), true);

Voilá, now you can cache bust everything based upon your latest Git revision.

Of course, there are other ways to do this as well. Another solution is to store environment variables that contains the latest revision and then read it from PHP, that would save some I/O from the physical file.

Installing WordPress core via Composer and finding the proper rewrites for Nginx or Apache

The idea is to separate the WordPress site’s components into their own directories right at the root. This creates a simple modular structure, where parts of a WordPress site are totally on their own. This makes things less complex and less prone to errors.

We will not be touching the WordPress subdirectory, we will only update it when a new version is released. Therefore, we will have to put our configuration and custom development (themes & plugins) outside the WordPress folder.

I’m going to use Composer package manager for PHP to install these packages and this is the directory structure that I want to create.

Directory structure

website/
--config/ 
--vendor/
--lib/
--www/
    wp/ - Will contain the WordPress package
    wp-content/ - Will contain all my themes and plugins
    .htaccess
    index.php
    wp-config.php
composer.json

Composer file

The Composer can be used for both the core and plugins, for plugins we will use wpackagist. After you’ve installed composer, create a composer.json in your root folder that looks something like this:

{
  "name": "parse/demo",
  "description": "Parse: Demo",
  "license": "proprietary",

  "repositories": [
    { "type":"composer", "url":"http://wpackagist.org" },

    { "type": "package",
      "package" : {
        "name": "wordpress",
        "type": "webroot",
        "version": "3.7.1",
        "dist": {
          "type": "zip",
          "url": "https://github.com/WordPress/WordPress/archive/3.7.1.zip"
       },
        "require" : {
          "fancyguy/webroot-installer": "1.1.0"
        }
      }
    }
  ],

  "require": {
    "composer/installers": "1.0.x-dev",
    "wordpress": "3.7.1",
    "wpackagist/mp6": "~2.1"
  },

  "require-dev": {
    "wpackagist/debug-bar": "~0.8",
    "wpackagist/debug-bar-console": "~0.3"
  },

  "minimum-stability": "dev",

  "extra": {
    "wp-content": "www/wp-content",
    "webroot-dir": "www/wp",
    "webroot-package": "wordpress",
    "installer-paths": {
      "www/wp-content/plugins/{$name}/": ["type:wordpress-plugin"]
    }
  }
}

This file defines that we want to install WordPress core in a folder www/wp/ and its plugins in www/wp-content/plugins/

index.php

By moving the WordPress core, the index.php that is in www/ will now have to be changed to:

<?php
// WordPress view bootstrapper
define( 'WP_USE_THEMES', true );
require( './wp/wp-blog-header.php' );

wp-config.php

And since we will not use the wp-content/ folder in www/wp/wp-content/, we need to redefine that in wp-config.php:

<?php
define('WP_CONTENT_DIR', dirname(__FILE__) . '/wp-content');
define('WP_CONTENT_URL', 'http://' . $_SERVER['HTTP_HOST'] . '/wp-content');

Now, we have set up the files, your vhost need to be configured to the www/ folder.

Nginx

After struggling a bit with PHP’s PATH_INFO variable and found a solution, this is the important part:

if (!-e $request_filename) {
  rewrite /wp-admin$ $scheme://$host$uri/ permanent;
  rewrite ^(/[^/]+)?(/wp-.*) /wp$2 last;
  rewrite ^(/[^/]+)?(/.*\.php)$ /wp$2 last;
}

location / {
  root   /home/username/apps/appname/current/www/;
  try_files $uri $uri/ /index.php?$args;
  index index.php;
}

location ~ \.php$ {
  fastcgi_pass 127.0.0.1:9000;
  fastcgi_index index.php;
  fastcgi_split_path_info ^(.+\.php)(/.+)$;
  fastcgi_param SCRIPT_FILENAME /home/username/apps/appname/current/www$fastcgi_script_name;
  fastcgi_param ENVIRONMENT production;
  fastcgi_param PATH_INFO $fastcgi_script_name;
  include /etc/nginx/fastcgi_params;
}

Apache

<VirtualHost *:80>
    ServerName domainname.com
    DocumentRoot "/home/username/apps/appname/current/www/"
    <Directory "/home/username/apps/appname/current/www/">
        Options Indexes Includes FollowSymLinks  
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

The .htaccess in this case will look something like this:

Options -Indexes
 
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
 
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
 
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) wp/$2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ wp/$2 [L]
RewriteRule . index.php [L]

To upgrade plugins or core, you simply need to update your composer.json. We still need to add custom plugins into our repository, but you could create your own repositories for them as well.

My experience at Uppsala Hackathon, and how to build a mobile app in a day

This post originally appeared at Swedish Startup Space.

Swedish Startup Space wrote about the Uppsala Hackathon back in June and I decided that I wanted to participate in this “gathering of programmers to collaboratively code in an extreme manner over a short period of time”.

The Uppsala Hackathon was attended by about 60-70 participants. Some people had teams and ideas before they arrived, but I had not found a team, so I joined one that consisted of the Valtech ConsultantsSara IngmarDaniel LervikPetter Norman and Sandra Nyström.

Design and Motive

In the beginning of the hackathon we knew that we wanted to build an app that would help solve difficulties when using public transportation. To solve the problem, we needed to use a few different API’s. Instead of collecting information from different API’s and combing results on the mobile application itself – we decided to build our own API.

In doing so, we keep the amount of data down to a minimum which is good because traveller’s/commuters doesn’t always have high bandwidth networks available. We can also be confident that we are sending the correct information to the device and avoid wasting precious data. This also gives us the opportunity to extend our service with more public transport agencies while maintaining control of performance and bandwidth of the app. Another benefit of using your own API, is that it makes it extremely easy to build another app for another platform since we have full control of the API.

Backend solution

We chose to build the API on .NET because the team had most experience on the platform. Daniel had previously participated in a project at Valtech where ServiceStack was used to build the API. ServiceStack is an open source REST web services framework which had lots of good stuff we could use. To further speed up the development process we used AppHarbor to host the API.

Mobile app

The mobile app was going to use the API generated by the ServiceStack. Both Daniel and myself have previous experience of developing mobile applications, so we focused on this part. The API was consumed using RestKit, an amazing framework for dealing with RESTful APIs.

The mobile app was developed using CocoaPods, because there is no sane person that enjoys dealing with dependencies and build flags in Xcode. Enter SLussen, see the demo of the app in the video below.

Disclaimer: the lag you see in the film is because of the delay that appeared when doing screen recordings.

We won! The jury wrote the motivation:

The SLussen project helps commuting travelers to calculate total ticket prices when traveling through different zones in Stockholm county. This project has was picked for its potential value in Uppsala county.

Read more

Thanks Petter for a great summary of the backend!

Video

Remove Previous, Next and Done buttons from keyboard in Phonegap in iOS

I’ve been working on my first Phonegap project together with a friend the last week or so. He’s been developing most of the app for Android and Eclipse, and my job is to make sure it runs smoothly in iOS. It contains in-apps and some other goodies that I will post about later.

Hide buttons

Since everything in Phonegap is a UIWebView, I needed a way to get rid of the silly previous, next and done buttons when focusing my keyboard. This uses private API:s so it will make your app rejected if you submit with this code.
6X1vv

The solution is to modify your AppDelegate.m to something like this:

Remove and add focus on keyboard

When bringing a keyboard in and out, use the following to remove focus from it

$('#searchform-1').blur();

And use this to bring focus to an input field:

$('#searchform-1').focus();

Swedish Startup Space launched!

Last week a friend of mine got in touch with me, asking for help about a website he’s been trying to put together on his own. James now works at Helishopter and previously worked for Jameslist. He wanted to create a community for swedish startups, it was something he and many others felt was missing for the swedish startup scene.

Said and done, yesterday we launched our first version. It was running on Heroku for a few hours but the site broke down and I had to move the site in haste to Binero. Since we are running WordPress and all the media assets is on Amazon S3 it is very easy to migrate the site to another host. We will make sure to make the new setup more stable before we attempt to move it again.

Head over and visit us!

© Copyright 2002 - 2014 Anders Hassis

Built on Notes Blog Core