Using Bootstrap with (JS/ CSS) resource aggregation

Note: this article applies to Bootstrap 2.3 only

The resource aggregation function was introduced in Domino 8.5.3. It automatically combines the CSS and JavaScript files loaded on a webpage into a single file, thus reducing the number of requests on a page. Brad Balassaitis did some tests with this option to show the (enormous) gains you get when enabling it. Reducing the number of requests is especially relevant when using a mobile internet connection.

If you use Bootstrap and enable the option, you'll find that it will break the links to the default Bootstrap images. The reason for this is the (virtual) location of the combined CSS file changes.

A possible solution is to create a simple css file that overrides the image location and add that to your page/ app. The bootstrap CSS files only refer to images in 2 CSS selectors, so those are the only you need to override. In Bootstrap 2.3.1 the override CSS file looks like this:

/*keep showing images if css aggregation is used*/
[class^="icon-"],
[class*=" icon-"] {
  background-image: url("../../../bootstrap/img/glyphicons-halflings.png");
}
.icon-white,
.nav-pills > .active > a > [class^="icon-"],
.nav-pills > .active > a > [class*=" icon-"],
.nav-list > .active > a > [class^="icon-"],
.nav-list > .active > a > [class*=" icon-"],
.navbar-inverse .nav > .active > a > [class^="icon-"],
.navbar-inverse .nav > .active > a > [class*=" icon-"],
.dropdown-menu > li > a:hover > [class^="icon-"],
.dropdown-menu > li > a:focus > [class^="icon-"],
.dropdown-menu > li > a:hover > [class*=" icon-"],
.dropdown-menu > li > a:focus > [class*=" icon-"],
.dropdown-menu > .active > a > [class^="icon-"],
.dropdown-menu > .active > a > [class*=" icon-"],
.dropdown-submenu:hover > a > [class^="icon-"],
.dropdown-submenu:focus > a > [class^="icon-"],
.dropdown-submenu:hover > a > [class*=" icon-"],
.dropdown-submenu:focus > a > [class*=" icon-"] {
  background-image: url("../../../bootstrap/img/glyphicons-halflings-white.png");
}

Now here's a trick: if you only load that CSS file if resource aggregation is enabled, all images will still work if you disable the aggregation function:

<xp:this.resources>
  <xp:styleSheet href="/override.css">
   <xp:this.rendered><![CDATA[#{javascript:context.getProperty("xsp.resources.aggregate")=="true"}]]></xp:this.rendered>
  </xp:styleSheet>
 </xp:this.resources>

The code above is for when you want to load the CSS file from an XPage. If you're using themes in your application (and you should), you can also conditionally load the CSS file in the theme:

<resource rendered="#{javascript:context.getProperty('xsp.resources.aggregate').equals('true')}">
	<content-type>text/css</content-type>
	<href>override.css</href>
</resource>