When adding CSJS libraries to your XPage, try to use the defer or the async option for a better user experience. When not using this options, the Page might be blocked during page load.
Have a look at this example XPage which contains two external CSJS scripts (for demonstration purposes they are computed to get a remote script out of nowhere):
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
Foo!
<xp:this.resources>
<xp:script clientSide="true">
<xp:this.src>
<![CDATA[#{javascript:"http://" + @Unique() + ".null";}]]>
</xp:this.src>
</xp:script>
</xp:this.resources>
<xp:scriptBlock id="scriptBlock1">
<xp:this.src>
<![CDATA[#{javascript:"http://" + @Unique() + ".null";}]]>
</xp:this.src>
</xp:scriptBlock>
Bar!
</xp:view>
When opening the XPage, the DOM is blocked, until the operation times out:
The best you can do is to use the async or the defer option of external CSJS scripts. For script blocks, there is an option in the DDE available:
The async option can be set with an attribute:
<xp:this.attrs>
<xp:attr name="async" value="async" minimized="true" />
</xp:this.attrs>
To use the option for a resource, you must add them as an attribute for both options:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
Foo!
<xp:this.resources>
<xp:script clientSide="true">
<xp:this.src>
<![CDATA[#{javascript:"http://" + @Unique() + ".null";}]]>
</xp:this.src>
<xp:this.attrs>
<xp:attr name="async" value="async" minimized="true" />
</xp:this.attrs>
</xp:script>
</xp:this.resources>
<xp:scriptBlock id="scriptBlock1" defer="true">
<xp:this.src>
<![CDATA[#{javascript:"http://" + @Unique() + ".null";}]]>
</xp:this.src>
</xp:scriptBlock>
Bar!
</xp:view>
There are some other techniques, but this is the simplest way and supported in most browsers:
Very nice post Sven.
Another technique is to place all of your JavaScript libraries at the bottom of the page (not the top). Just make sure you do not try and invoke any of them ($ is undefined) before they are loaded.