Portrait bust of a man, 1st century b.c.; Republican

H. 14.37 in. (36.5 cm)
Rogers Fund, 1912 (12.233)

The traditional Roman concept of virtue called for old-fashioned morality, a serious, responsible public bearing, and courageous endurance in the field of battle. Prestige came as a result of age, experience, and competition among equals within the established political system. These are the values expressed in portraits of grim-faced, middle-aged men, such as the one featured here. Roman cultural identity was also structured around a profound respect for family and ancestry, and a principal funerary practice involved the public display of portraits of distinguished ancestors at the funeral of family members. These wax masks, called "imagines," served to advertise the family's illustrious history of public service and to inspire younger generations to strive for such achievements. Similarly, "veristic" portraits, so-called because of their seemingly harsh and severe realism, emphasized the solemnity with which the Romans regarded their civic and military responsibilities. Because the Romans considered facial features to be the best conveyors of personality, age and wisdom gained through long, hard years of life experience were accentuated in portraiture in order to project the qualities they valued most highly.

While realism was a component of Hellenistic art as well, the Republican style is also linked to Etruscan and Italic sculptural traditions. The ancestors of the Roman portrait bust can be traced to the stylized heads on Etruscan funerary jars and urns, and especially to portrait sculptures such as the bronze "Brutus" bust in the Palazzo dei Conservatori in Rome. Roman portraiture was also influenced by Etruscan honorific statuary, such as the famous Arringatore, the Orator, now in the Museo Archeologico in Florence. Dedicatory portrait statues proliferated in Roman public spaces, and represent a major component of portrait sculpture in the Re

Cache busting with SystemJS, Gulp, and Aurelia.

Clearing the SystemJS Cache

It’s important to clear the browser cache when we release new builds of our Aurelia application. This is tricky because Aurelia uses SystemJS, which is both powerful and confusing. How do we clear the Firefox cache?

A diagram of how SystemJs works with Config.js

As developers, we can use Ctrl + Shift + Del and choose to clear the cache. For releases, we cannot ask end-users to do this. We need to do it for them. That’s where cache busting is useful. If we don’t do this, end-users will see out-of-date versions of images, style sheets, JavaScript, and other resources that the web browser has cached.

We cannot ask end-users to do this (it’s bad enough that we’re asking them to download native apps.)

Check the box that indicates to clear the cache.

Clearing the SystemJS Cache via Gulp

There are a lot of approaches to cache-busting. Our favorite is to rename the directory that contains the resources, and to replace all references to that directory. This way, we trick the web browser into thinking it is requesting different resources than the ones that it cached previously.

In our cache busting feature, we use gulp to rename the directory with a build-number suffix, and we do this before and during the gulp build of the resources. This involves four high-level steps:

  1. Store the current build number somewhere. E.g. 134
  2. Increment the build number. E.g. 135
  3. Rename the build output directory with that build number. E.g. dist134 becomes dist135
  4. Replace references to the build output directory with the new name. E.g. config.js needs now to point to dist135

In the implementation, step four happens before step three. You’ll see.

Aurelia’s Project Structure as It Relates to Gulp and SystemJs

Before we start, it’s worth knowing the build output directory structure of a typical Aurelia application. We’ll need to adapt the cache-bust task to make it work with SystemJS projects that use a different structure.

In a typical Aurelia application, the relevant files are these. (For clarity, we omitted a bunch of other files.)

        cache-bust.js <-- part of our feature
    build-number.txt  <-- part of our feature


The cache-bust.js file comprises the bulk of our cache busting solution. It finds and replaces all references to the build output directory (e.g. dist) and replaces them with the new directory name (e.g. dist1). If you are a software developer with some experience with gulp, you will probably be able to understand the following code in about 5-15 minutes of analysis. Here it is:

var gulp = require('gulp');
var replace = require('gulp-replace');
var fs = require("fs");

var buildNumberFile = 'build/build-number.txt';

var filesToChange = [

gulp.task('cache-bust', function () {

    // get the current build number
    var contents = fs.readFileSync(buildNumberFile, 'utf8');
    version = parseInt(contents);

    // bump the current build number
    version = version + 1;
    fs.writeFile(buildNumberFile, version);

    // matches "dist
    // matches 'dist
    // matches "dist1
    // matches 'dist12
    var outputDirectoryRegex = /([\"|\']dist)([0-9]*)/g;

    // replace the build number in appropriate files
    gulp.src(filesToChange, { base: './' })
        .pipe(replace(outputDirectoryRegex, '$1' + version))


This build-number.txt file is the part of our cache busting solution that tracks the build number. It contains an integer. That’s it. The entire file contents is that integer. In the example, we start with 134 as our number. Then we increment.


This bundles.js file is part of the Aurelia application template. It tells the aurelia-bundler to bundle together source files. Importantly, the bundles.js file includes a reference to the build output directory. You can see the dist/app-build and the dist/aurelia bundles. Our cache-bust task replaces dist134 with dist135.

module.exports = {
  "bundles": {
    "dist/app-build": {
      "includes": [
      "options": {
         // additional code omitted for clarity
    "dist/aurelia": {
      "includes": [
        // additional code omitted for clarity
      "options": {
          // additional code omitted for clarity


The paths.js file is also part of the Aurelia application template. It lists a bunch of paths that gulp uses during its build. The outputRoot and the e2eSpecsDist both contain a reference to the build output directory. Our cache-bust task replaces those references too.

var appRoot = 'src/';
var outputRoot = 'dist';
var exporSrvtRoot = 'export/'

module.exports = {
  root: appRoot,
  source: appRoot + '**/*.ts',
  html: appRoot + '**/*.html',
  scss: 'sass/**/*.scss',
  output: outputRoot,
  exportSrv: exporSrvtRoot,
  doc: './doc',
  e2eSpecsSrc: 'test/e2e/src/**/*.ts',
  e2eSpecsDist: 'test/e2e/dist/',
  dtsSrc: [


The config.js file is part of SystemJS. It tells SystemJS the location of modules to load. Importantly, it too contains a reference to the gulp build output directory. Lo and behold, our cache-bust task replaces those references.

  defaultJSExtensions: true,
  transpiler: "none",
  paths: {
    "*": "dist",
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*"
  // other code omitted for clarity


Th package.json file is part of the NPM/JSPM package management. It contains a reference to the gulp build output directory. The main property is the “primary entry point to your program.” Our cache-bust task replace that references.

  "name": "aurelia-skeleton-navigation-typescript",
  "version": "1.0.0-beta.1.2.6",
  "main": "dist8/main.js",
  // other code omitted for clarity

Bringing it all Together

First, we call the gulp cache-bust task. Then we call gulp bundle. The cache-bust task increments the build number and replaces the output directory references with the new suffix. The bundle task will put the build output into the new distXXX directory instead of into the previous dist directory. SystemJs will look for the resources in the new directory instead of in the previous one.

gulp cache-bust
gulp bundle

Our cache is busted. That’s a good thing. 🙂

If something doesn’t look quite right or isn’t terribly clear, please let me know on Twitter @dicshaunary.