Reduce page load times by combining DocumentGraphics into one sprite
I'm not particular skilled at this but here's an example:
http://svidgen.com/sprites
Implementation Ideas
One way to do this would be to modify the
%ICON{}%
variable to output a modified img tag and add the appropriate css to the header. Some thing like:
%ICON{person}%
Would output
<img src='/pub/System/DocumentGraphics/placeholder.gif#person' alt='person' title='person' class='documentgraphicsprite person' />
and add the following to the header
<style type='text/css'>
. documentgraphicsprite {
width: 16px;
height: 16px;
background-image: url('/pub/System/DocumentGraphics/sprites.gif');
}
. documentgraphicsprite.person {
background-position: 0px 0px;
}
</style>
There would need to be some sort of conf settings mapping icon names to pixel-based coordinates on the background image.
Another way to do this would be to make a new plugin that did much the same thing with a different command. Perhaps %SPRITE{}%
--
DrewStevenson - 24 Dec 2009
SpritePlugin
Went ahead and sketched out a rough SpritePlugin and attached it. Relies on
FamFamFamContrib. Also included a
screenshot
--
DrewStevenson - 24 Dec 2009
Thanks for the idea, I just learned something new.
However, the page you reference lists two drawbacks ("when not to use this technique"):
- In the rare circumstance that your users need to be able to right-click on your image to save them [or] view their properties, this technique should not be used. -- Ok, this might not be that important
- This technique can also cause issues printing the page, as background-images (like sprites) are ignored by default in most browsers for printing purposes. -- But this sounds like a serious problem; even if we would disable sprites for the print skin, this (a) doesn't mean that nobody tries to 'print' another skin and (b) does mean that all images would have to be transferred twice in that case (on second thought, (b) might not be a showstopper either)
btw, did you by chance do some benchmarks? Aren't these images cached on the client side anyway (cf.
mod_expires
or the like)?
--
MarkusUeberall - 24 Dec 2009
Hi Drew,
I too thought CSS sprites would be a great idea (after profiling my wiki with YSlow! and having it suggest this technique to me). And actually, the
TinyMCE editor does this already for most of its toolbar graphics.
I had
this brief chat with
SvenDowideit about using CSS Sprites. As with the argument for compiling all our CSS and javascript files into one big blob, I get the impression that there is lower hanging fruit to optimise the end-user experience of foswiki (but then again, try telling that to users on PCs configured to clear their cache every time they close their browsers)...
The fact is the typical foswiki page view (and especially page edit) generates a gazillion HTTP requests (well, my site does anyway) and too often
mod_expires
is a band-aid that fails to hide this reality from my users.
So anyway, I'm very grateful for your experiments. If I were to pick this up and run with it, I would not generate the CSS dynamically in the header. It should be possible to compile all the CSS required for the entire doc graphics suite into one file in
/pub
. This will save on CPU time at the server and reduce bandwidth overhead for each page view.
On the other hand, unless you use Foswiki as a glorified CMS and you care greatly about first impression page view performance, when determining optimisation and usability priorities I will usually try to go for satisfying the regular contributors first, then the regular read-only users, and then casual/random users. Or to put this another way, I have found myself asking the question: "Are my efforts going to impact the users that I care about?". With CSS sprites, it's not a clear answer.
I will tell you something that I would find worthwhile though, probably more so than CSS sprites: I am reluctant to give my
mod_expires
apache config an aggressive expiry date too far into the future, because most of the CSS and JS in Foswiki is not versioned and the site is likely to look broken if people are hitting old files that have since been upgraded.
JQueryPlugin solves this by appending a
?version=x.y.z
to the URL of any CSS/Javascript file that those plugins fetch. If we had a similar facility for the rest of Foswiki, I think more Foswiki installations would feel comfortable with setting their expires headers to a very distant future date.
--
PaulHarvey - 24 Dec 2009
These are good concerns raised up above.
Absolutely agree that the final version should generate a css file in pub and use that although it would be good to have it regenerate it based on some change in the settings or plugin page.
With regard to right-clicking Firefox gives the option to 'view background image'.
The print view scenario is a dicier one.
As too performance gains and the intended audience: My primary use cases both involve significantly more viewers than contributors With regard to the most performance sensitive one (
http://systemstatus.umn.edu) I'm actually using the
BrowserBoosterPlugin along with aggressive caching via Varnish to get stellar performance out of Foswiki as an app platform but one of my sys admins noticed that there were still a lot of requests required to load any of the pages and we weren't really comfortable with the far future expire dates either.
Maybe it'll just end up being a special use-case plugin. Although it might also make an interesting config option to have ICON switch to "sprite mode"
--
DrewStevenson - 24 Dec 2009
A small but useful enhancement would be for the
ICON
tag to detect whether it is running in the context of the
print
skin/cover or not. That way it could decide the style of
img
tag to generate (ie, using sprites or hardlinked images). If the behavios is cleary documented, and users are encouraged to use the "print" button in a skin (which should add the
print
cover/skin), one of the dawbacks of the techique is removed.
Of course, this implies that the images must be shipped in the sprite and standalone form, which may be a drawback too.
--
RafaelAlvarez - 29 Dec 2009
I'm working on using Image Magick's montage tool to generate the sprite and map info automatically. Thus if
ImageMagick is present you get sprites and perhaps if
ImageMagick isn't present or you're in genpdf or print skin you get regular old img tags. Thoughts?
--
DrewStevenson - 11 Jan 2010
this dovetails well with my intention to change the
ICON
macro in 1.1 to use =tmpl='s and css as per
Tasks.Item2456 and
AddFamFamFamContribToCore. That way, enabling this optimization would effectively become a change in the skin path. Very Cool.
I do wonder how much this improves things, given the articles i recal reading a while ago about the size of the browser's in-memory image cache - in that its limited to a small number of files, and a relatively small size - given that it stores the images in uncompressed form.
--
SvenDowideit - 12 Jan 2010