Loading Resources via Themes
Thu Apr 10 13:36:51 EDT 2014
In today's TLCC XPages webinar, Marky Roden had a great presentation discussing resources and design definitions to help speed up Designer. If you didn't catch it live, it's worth tracking it down when it's available.
I'd like to build on what he was talking about a bit by explaining how to use themes to load resources in a way that also prevents Designer slowdown while having the secondary benefit of being clean design (with some caveats that I'll get into).
If you're not familiar with themes, they're the oddball XML design element introduced alongside XPages, and they serve a number of purposes. One of them, which Tim Tripcony explained well is that you can use them to set properties of your XPages controls - so if you want to, say, apply the CSS class of "btn" to all buttons, you can use a Theme to do that instead of writing it into every <xp:button/> control. They can also be used, though, to load resources in much the same way as you do on an XPage or Custom Control directly. The default theme you get includes some comments that point in this direction, but they use the horrible multi-line syntax. It turns out that you can use a shorter syntax that mirrors the normal XSP markup. Say you have a resource section like this:
<xp:this.resources> <xp:styleSheet href="/style.css"/> <xp:styleSheet href="/fixes.css"/> <xp:styleSheet href="/ieonly.css" rendered="#{context.userAgent.IE}"/> <xp:dojoModule name="dojo.behavior"/> <xp:script src="/behavior.js" clientSide="true"/> <xp:metaData name="viewport" content="width=device-width, initial-scale=1.0"/> <xp:linkResource href="#{facesContext.externalContext.requestContextPath}/feed.xml" rel="alternate" type="application/rss.xml" title="RSS Feed"/> </xp:this.resources>
To convert that to theme syntax, you just chop off all the "xp:" and "this." bits:
<theme extends="webstandard"> <resources> <styleSheet href="/style.css"/> <styleSheet href="/fixes.css"/> <styleSheet href="/ieonly.css" rendered="#{context.userAgent.IE}"/> <dojoModule name="dojo.behavior"/> <script src="/behavior.js" clientSide="true"/> <metaData name="viewport" content="width=device-width, initial-scale=1.0"/> <linkResource href="#{facesContext.externalContext.requestContextPath}/feed.xml" rel="alternate" type="application/rss.xml" title="RSS Feed"/> </resources> </theme>
Once you apply that to your app in the Xsp Properties, it will be as if you included the resources on the XPage directly, but you avoid the Designer slowdown problem and the XSP load time itself will be (imperceptably) faster. As an important bonus, it separates the concerns nicely: the theme's job is to handle describing the client-only stuff, and accordingly you get to delete some code from your XPages. One less thing to worry about during normal development.
Now, as I mentioned, there are some caveats, and themes are not appropriate in all cases.
- Most importantly, the resources loaded by themes are not available during programmatic page load. This is not normally a big deal, since the page loading doesn't care about CSS files or client JavaScript anyway, but it DOES matter for two types particularly: SSJS libraries and property bundles. If you have code that needs to access them during initial processing (either in ${}-bound properties or in places like before/afterPageLoad events), you should include them on the XPage directly.
- There's no good UI for modifying themes. You kind of have to just know how they work. I believe there's a thorough treatment in Mastering XPages, but other than that you're on your own until you learn.
- Since Designer doesn't load them, it also doesn't help you when specifying style classes. If you're in the habit of using the "Style" properties pane to pick classes from linked stylesheets, this will break that.
But even with those caveats in mind, I'm a huge fan of themes (for this and other uses) and use them constantly. The code cleanliness, performance improvements, and structural advantages are well worth the caveats.