ICEfaces
  1. ICEfaces
  2. ICE-5886

Add framework support for dynamically coalescing multiple .js/.css file resources into a single .js/.css request/response

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 3.3
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      Glimmer
    • Assignee Priority:
      P2
    • Affects:
      Documentation (User Guide, Ref. Guide, etc.), Compatibility/Configuration

      Description

      ISSUE: The current number of @ResourceDependency entries required for ACE-based components such as Slider is substantial, resulting in a large number of HTTP requests for a simple component, which can greatly increase page loading times.

        Issue Links

          Activity

          Hide
          Mark Collette added a comment -

          The name of resource should be consistent, and derived from the names of all the concatenated files, to maximise cachability.

          Show
          Mark Collette added a comment - The name of resource should be consistent, and derived from the names of all the concatenated files, to maximise cachability.
          Hide
          Ted Goddard added a comment -

          Note that an important feature of ICEfaces 1.8 is the deterministic JavaScript kernel: a fixed JavaScript library can be audited for security purposes and has reliable behavior across all applications. The current exceptions to this are found with two special purpose components: rich text editor and google maps.

          In ICEfaces 2.0, a similar strategy should be employed. A commonly used component library of approximately 200k should be determined and aggressively precompressed. This core dependency can be declared in the source code, greatly simplifying the component annotations.

          If additional libraries are necessary for less commonly used components, they can be dynamically loaded via the above strategy.

          Show
          Ted Goddard added a comment - Note that an important feature of ICEfaces 1.8 is the deterministic JavaScript kernel: a fixed JavaScript library can be audited for security purposes and has reliable behavior across all applications. The current exceptions to this are found with two special purpose components: rich text editor and google maps. In ICEfaces 2.0, a similar strategy should be employed. A commonly used component library of approximately 200k should be determined and aggressively precompressed. This core dependency can be declared in the source code, greatly simplifying the component annotations. If additional libraries are necessary for less commonly used components, they can be dynamically loaded via the above strategy.
          Hide
          Ted Goddard added a comment -

          Mark described an approach for avoiding the problem of loading these dynamically assembled JavaScript files multiple times:

          The user visits a page containing a calendar and a rich text component:

          http://localhost:8080/app/loadjs?calendar.js&richtext.js

          The user navigates to a page containing only a calendar (or hides the rich text component):

          http://localhost:8080/app/loadjs?calendar.js&richtext.js

          In other words, the URL for a given user must always be the union of all JavaScript files they have requested so far.

          Unfortunately, visiting the above pages in the opposite order results in a cache miss. It is likely preferable to statically declare the JavaScript required for a particular application. (Note that this could be automatically determined by pre-scanning the pages in the application.)

          Show
          Ted Goddard added a comment - Mark described an approach for avoiding the problem of loading these dynamically assembled JavaScript files multiple times: The user visits a page containing a calendar and a rich text component: http://localhost:8080/app/loadjs?calendar.js&richtext.js The user navigates to a page containing only a calendar (or hides the rich text component): http://localhost:8080/app/loadjs?calendar.js&richtext.js In other words, the URL for a given user must always be the union of all JavaScript files they have requested so far. Unfortunately, visiting the above pages in the opposite order results in a cache miss. It is likely preferable to statically declare the JavaScript required for a particular application. (Note that this could be automatically determined by pre-scanning the pages in the application.)
          Hide
          Mark Collette added a comment -

          Ok, now we're using the YUI loader, so our initial javascript file count is much lower. As well, we use @MandatoryResourceComponent and @ResourceDependency to load everything we could need, no matter if each particular component is on each page already, in case other components are added to the view on postback.

          So there is a fixed set of javascript that we initially load, that won't typically change. It should make a lot more sense serving those all out as a single file now. That could entail sending the core, compat, push and ace javascript all as one file, or it could entail just concatenating all the ace javascript, or doing it per library.

          Show
          Mark Collette added a comment - Ok, now we're using the YUI loader, so our initial javascript file count is much lower. As well, we use @MandatoryResourceComponent and @ResourceDependency to load everything we could need, no matter if each particular component is on each page already, in case other components are added to the view on postback. So there is a fixed set of javascript that we initially load, that won't typically change. It should make a lot more sense serving those all out as a single file now. That could entail sending the core, compat, push and ace javascript all as one file, or it could entail just concatenating all the ace javascript, or doing it per library.
          Hide
          Mark Collette added a comment -

          Might benefit from waiting until after ICE-6727 is done, as that will affect what we initially load.

          Show
          Mark Collette added a comment - Might benefit from waiting until after ICE-6727 is done, as that will affect what we initially load.
          Hide
          Mark Collette added a comment -

          This jira is about adding a mechanism to the framework to dynamically coalesce javascript resources. That might involve supporting combo urls, to integrate with the YUI loader, or it might involve detecting <script> tags in the head and automatically combining them. Either way, it's not specific to ACE, as it could operate on the framework javascript, and application javascript.

          Show
          Mark Collette added a comment - This jira is about adding a mechanism to the framework to dynamically coalesce javascript resources. That might involve supporting combo urls, to integrate with the YUI loader, or it might involve detecting <script> tags in the head and automatically combining them. Either way, it's not specific to ACE, as it could operate on the framework javascript, and application javascript.
          Hide
          Ken Fyten added a comment - - edited

          It would be great to have a new facility within ICEfaces that would provide automatic consolidation of multiple .js file requests into a single larger file request, resulting in greatly improved page load times. This feature could use a new custom annotation to mark which .js files should be loaded and are subject to consolidation. It could also be used by any ICEfaces application that wanted to leverage it.

          The way this could work is that each Get within ICEfaces for a complete page would result in a new .js file being generated for the page consisting of the consolidated .js files. Each partial-page update after that would keep the original file request (cached now) and if necessary (additional .js files added dynamically that weren't in the original page) generate another file for the newly added .js.

          was:
          ISSUE: The current number of @ResourceDependency entries required for YUI-based components such as Slider is very large, resulting in a large number of HTTP requests for a simple component, which can greatly increase page loading times.

          It would be great to have a new facility within ICEfaces that would provide automatic consolidation of multiple .js file requests into a single larger file request, resulting in greatly improved page load times. This feature could use a new custom annotation to mark which .js files should be loaded and are subject to consolidation. It could also be used by any ICEfaces application that wanted to leverage it.

          The way this could work is that each Get within ICEfaces for a complete page would result in a new .js file being generated for the page consisting of the consolidated .js files. Each partial-page update after that would keep the original file request (cached now) and if necessary (additional .js files added dynamically that weren't in the original page) generate another file for the newly added .js.

          Affects: Documentation (User Guide, Ref. Guide, etc.)

          Consider for 3.3.

          Show
          Ken Fyten added a comment - - edited It would be great to have a new facility within ICEfaces that would provide automatic consolidation of multiple .js file requests into a single larger file request, resulting in greatly improved page load times. This feature could use a new custom annotation to mark which .js files should be loaded and are subject to consolidation. It could also be used by any ICEfaces application that wanted to leverage it. The way this could work is that each Get within ICEfaces for a complete page would result in a new .js file being generated for the page consisting of the consolidated .js files. Each partial-page update after that would keep the original file request (cached now) and if necessary (additional .js files added dynamically that weren't in the original page) generate another file for the newly added .js. was: ISSUE: The current number of @ResourceDependency entries required for YUI-based components such as Slider is very large, resulting in a large number of HTTP requests for a simple component, which can greatly increase page loading times. It would be great to have a new facility within ICEfaces that would provide automatic consolidation of multiple .js file requests into a single larger file request, resulting in greatly improved page load times. This feature could use a new custom annotation to mark which .js files should be loaded and are subject to consolidation. It could also be used by any ICEfaces application that wanted to leverage it. The way this could work is that each Get within ICEfaces for a complete page would result in a new .js file being generated for the page consisting of the consolidated .js files. Each partial-page update after that would keep the original file request (cached now) and if necessary (additional .js files added dynamically that weren't in the original page) generate another file for the newly added .js. Affects: Documentation (User Guide, Ref. Guide, etc.) Consider for 3.3.
          Hide
          Migration added a comment -

          It would be great to have a new facility within ICEfaces that would provide automatic consolidation of multiple .js file requests into a single larger file request, resulting in greatly improved page load times. This feature could use a new custom annotation to mark which .js files should be loaded and are subject to consolidation. It could also be used by any ICEfaces application that wanted to leverage it.

          The way this could work is that each Get within ICEfaces for a complete page would result in a new .js file being generated for the page consisting of the consolidated .js files. Each partial-page update after that would keep the original file request (cached now) and if necessary (additional .js files added dynamically that weren't in the original page) generate another file for the newly added .js.

          was:
          ISSUE: The current number of @ResourceDependency entries required for YUI-based components such as Slider is very large, resulting in a large number of HTTP requests for a simple component, which can greatly increase page loading times.

          It would be great to have a new facility within ICEfaces that would provide automatic consolidation of multiple .js file requests into a single larger file request, resulting in greatly improved page load times. This feature could use a new custom annotation to mark which .js files should be loaded and are subject to consolidation. It could also be used by any ICEfaces application that wanted to leverage it.

          The way this could work is that each Get within ICEfaces for a complete page would result in a new .js file being generated for the page consisting of the consolidated .js files. Each partial-page update after that would keep the original file request (cached now) and if necessary (additional .js files added dynamically that weren't in the original page) generate another file for the newly added .js.

          Affects: Documentation (User Guide, Ref. Guide, etc.)

          Consider for 3.3.

          Show
          Migration added a comment - It would be great to have a new facility within ICEfaces that would provide automatic consolidation of multiple .js file requests into a single larger file request, resulting in greatly improved page load times. This feature could use a new custom annotation to mark which .js files should be loaded and are subject to consolidation. It could also be used by any ICEfaces application that wanted to leverage it. The way this could work is that each Get within ICEfaces for a complete page would result in a new .js file being generated for the page consisting of the consolidated .js files. Each partial-page update after that would keep the original file request (cached now) and if necessary (additional .js files added dynamically that weren't in the original page) generate another file for the newly added .js. was: ISSUE: The current number of @ResourceDependency entries required for YUI-based components such as Slider is very large, resulting in a large number of HTTP requests for a simple component, which can greatly increase page loading times. It would be great to have a new facility within ICEfaces that would provide automatic consolidation of multiple .js file requests into a single larger file request, resulting in greatly improved page load times. This feature could use a new custom annotation to mark which .js files should be loaded and are subject to consolidation. It could also be used by any ICEfaces application that wanted to leverage it. The way this could work is that each Get within ICEfaces for a complete page would result in a new .js file being generated for the page consisting of the consolidated .js files. Each partial-page update after that would keep the original file request (cached now) and if necessary (additional .js files added dynamically that weren't in the original page) generate another file for the newly added .js. Affects: Documentation (User Guide, Ref. Guide, etc.) Consider for 3.3.
          Hide
          Ken Fyten added a comment -

          Suggestion to statically combine the compat js files into a single resource file as they are generally used together:

          • javax.faces.resource/compat.uncompressed.js.jsf
          • javax.faces.resource/icefaces-compat.uncompressed.js.jsf

          Show
          Ken Fyten added a comment - Suggestion to statically combine the compat js files into a single resource file as they are generally used together: • javax.faces.resource/compat.uncompressed.js.jsf • javax.faces.resource/icefaces-compat.uncompressed.js.jsf
          Hide
          Mircea Toma added a comment - - edited

          Added first cut implementation for the resource coalescing feature. The ResourceCollector system events listener collects all the resources (js and css) added to the head, just after they were ordered by the ResourceOrdering system events listeners. Then it replaces these resources with just one resource component (coalesced.js or coalesced.css). The registered CoalescingResourceHandler will server a CoalescingResource resource implementation when coalesced.js or coalseced.css is requested. This resource will use the list with all the previously registered resources to dynamically build an InputStream that uses all the input stream from all the corresponding resources.

          Show
          Mircea Toma added a comment - - edited Added first cut implementation for the resource coalescing feature. The ResourceCollector system events listener collects all the resources (js and css) added to the head, just after they were ordered by the ResourceOrdering system events listeners. Then it replaces these resources with just one resource component (coalesced.js or coalesced.css). The registered CoalescingResourceHandler will server a CoalescingResource resource implementation when coalesced.js or coalseced.css is requested. This resource will use the list with all the previously registered resources to dynamically build an InputStream that uses all the input stream from all the corresponding resources.
          Hide
          Mircea Toma added a comment -

          Introduced org.icefaces.coalesceResource context parameter that can be used to enable/disable this feature. By default the featue is disabled (org.icefaces.coalesceResource=false).

          Show
          Mircea Toma added a comment - Introduced org.icefaces.coalesceResource context parameter that can be used to enable/disable this feature. By default the featue is disabled (org.icefaces.coalesceResource=false).
          Hide
          Mircea Toma added a comment -

          The hashcode is a digest of all the name and library strings of the resources used. So, if resources use don't change when session is restored then the URL won't change either.

          Show
          Mircea Toma added a comment - The hashcode is a digest of all the name and library strings of the resources used. So, if resources use don't change when session is restored then the URL won't change either.
          Hide
          Mircea Toma added a comment -

          Added detection of the servlet mapping. This is used by the resource implementation to build the request URL.

          Show
          Mircea Toma added a comment - Added detection of the servlet mapping. This is used by the resource implementation to build the request URL.
          Hide
          Mircea Toma added a comment -

          Modified GMapResourceHandler (ace and compat) to not cache content on server, instead modify request URL to point to external site. Modified CoalescingResourceHandler to skip the coalescing for resources that have absolute URLs.

          Show
          Mircea Toma added a comment - Modified GMapResourceHandler (ace and compat) to not cache content on server, instead modify request URL to point to external site. Modified CoalescingResourceHandler to skip the coalescing for resources that have absolute URLs.
          Hide
          Mircea Toma added a comment -

          Coalesce required resources only for the first GET request of the user session. Subsequent requests for pages that have additional resources will have their resources referenced seprarately from the coalesced ones.

          Show
          Mircea Toma added a comment - Coalesce required resources only for the first GET request of the user session. Subsequent requests for pages that have additional resources will have their resources referenced seprarately from the coalesced ones.
          Hide
          Mircea Toma added a comment -

          Coalesced CSS resources are referenced first in the head (before the JS coalesced resources).

          Show
          Mircea Toma added a comment - Coalesced CSS resources are referenced first in the head (before the JS coalesced resources).
          Hide
          Ken Fyten added a comment -

          Re-opened. This is working well in general now.

          However, I noticed that with...

          <context-param>
              <param-name>org.icefaces.coalesceResources</param-name>
              <param-value>true</param-value>
          </context-param>
          

          ...about half the time the ace:chart demo will not function in showcase. JS errors abound in this case. Seems strange as sometimes it will work, and others not. I'll attach a screenshot of the errors.

          Show
          Ken Fyten added a comment - Re-opened. This is working well in general now. However, I noticed that with... <context-param> <param-name>org.icefaces.coalesceResources</param-name> <param-value> true </param-value> </context-param> ...about half the time the ace:chart demo will not function in showcase. JS errors abound in this case. Seems strange as sometimes it will work, and others not. I'll attach a screenshot of the errors.
          Hide
          Ken Fyten added a comment -

          JS errors when chart doesn't function.

          Show
          Ken Fyten added a comment - JS errors when chart doesn't function.
          Hide
          Mircea Toma added a comment -

          The fix makes sure that the coalesced resource is always referenced before the resources that are added later on.

          Show
          Mircea Toma added a comment - The fix makes sure that the coalesced resource is always referenced before the resources that are added later on.
          Hide
          Ken Fyten added a comment -

          Enabled resource coalescing by default in the showcase sample application.

          svn commit -m "ICE-5886 - Enable resource coalescing by default in the showcase sample application." 1 packet
          [16:34:34] - Sending /Users/Ken/Code/svn/icefaces3-trunk/icefaces/samples/showcase/showcase/src/main/webapp/WEB-INF/web.xml
          [16:34:35] - Committed revision 34369.

          Show
          Ken Fyten added a comment - Enabled resource coalescing by default in the showcase sample application. svn commit -m " ICE-5886 - Enable resource coalescing by default in the showcase sample application." 1 packet [16:34:34] - Sending /Users/Ken/Code/svn/icefaces3-trunk/icefaces/samples/showcase/showcase/src/main/webapp/WEB-INF/web.xml [16:34:35] - Committed revision 34369.

            People

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

              Dates

              • Created:
                Updated:
                Resolved: