ICEfaces
  1. ICEfaces
  2. ICE-9640

Head Resource ordering does not place CSS before Javascript

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major 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&amp;stage=Development&amp;v=3_3_0_130829" type="text/javascript"></script>
              <link href="/app/javax.faces.resource/themes/sam/theme.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
              <script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
              <link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
              <script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
              <link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
              <script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&amp;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&amp;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&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
              <link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
              <link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&amp;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&amp;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&amp;stage=Development&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
              <script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&amp;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.


        Activity

        Philip Breau created issue -
        Philip Breau made changes -
        Field Original Value New Value
        Assignee Ken Fyten [ ken.fyten ]
        Philip Breau made changes -
        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>
            <title>#{msgs.title}</title>
            <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&amp;stage=Development&amp;v=3_3_0_130829" type="text/javascript"></script>
                <link href="/app/javax.faces.resource/themes/sam/theme.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
                <link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
                <link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&amp;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&amp;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&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&amp;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&amp;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&amp;stage=Development&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&amp;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.


        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&amp;stage=Development&amp;v=3_3_0_130829" type="text/javascript"></script>
                <link href="/app/javax.faces.resource/themes/sam/theme.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
                <link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
                <link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&amp;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&amp;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&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <link href="/app/javax.faces.resource/util/combined.css.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" rel="stylesheet" type="text/css" />
                <link href="/app/javax.faces.resource/core.css.jsf?ln=ice.core&amp;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&amp;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&amp;stage=Development&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/bridge.uncompressed.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/icepush.uncompressed.js.jsf?ln=ice.push&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/util/ace-jquery.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/icefaces-ee.js.jsf?ln=ice.core.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/head-update-test.js.jsf?ln=ice.core&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/mobi.js.jsf?ln=ice.push.ee&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/util/ace-components.uncompressed.js.jsf?ln=icefaces.ace&amp;v=3_3_0_130829" type="text/javascript"></script>
                <script src="/app/javax.faces.resource/component.js.jsf?ln=org.icefaces.component.util&amp;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.


        Hide
        Ken Fyten added a comment -

        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.

        Show
        Ken Fyten added a comment - 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.
        Ken Fyten made changes -
        Fix Version/s 3.4 [ 10770 ]
        Fix Version/s EE-3.3.0.GA_P02 [ 11371 ]
        Assignee Ken Fyten [ ken.fyten ] Mircea Toma [ mircea.toma ]
        Environment n/a ICEfaces 3.x
        Assignee Priority P1 [ 10010 ]
        Hide
        Ken Fyten added a comment -

        Attached Screen shot which shows the order of resources in the head after loading the showcase app. with coalescing=false.

        Show
        Ken Fyten added a comment - Attached Screen shot which shows the order of resources in the head after loading the showcase app. with coalescing=false.
        Ken Fyten made changes -
        Hide
        Ken Fyten added a comment -

        This issue was tackled for EE 3.3.0.GA in ICE-9225, but appears to still exist of have re-appeared since then.

        Show
        Ken Fyten added a comment - This issue was tackled for EE 3.3.0.GA in ICE-9225 , but appears to still exist of have re-appeared since then.
        Hide
        Mircea Toma added a comment -

        Modified ResourceOrdering handler to load the ordered CSS resources first, then the ordered JS resources to help improving the page load time.

        Show
        Mircea Toma added a comment - Modified ResourceOrdering handler to load the ordered CSS resources first, then the ordered JS resources to help improving the page load time.
        Mircea Toma made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Repository Revision Date User Message
        ICEsoft Public SVN Repository #38614 Thu Oct 17 07:10:12 MDT 2013 mircea.toma ICE-9640 Load the ordered CSS resources first, then the ordered JS resources to help improving the page load time.
        Files Changed
        Commit graph MODIFY /icefaces3/trunk/icefaces/core/src/main/java/org/icefaces/impl/event/ResourceOrdering.java
        Ken Fyten made changes -
        Resolution Fixed [ 1 ]
        Status Resolved [ 5 ] Reopened [ 4 ]
        Assignee Priority P1 [ 10010 ] P2 [ 10011 ]
        Hide
        Mircea Toma added a comment -

        Back-ported fix.

        Show
        Mircea Toma added a comment - Back-ported fix.
        Mircea Toma made changes -
        Status Reopened [ 4 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Ken Fyten made changes -
        Resolution Fixed [ 1 ]
        Status Resolved [ 5 ] Reopened [ 4 ]
        Mircea Toma made changes -
        Status Reopened [ 4 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Ken Fyten made changes -
        Fix Version/s 4.0 [ 11382 ]
        Ken Fyten made changes -
        Status Resolved [ 5 ] Closed [ 6 ]

          People

          • Assignee:
            Mircea Toma
            Reporter:
            Philip Breau
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: