First off, when using http://tools.pingdom.com as well as Firebug I discovered that the static resources were in fact not cached. To correct this, all that was required was to insert a section into Web.config (in the nopCommerce root catalog of the deployed site, or in the Nop.Web project root).
I added the following code into Web.config. This allows each of the specified resources to be cached at the client for maximum 8 days.
<system.webServer>
...
<caching>
<profiles>
<add extension=".png" policy="CacheUntilChange" varyByHeaders="User-Agent" location="Client" />
<add extension=".gif" policy="CacheUntilChange" varyByHeaders="User-Agent" location="Client" />
<add extension=".jpg" policy="CacheUntilChange" varyByHeaders="User-Agent" location="Client" />
<add extension=".js" policy="CacheUntilChange" varyByHeaders="User-Agent" location="Client" />
<add extension=".css" policy="CacheUntilChange" varyByHeaders="User-Agent" location="Client" />
<add extension=".axd" kernelCachePolicy="CacheUntilChange" varyByHeaders="User-Agent" location="Client" />
</profiles>
</caching>
<httpProtocol allowKeepAlive="true">
<customHeaders>
<add name="Cache-Control" value="public, max-age=691200" />
</customHeaders>
</httpProtocol>
</system.webServer>
The improvement was seen on the second request, where 20 or so files were already in cache, and load time went from 1.2s to 0.6s.
The second change I made was to use CDN (Content Delivery Networks) for the core javascripts, boosting parallel downloading of resources, as well as the chance that the users web browser already has the requested file in cache.
For example, I replaced the following from Views\Shared\_Root.cshtml
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui.min.js")" type="text/javascript"></script>
with
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
And you may find the following to work too for the ajax references:
<script src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js" type="text/javascript"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/MicrosoftMvcAjax.js" type="text/javascript"></script>
And the validation:
<script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js" type="text/javascript"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
Maybe these changes could find themselves in a future release of nopCommerce? (I'm using v2.30)
Hope this helps someone wanting to fine tune their performance!
EDIT: The file I didn't find on CDN was jquery.validate.min.js, not jquery.validate.unobtrusive.min.js as I first wrote.
EDIT2: Link to jquery.validate.min.js added above.