ICEfaces
  1. ICEfaces
  2. ICE-5576

ACE metadata static resource optimization

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-Alpha3
    • Fix Version/s: EE-3.2.0.GA, 3.3
    • Component/s: ACE-Components
    • Labels:
      None
    • Environment:
      ICEfaces 2
    • Affects:
      Documentation (User Guide, Ref. Guide, etc.)

      Description

      We need a way to declare static javascript and css dependencies in our component metadata.

      For example, in org.icefaces.component.slider.Slider we have this method called from the constructor:

          private void loadDependency(FacesContext context) {
              context.getViewRoot().addComponentResource(context, new UIOutput() {
                  public void encodeBegin(FacesContext context) throws IOException {
                      ResponseWriter writer = context.getResponseWriter();
                      writer.startElement("script", this);
                      writer.writeAttribute("type", "text/javascript", null);
                      writer.writeAttribute("src", "http://yui.yahooapis.com/3.0.0/build/yui/yui-min.js", null);
                      writer.endElement("script");
                  }
              }, "head");
          }

      Here we're manually coding a javascript dependency on http://yui.yahooapis.com/3.0.0/build/yui/yui-min.js which could be represented as an annotation on SliderMeta, and then this method could be generated in SliderBase.

      Above that, we use the new JSF 2.0 annotations for declaring resources to be served out of our own component JAR:

      @ResourceDependencies({
          @ResourceDependency(name="util.js",library="org.icefaces.component.util"),
          @ResourceDependency(name="yui3.js",library="org.icefaces.component.util"),
          @ResourceDependency(name="slider.js",library="org.icefaces.component.slider")
      })

      Again, it would be nice if we could specify some annotation on SliderMeta, which would then generate this code on SliderBase.

        Issue Links

          Activity

          Hide
          Ted Goddard added a comment -

          It may be possible for the component generator to scan the component annotations and produce a single unified .js file at compile time.

          Show
          Ted Goddard added a comment - It may be possible for the component generator to scan the component annotations and produce a single unified .js file at compile time.
          Hide
          Mark Collette added a comment -

          From the component team meeting today:

          1. Download yui dependencies locally, so don't use external resources
          2. Make sure multiple uses of a component is optimal in only having one link for each of its resources
          3. Add javascript coalescing, so that every javascript file is glommed together and served in a single GET

          Show
          Mark Collette added a comment - From the component team meeting today: 1. Download yui dependencies locally, so don't use external resources 2. Make sure multiple uses of a component is optimal in only having one link for each of its resources 3. Add javascript coalescing, so that every javascript file is glommed together and served in a single GET
          Hide
          Mark Collette added a comment - - edited

          1. The immediate focus of this work, should be to add functionality to the generator, such that @ResourceDependency annotations may be put on the Meta class itself, which will then be copied directly onto the generated Base class.

          Once this is done, it will be a simple matter to cut and paste the @ResourceDependency annotations, from the concrete component classes, into their respective Meta classes.

          2. Then, as a secondary objective, it would be nice to affect the JSF resource serving caching, so that if a javascript file is changed, the browser will know to fetch the new one. The existing stock JSF resource handling does not appear to achieve this. One suggestion, from Ted, was that during the build process, the generator could find the resource in question (not sure if we do the CSS smart sprite processing before of after compiling the Meta classes), and do a hash on them, and then use that as the version number, if no version number has been specified, in the generated @ResourceDependency annotation in the Base class.

          To see if this is feasible, we could make a javascript with an alert that says one word, and then change the word and rebuild and redeploy. Note that the old word still shows, since the browser cached the old file. Now, change the version number in the annotation, and rebuild and redeploy. If the browser starts showing the new word, then this technique could work.

          Show
          Mark Collette added a comment - - edited 1. The immediate focus of this work, should be to add functionality to the generator, such that @ResourceDependency annotations may be put on the Meta class itself, which will then be copied directly onto the generated Base class. Once this is done, it will be a simple matter to cut and paste the @ResourceDependency annotations, from the concrete component classes, into their respective Meta classes. 2. Then, as a secondary objective, it would be nice to affect the JSF resource serving caching, so that if a javascript file is changed, the browser will know to fetch the new one. The existing stock JSF resource handling does not appear to achieve this. One suggestion, from Ted, was that during the build process, the generator could find the resource in question (not sure if we do the CSS smart sprite processing before of after compiling the Meta classes), and do a hash on them, and then use that as the version number, if no version number has been specified, in the generated @ResourceDependency annotation in the Base class. To see if this is feasible, we could make a javascript with an alert that says one word, and then change the word and rebuild and redeploy. Note that the old word still shows, since the browser cached the old file. Now, change the version number in the annotation, and rebuild and redeploy. If the browser starts showing the new word, then this technique could work.
          Hide
          Arturo Zambrano added a comment -

          This is how the test was performed:

          I first added this annotation to the slider component...

          @ResourceDependency(name="test.js/1_0.js",library="org.icefaces.component.slider")

          ...the file contained the word "1" in the alert message.

          Then, I changed the word to "2", and rebuilt and redeployed, without clearing the browser's cache. When loading the page, the word was still "1".

          Then, I changed the annotation to...

          @ResourceDependency(name="test.js/2_0.js",library="org.icefaces.component.slider")

          ...and after rebuilding and redeploying, the word was finally "2".

          From Mark:

          """
          What you demonstrated was that if we change the contents of a resource, like generating new sprite image, or updating the css theme, or changing some javascript code, the JSF resource mechanism won't set the caching headers properly, so after the change the users' browser will continue using the old resources, without trying to download the newly modified ones. But, if we somehow change the URL, by altering the version number, then the browsers will see they don't have the new things cached, and will get it.

          So, the idea is, after compiling the Meta classes, but before (or while) generating the Base classes, to have a task that finds the local resources, referenced by @ResourceDependency annotations in the Meta class, and do a hash of them. Then, the resources can have some part of their path include that version number, which is derived from the hash. Bonus points if we can do this without actually moving any resource files into new directories, but that might be necessary. When the Base classes are generated, they will include the @ResourceDependency annotations, taken from the Meta classes, but with the hash altered paths.
          """

          Show
          Arturo Zambrano added a comment - This is how the test was performed: I first added this annotation to the slider component... @ResourceDependency(name="test.js/1_0.js",library="org.icefaces.component.slider") ...the file contained the word "1" in the alert message. Then, I changed the word to "2", and rebuilt and redeployed, without clearing the browser's cache. When loading the page, the word was still "1". Then, I changed the annotation to... @ResourceDependency(name="test.js/2_0.js",library="org.icefaces.component.slider") ...and after rebuilding and redeploying, the word was finally "2". From Mark: """ What you demonstrated was that if we change the contents of a resource, like generating new sprite image, or updating the css theme, or changing some javascript code, the JSF resource mechanism won't set the caching headers properly, so after the change the users' browser will continue using the old resources, without trying to download the newly modified ones. But, if we somehow change the URL, by altering the version number, then the browsers will see they don't have the new things cached, and will get it. So, the idea is, after compiling the Meta classes, but before (or while) generating the Base classes, to have a task that finds the local resources, referenced by @ResourceDependency annotations in the Meta class, and do a hash of them. Then, the resources can have some part of their path include that version number, which is derived from the hash. Bonus points if we can do this without actually moving any resource files into new directories, but that might be necessary. When the Base classes are generated, they will include the @ResourceDependency annotations, taken from the Meta classes, but with the hash altered paths. """
          Hide
          Ken Fyten added a comment -

          Not sure what needs to be done here, requires review.

          Show
          Ken Fyten added a comment - Not sure what needs to be done here, requires review.
          Hide
          Mark Collette added a comment - - edited

          The javascript coalescing has been spun off into ICE-5886 and ICE-6194.

          The resource versioning is what's left here. I believe that Art had prototyped this feature a while ago.

          Show
          Mark Collette added a comment - - edited The javascript coalescing has been spun off into ICE-5886 and ICE-6194 . The resource versioning is what's left here. I believe that Art had prototyped this feature a while ago.
          Hide
          Mark Collette added a comment -

          The last part of this, the resource versioning, was resolved with ICE-8666.

          Show
          Mark Collette added a comment - The last part of this, the resource versioning, was resolved with ICE-8666 .

            People

            • Assignee:
              Unassigned
              Reporter:
              Mark Collette
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: