Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: EE-3.3.0.GA_P01
-
Fix Version/s: 4.0.BETA, EE-3.3.0.GA_P02, 4.0
-
Component/s: Framework
-
Labels:None
-
Environment:ICEfaces 3.x
-
Assignee Priority:P2
Description
The ordering of CSS and Javascript in the head is currently a bit random. A common best practice in web development (http://uxmovement.com/content/why-you-should-place-style-sheets-before-scripts/) is to always place CSS before JavaScript. Manually doing so with the sample below shaved off 150ms for the total page load time. If CSS is loaded after Javascript, the page cannot start the rendering process until the js has finished loading. If the CSS is loaded before the javascript, the browser can start the rendering process before the javascript is finished loading. If we have a huge js file that's the last thing to finish loading, having the CSS load before could dramatically improve the perception of page performance. Users would still see the page loading until the js finished loading, although they would see the page render much more quickly.
A page loading compat, some ace components, and ICEmobile, such as the following:
<h:head>
<mobi:deviceResource theme="android_light"/>
<h:outputStylesheet name="css/custom.css"></h:outputStylesheet>
</h:head>
will generate the following HTML
This is the current ordering:
<head>
<script src="/app/javax.faces.resource/jsf.js.jsf?ln=javax.faces&stage=Development&v=3_3_0_130829" type="text/javascript"></script>
<link href="/app/javax.faces.resource/themes/sam/theme.css.jsf?ln=icefaces.ace&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&v=3_3_0_130829" type="text/javascript"></script>
<link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&v=3_3_0_130829" type="text/javascript"></script>
<link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&v=3_3_0_130829" type="text/javascript"></script>
<link href='/app/resources/images/favicon.ico' rel='icon' type='image/x-icon'/>
<link href='/app/resources/images/favicon.ico' rel='shortcut icon' type='image/x-icon'/>
<link href="/app/javax.faces.resource/android_light.css.jsf?ln=org.icefaces.component.skins&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<script type="text/javascript">document.documentElement.className = document.documentElement.className+' android_light ui-mobile desktop'; if (window.addEventListener) window.addEventListener('load', function() {document.body.className = 'ui-body-c';});</script>
<link href="/app/javax.faces.resource/css/fedex-mobi-theme.css.jsf?v=3_3_0_130829" rel="stylesheet" type="text/css" />
</head>
An efficient ordering would be the following:
<head>
<!-- ALL CSS FIRST -->
<link href="/app/javax.faces.resource/themes/sam/theme.css.jsf?ln=icefaces.ace&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<link href='/app/resources/images/favicon.ico' rel='icon' type='image/x-icon'/>
<link href='/app/resources/images/favicon.ico' rel='shortcut icon' type='image/x-icon'/>
<link href="/app/javax.faces.resource/android_light.css.jsf?ln=org.icefaces.component.skins&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<link href="/app/javax.faces.resource/css/fedex-mobi-theme.css.jsf?v=3_3_0_130829" rel="stylesheet" type="text/css" />
<!-- ALL JAVASCRIPT LAST -->
<script src="/app/javax.faces.resource/jsf.js.jsf?ln=javax.faces&stage=Development&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&v=3_3_0_130829" type="text/javascript"></script>
<script type="text/javascript">document.documentElement.className = document.documentElement.className+' android_light ui-mobile desktop'; if (window.addEventListener) window.addEventListener('load', function() {document.body.className = 'ui-body-c';});</script>
</head>
Note, that currently ICEmobile does not create JSF resources for CSS or JavaScript, so the ICEmobile resources may not be ordered efficiently before that is fixed (MOBI-700), although the standard JSF, Ace,and compat resource ordering could be improved.
A page loading compat, some ace components, and ICEmobile, such as the following:
<h:head>
<mobi:deviceResource theme="android_light"/>
<h:outputStylesheet name="css/custom.css"></h:outputStylesheet>
</h:head>
will generate the following HTML
This is the current ordering:
<head>
<script src="/app/javax.faces.resource/jsf.js.jsf?ln=javax.faces&stage=Development&v=3_3_0_130829" type="text/javascript"></script>
<link href="/app/javax.faces.resource/themes/sam/theme.css.jsf?ln=icefaces.ace&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&v=3_3_0_130829" type="text/javascript"></script>
<link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&v=3_3_0_130829" type="text/javascript"></script>
<link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&v=3_3_0_130829" type="text/javascript"></script>
<link href='/app/resources/images/favicon.ico' rel='icon' type='image/x-icon'/>
<link href='/app/resources/images/favicon.ico' rel='shortcut icon' type='image/x-icon'/>
<link href="/app/javax.faces.resource/android_light.css.jsf?ln=org.icefaces.component.skins&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<script type="text/javascript">document.documentElement.className = document.documentElement.className+' android_light ui-mobile desktop'; if (window.addEventListener) window.addEventListener('load', function() {document.body.className = 'ui-body-c';});</script>
<link href="/app/javax.faces.resource/css/fedex-mobi-theme.css.jsf?v=3_3_0_130829" rel="stylesheet" type="text/css" />
</head>
An efficient ordering would be the following:
<head>
<!-- ALL CSS FIRST -->
<link href="/app/javax.faces.resource/themes/sam/theme.css.jsf?ln=icefaces.ace&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<link href='/app/resources/images/favicon.ico' rel='icon' type='image/x-icon'/>
<link href='/app/resources/images/favicon.ico' rel='shortcut icon' type='image/x-icon'/>
<link href="/app/javax.faces.resource/android_light.css.jsf?ln=org.icefaces.component.skins&v=3_3_0_130829" rel="stylesheet" type="text/css" />
<link href="/app/javax.faces.resource/css/fedex-mobi-theme.css.jsf?v=3_3_0_130829" rel="stylesheet" type="text/css" />
<!-- ALL JAVASCRIPT LAST -->
<script src="/app/javax.faces.resource/jsf.js.jsf?ln=javax.faces&stage=Development&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&v=3_3_0_130829" type="text/javascript"></script>
<script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&v=3_3_0_130829" type="text/javascript"></script>
<script type="text/javascript">document.documentElement.className = document.documentElement.className+' android_light ui-mobile desktop'; if (window.addEventListener) window.addEventListener('load', function() {document.body.className = 'ui-body-c';});</script>
</head>
Note, that currently ICEmobile does not create JSF resources for CSS or JavaScript, so the ICEmobile resources may not be ordered efficiently before that is fixed (
Another observation is that when using latest icefaces3/trunk and the showcase sample application, the CSS loads first when resource-coalescing is enabled, but does not when coalescing=false. This seems to indicate a similar issue as the one reported by Philip in the description.