Tapestry 5
  1. Tapestry 5
  2. TAP5-73

JavaScript libraries should be automatically packed/minimalized

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 5.0.15
    • Fix Version/s: 5.3
    • Component/s: None
    • Labels:
      None

      Description

      Tapestry should catch downloads of JavaScript libraries, and should "pack" the JavaScript ... remove comments and unecessary whitespace. I believe Dojo has a library to do this, it may even shorten variable names .

      A smart implementation of this would manage to cache the compressed JS, and notice when the uncompressed version changed.

        Issue Links

          Activity

          Howard M. Lewis Ship created issue -
          Show
          Jérôme BERNARD added a comment - This page might help: http://getahead.org/blog/joe/2005/07/22/javascript_who_wants_a_compression_utility.html You've got JSMin ( http://www.crockford.com/javascript/jsmin.html – AS IS licence) Java translation at: http://inconspicuous.org/projects/jsmin/JSMin.java
          Howard M. Lewis Ship made changes -
          Field Original Value New Value
          Fix Version/s 5.1 [ 12312964 ]
          Hide
          Martin Strand added a comment -

          Yahoo's compressor works great, is very efficient, and can also compress css:
          http://developer.yahoo.com/yui/compressor/

          The js/css files bundled with Tapestry can be compressed at build time if you use this Maven plugin:
          http://alchim.sourceforge.net/yuicompressor-maven-plugin/

          Show
          Martin Strand added a comment - Yahoo's compressor works great, is very efficient, and can also compress css: http://developer.yahoo.com/yui/compressor/ The js/css files bundled with Tapestry can be compressed at build time if you use this Maven plugin: http://alchim.sourceforge.net/yuicompressor-maven-plugin/
          Hide
          Ville Virtanen added a comment -

          Files bundled with Tapestry should be compressed at build time imho.

          I personally don't want T5 to consume any precious cpu cycles compressing and concatenating files during runtime or consume memory caching those, as it can be easily achieved using build time tools. Hence, please make this configurable.

          I recommed packing files bundled with T5 build time. There should be a configuration symbol to decide whether to use packed or non-packed files though (Both should be part of distribution.).

          That, and add packing to be part of maven quick start should be enough.

          I've used yui for my projects without single problem. (Although my js doesn't compare to dojo etc. at any level.)

          Show
          Ville Virtanen added a comment - Files bundled with Tapestry should be compressed at build time imho. I personally don't want T5 to consume any precious cpu cycles compressing and concatenating files during runtime or consume memory caching those, as it can be easily achieved using build time tools. Hence, please make this configurable. I recommed packing files bundled with T5 build time. There should be a configuration symbol to decide whether to use packed or non-packed files though (Both should be part of distribution.). That, and add packing to be part of maven quick start should be enough. I've used yui for my projects without single problem. (Although my js doesn't compare to dojo etc. at any level.)
          Hugo Palma made changes -
          Link This issue is duplicated by TAPESTRY-2628 [ TAPESTRY-2628 ]
          Howard M. Lewis Ship made changes -
          Project Tapestry [ 10573 ] Tapestry 5 [ 12310833 ]
          Affects Version/s 5.0.5 [ 12312477 ]
          Component/s tapestry-core [ 12311285 ]
          Key TAPESTRY-1792 TAP5-73
          Issue Type New Feature [ 2 ] Bug [ 1 ]
          Fix Version/s 5.1 [ 12312964 ]
          Howard M. Lewis Ship made changes -
          Affects Version/s 5.0.15 [ 12313429 ]
          Hide
          Howard M. Lewis Ship added a comment -

          The tricky part is determining which JS have been loaded on the client side, and only loading what is needed in a later Ajax update.

          Show
          Howard M. Lewis Ship added a comment - The tricky part is determining which JS have been loaded on the client side, and only loading what is needed in a later Ajax update.
          Howard M. Lewis Ship made changes -
          Issue Type Bug [ 1 ] New Feature [ 2 ]
          Hide
          Andreas Andreou added a comment -

          I'd suggest https://jawr.dev.java.net/

          It does its work @ server startup and I guess it'd need a small service written for it in order to be usable from within
          Tapestry, but i believe it has good potential...

          Additionally, for ppl who want the same functionality at build time (like i did recently) there's a maven
          plugin I did at http://github.com/andyhot/maven-jawr-plugin/

          Show
          Andreas Andreou added a comment - I'd suggest https://jawr.dev.java.net/ It does its work @ server startup and I guess it'd need a small service written for it in order to be usable from within Tapestry, but i believe it has good potential... Additionally, for ppl who want the same functionality at build time (like i did recently) there's a maven plugin I did at http://github.com/andyhot/maven-jawr-plugin/
          Hide
          Martin Reurings added a comment -

          A built-in feature set such as this has the potential of a negative effect on real high-performance websites:

          • Packing Javascripts may cause scripts that could have been cached client-side to get reloaded numerous times.
          • Packing Javascripts may cause unneeded Javascript to get sent (and parsed) numerous times
          • If T5 stays responsible for supplying what are essentially 'static' files these cannot be served from a different server, which allows caching and could have a different bandwidth allowance (this is already a problem and would get even worse).
          • Packed/Compressed Javascripts are almost impossible to debug properly.

          I'm quite certainly missing some more negative side-effects, but these feel likel enough to make my point. Features like these are great to have in a framework, but must be disabled by default, in my humble opinion. Also, I have to agree with some of the previous posters in stating, this should be fixed at build-time not take CPU and memory at run-time.

          Show
          Martin Reurings added a comment - A built-in feature set such as this has the potential of a negative effect on real high-performance websites: Packing Javascripts may cause scripts that could have been cached client-side to get reloaded numerous times. Packing Javascripts may cause unneeded Javascript to get sent (and parsed) numerous times If T5 stays responsible for supplying what are essentially 'static' files these cannot be served from a different server, which allows caching and could have a different bandwidth allowance (this is already a problem and would get even worse). Packed/Compressed Javascripts are almost impossible to debug properly. I'm quite certainly missing some more negative side-effects, but these feel likel enough to make my point. Features like these are great to have in a framework, but must be disabled by default, in my humble opinion. Also, I have to agree with some of the previous posters in stating, this should be fixed at build-time not take CPU and memory at run-time.
          Hide
          Howard M. Lewis Ship added a comment -

          Like any other performance issue, it is necessary to measure.

          I will be implementing this such that the level of packed/minimilzed & combined is controllable via a symbol contribution.

          The packed/gzipped/combined JSs will have far future expiration dates which should help the client-side to cache.

          My prediction is that a typical site will have very similar JS requirements page-to-page and will therefore see a net improvement here.

          Show
          Howard M. Lewis Ship added a comment - Like any other performance issue, it is necessary to measure. I will be implementing this such that the level of packed/minimilzed & combined is controllable via a symbol contribution. The packed/gzipped/combined JSs will have far future expiration dates which should help the client-side to cache. My prediction is that a typical site will have very similar JS requirements page-to-page and will therefore see a net improvement here.
          Hide
          Martin Reurings added a comment -

          Much more important than how far in the future the cache date is, what will the uri of the resource be? If every page will have a unique uri for its' combined Javascripts the client will suddenly have to download prototype, scriptaculous and tapestry js-files for every page instead of just once for the entire application.

          I suppose I'm just very paranoid about the possible pitfalls and I'll just have to see what you come up with

          Show
          Martin Reurings added a comment - Much more important than how far in the future the cache date is, what will the uri of the resource be? If every page will have a unique uri for its' combined Javascripts the client will suddenly have to download prototype, scriptaculous and tapestry js-files for every page instead of just once for the entire application. I suppose I'm just very paranoid about the possible pitfalls and I'll just have to see what you come up with
          Hide
          Jordi Hernandez Sellés added a comment - - edited

          I'd love to see Jawr used by Tapestry, so I thought you might want more info before you rolled your own solution.
          First and foremost, Jawr is built with framework integration in mind. This means that you don't need to force users to learn how to use any new tool, but rather you can just use it behind the scenes.
          There is some specific documentation on the subject at https://jawr.dev.java.net/integration/augmenter.html. You can get a general idea there, but integration possibilities go beyond what is explained there. For instance, the tag library delegates in tag-agnostic renderers. I made a facelets tag library out of these and each tag is almost a one-liner. I'm willing to help out with this if you want.

          Now, Martin's concerns are all valid and should be accounted for. Jawr has out of the box solutions for these issues:

          Q: may cause scripts that could have been cached client-side to get reloaded numerous times
          A: etag and expires headers are added to responses. Also, Jawr returns 304 (not modified) header and empty response body when if-modified-since or if-none-match header is present in a request.

          Q: may cause unneeded Javascript to get sent (and parsed) numerous times
          A: Jawr keeps a list of all script/css tags added to a page so repeats can't happen. Other than that, being careful to not repeat content in a script/css bundle avoids this.

          Q: 'static' files cannot be served from a different server, which allows caching and could have a different bandwidth allowance (this is already a problem and would get even worse).
          A: Jawr has production and developer modes. It is possible to set a domain name to prefix all urls in production mode. you can do all your development using your local files, then deploy to production and point them to a CDN automatically.

          Q: Packed/Compressed Javascripts are almost impossible to debug properly.
          A: Again, there is a development mode. All members of a pack are included separately and uncompressed, so it's very easy to debug. Change a flag, and you get the packed version.

          Q:Much more important than how far in the future the cache date is, what will the uri of the resource be?
          A: Each URI in Jawr has a 'version hash' part that depends on the actual bundle contents. It only changes when content does, so dont' worry, users get each script once and only once. And when a new version comes out, the URL changes so none of them run on outdated scripts.

          By the way, both JSmin and the YUI compressor are supported. And there's a cool i18n feature that generates javascript literals from resource bundle properties files.
          You can get more ideas at the features list page at https://jawr.dev.java.net/features.html.
          I'll help as I said, if you need me to. And if you'd still rather go on and roll your solution, best luck.

          Regards to all,
          Jordi.

          Show
          Jordi Hernandez Sellés added a comment - - edited I'd love to see Jawr used by Tapestry, so I thought you might want more info before you rolled your own solution. First and foremost, Jawr is built with framework integration in mind. This means that you don't need to force users to learn how to use any new tool, but rather you can just use it behind the scenes. There is some specific documentation on the subject at https://jawr.dev.java.net/integration/augmenter.html . You can get a general idea there, but integration possibilities go beyond what is explained there. For instance, the tag library delegates in tag-agnostic renderers. I made a facelets tag library out of these and each tag is almost a one-liner. I'm willing to help out with this if you want. Now, Martin's concerns are all valid and should be accounted for. Jawr has out of the box solutions for these issues: Q: may cause scripts that could have been cached client-side to get reloaded numerous times A: etag and expires headers are added to responses. Also, Jawr returns 304 (not modified) header and empty response body when if-modified-since or if-none-match header is present in a request. Q: may cause unneeded Javascript to get sent (and parsed) numerous times A: Jawr keeps a list of all script/css tags added to a page so repeats can't happen. Other than that, being careful to not repeat content in a script/css bundle avoids this. Q: 'static' files cannot be served from a different server, which allows caching and could have a different bandwidth allowance (this is already a problem and would get even worse). A: Jawr has production and developer modes. It is possible to set a domain name to prefix all urls in production mode. you can do all your development using your local files, then deploy to production and point them to a CDN automatically. Q: Packed/Compressed Javascripts are almost impossible to debug properly. A: Again, there is a development mode. All members of a pack are included separately and uncompressed, so it's very easy to debug. Change a flag, and you get the packed version. Q:Much more important than how far in the future the cache date is, what will the uri of the resource be? A: Each URI in Jawr has a 'version hash' part that depends on the actual bundle contents. It only changes when content does, so dont' worry, users get each script once and only once. And when a new version comes out, the URL changes so none of them run on outdated scripts. By the way, both JSmin and the YUI compressor are supported. And there's a cool i18n feature that generates javascript literals from resource bundle properties files. You can get more ideas at the features list page at https://jawr.dev.java.net/features.html . I'll help as I said, if you need me to. And if you'd still rather go on and roll your solution, best luck. Regards to all, Jordi.
          Howard M. Lewis Ship made changes -
          Assignee Howard M. Lewis Ship [ hlship ]
          Howard M. Lewis Ship made changes -
          Assignee Howard M. Lewis Ship [ hlship ]
          Hide
          Joshua Long added a comment -

          I'm pleased that some of these changes came through in Tapestry 5.1, but it seems like it's not quite enough to fill the gap. For me the goal is to make the YSlow plugin and the Google Page Speed plugin absolutely just purr on the pages I create. I understand the dynamic behavior of Tapestry does complicate things a little, but I think its surmountable. And, in fact, Tapestry's already halfway there.

          The way JAWR works is that on application startup time, it looks in different directories and creates a cached minified asset for all the bundles/js/css it finds. These various artifacts are never recreated. With Tapestry, this is slightly more complicated because you don't really have an efficient way of resolving all the JavaScript files since Tapestry's kind/smart enough to load from the classpath at runtime. Even if you think about applying this technique to all js files that are registered via @IncludeJavaScript, you then have to worry about the dynamically added JS from the renderSupport and so on. Several different solutions come to mind:

          • could tapestry also support the notion of a JAWR bundle in the @IncludeJavaScript annotation? These bundles would be arbitrary names. Heck, since theyre just names, those bundles might be overridable by clients too using TapestryIOC or something. This would be another way to solve the issue of having to "undo" the Tapestry default CSS or Client side validation: just override / replace the bundle. in your own specific JAWR configuration.
          • if a resource is so important, surely its not too much to ask the user to enumerate them as bundles?

          Perhaps there be several 'layers' of support. Debug would be: just write out each and every css/js file. production defaults would be: all Tapestry shipped CSS/JS code is minified/compressed using JAWR, but userland components dont benefit from it unless they opt in. Opting in mean having components use the idea of a bundle instead of a regular js file. Additionally, JAWR is smart enough to intercept requests for standard JS links and return the minified version instead. This would mean 3rd party components that don't use the bundle structure but that do use CSS/JS could still have their assets compressed using this system. For those components that Tapestry doesn't know about at startup time (for example, in a third party component that loads the js at runtime), perhaps there could be a setting to, on the fly, cache/minify/gzip these files and then return subsequent requests for them with the cached version? This, also would be opt-in. I dont know at what granularity this mechanism is supported. The above posts mention the concern of tapestry creating a separate js/css bundle that forces the redownload of prototype/blackbird/etc on each page, and i agree thats valid. So perhaps if the user has opted in, but the js is in a third party component thats not using a bundle name, then for those js files (not the sum collection of js from that component, but for each individual one) we just return the js/css file minified/compressed but dont serve up all the js/css as a group.

          Put another way, my ideal setup, assuming ive enabled every optimisation Tapestry provides:

          • My code and any third party components deal in bundle names, which means that a third party component may load 10 js files, but I only pay the price of loading one gzipped/minified file for the component. Code using bundles would benefit from one-time compilation of the bundles at startup via a JAWR-like config option for tapestry.
          • Any code that doesnt deal in terms of bundles is still gzipped, minified, but it manifests as as many includes as required, ie: i'd still have 10 js script tags, but theyre individually packed. code using explicit js/css references would be served up dynamically, but all subsequent, like requests would be served from the cached version.

          Personally, I like the idea of an opt-in system with tapestry stuff JAWR'd by default and then, in my pages/components, I have the ability to pass bundle names around to the createScriptLink and @IncludeJavaScript annotations. I don't use third party components (not yet, anyway) but just being able to consolidate /gzip all MY stuff (5 js files and 6 css files, one of each of which is designed to undo the Tapestry defaults) would be a huge win.

          All of this is meant to be equally applicable to CSS as well as JS, since CSS is as integral a part of a components 'package' as JS, in my view. This is part and parcel with why I love Tapestry: the ability to componentize common look and feels, behaviors and so on helps me scale the site out. Being able to carry forward the CSS is vital.

          Show
          Joshua Long added a comment - I'm pleased that some of these changes came through in Tapestry 5.1, but it seems like it's not quite enough to fill the gap. For me the goal is to make the YSlow plugin and the Google Page Speed plugin absolutely just purr on the pages I create. I understand the dynamic behavior of Tapestry does complicate things a little, but I think its surmountable. And, in fact, Tapestry's already halfway there. The way JAWR works is that on application startup time, it looks in different directories and creates a cached minified asset for all the bundles/js/css it finds. These various artifacts are never recreated. With Tapestry, this is slightly more complicated because you don't really have an efficient way of resolving all the JavaScript files since Tapestry's kind/smart enough to load from the classpath at runtime. Even if you think about applying this technique to all js files that are registered via @IncludeJavaScript, you then have to worry about the dynamically added JS from the renderSupport and so on. Several different solutions come to mind: could tapestry also support the notion of a JAWR bundle in the @IncludeJavaScript annotation? These bundles would be arbitrary names. Heck, since theyre just names, those bundles might be overridable by clients too using TapestryIOC or something. This would be another way to solve the issue of having to "undo" the Tapestry default CSS or Client side validation: just override / replace the bundle. in your own specific JAWR configuration. if a resource is so important, surely its not too much to ask the user to enumerate them as bundles? Perhaps there be several 'layers' of support. Debug would be: just write out each and every css/js file. production defaults would be: all Tapestry shipped CSS/JS code is minified/compressed using JAWR, but userland components dont benefit from it unless they opt in. Opting in mean having components use the idea of a bundle instead of a regular js file. Additionally, JAWR is smart enough to intercept requests for standard JS links and return the minified version instead. This would mean 3rd party components that don't use the bundle structure but that do use CSS/JS could still have their assets compressed using this system. For those components that Tapestry doesn't know about at startup time (for example, in a third party component that loads the js at runtime), perhaps there could be a setting to, on the fly, cache/minify/gzip these files and then return subsequent requests for them with the cached version? This, also would be opt-in. I dont know at what granularity this mechanism is supported. The above posts mention the concern of tapestry creating a separate js/css bundle that forces the redownload of prototype/blackbird/etc on each page, and i agree thats valid. So perhaps if the user has opted in, but the js is in a third party component thats not using a bundle name, then for those js files (not the sum collection of js from that component, but for each individual one) we just return the js/css file minified/compressed but dont serve up all the js/css as a group. Put another way, my ideal setup, assuming ive enabled every optimisation Tapestry provides: My code and any third party components deal in bundle names, which means that a third party component may load 10 js files, but I only pay the price of loading one gzipped/minified file for the component. Code using bundles would benefit from one-time compilation of the bundles at startup via a JAWR-like config option for tapestry. Any code that doesnt deal in terms of bundles is still gzipped, minified, but it manifests as as many includes as required, ie: i'd still have 10 js script tags, but theyre individually packed. code using explicit js/css references would be served up dynamically, but all subsequent, like requests would be served from the cached version. Personally, I like the idea of an opt-in system with tapestry stuff JAWR'd by default and then, in my pages/components, I have the ability to pass bundle names around to the createScriptLink and @IncludeJavaScript annotations. I don't use third party components (not yet, anyway) but just being able to consolidate /gzip all MY stuff (5 js files and 6 css files, one of each of which is designed to undo the Tapestry defaults) would be a huge win. All of this is meant to be equally applicable to CSS as well as JS, since CSS is as integral a part of a components 'package' as JS, in my view. This is part and parcel with why I love Tapestry: the ability to componentize common look and feels, behaviors and so on helps me scale the site out. Being able to carry forward the CSS is vital.
          Hide
          Thiago H. de Paula Figueiredo added a comment -

          Tapestry 5.1.0.5 (don't know about previous 5.1.0.x versions) already combines all the external (not inline) Javascript files when the symbol SymbolConstants.COMBINE_SCRIPTS is set to true (default value: the same as SymbolConstants.PRODUCTION_MODE, which has true as default). Therefore, IMHO, we don't need Javascript bundles nor JAWR, just the minification of Javascript files.

          By the way, after GZipping combined Javascript files, do we still need to minify them?

          I've just opened https://issues.apache.org/jira/browse/TAP5-741 to provide packing/minification for CSS files too.

          Support for JAWR bundles in @IncludeJavaScript doesn't need any modifications to Tapestry: just add another binding that provides the correct URL for that given JAWR bundle.

          Show
          Thiago H. de Paula Figueiredo added a comment - Tapestry 5.1.0.5 (don't know about previous 5.1.0.x versions) already combines all the external (not inline) Javascript files when the symbol SymbolConstants.COMBINE_SCRIPTS is set to true (default value: the same as SymbolConstants.PRODUCTION_MODE, which has true as default). Therefore, IMHO, we don't need Javascript bundles nor JAWR, just the minification of Javascript files. By the way, after GZipping combined Javascript files, do we still need to minify them? I've just opened https://issues.apache.org/jira/browse/TAP5-741 to provide packing/minification for CSS files too. Support for JAWR bundles in @IncludeJavaScript doesn't need any modifications to Tapestry: just add another binding that provides the correct URL for that given JAWR bundle.
          Hide
          Joshua Long added a comment -

          You don't, in theory, need the minification after compression. The only case I can think of otherwise are the few browsers that dont support gzip (I know JAWR mentions in its documentation certain versions of IE6 as not supporting gzip, and thus requiring a separate non-gzipped bundle thats made available.)

          And yes, combining/minifying CSS would be wonderful. My question is: how does Tapestry combine and expose them as a URL? Is the URL constantly hashed? IE, if I use prototype and a calendar javascript on 10 pages, is the url generated by Tapestry the same? What about if I use prototype, a calendar javascript on 9 pages but on the 10th, I decide to also jQuery. Do I, on this page, have to download prototype and the calendar widget again because the URL has changed for the combined .js? This would defeat the purpose of the caching. In this case it would be ideal to be able to force Tapestry to emit two script tags (yes, that implies two HTTP requests for associated js scripts for the page, but at least the client isn't forced to download a whole half megabyte of JavaScript per page...)

          Show
          Joshua Long added a comment - You don't, in theory, need the minification after compression. The only case I can think of otherwise are the few browsers that dont support gzip (I know JAWR mentions in its documentation certain versions of IE6 as not supporting gzip, and thus requiring a separate non-gzipped bundle thats made available.) And yes, combining/minifying CSS would be wonderful. My question is: how does Tapestry combine and expose them as a URL? Is the URL constantly hashed? IE, if I use prototype and a calendar javascript on 10 pages, is the url generated by Tapestry the same? What about if I use prototype, a calendar javascript on 9 pages but on the 10th, I decide to also jQuery. Do I, on this page, have to download prototype and the calendar widget again because the URL has changed for the combined .js? This would defeat the purpose of the caching. In this case it would be ideal to be able to force Tapestry to emit two script tags (yes, that implies two HTTP requests for associated js scripts for the page, but at least the client isn't forced to download a whole half megabyte of JavaScript per page...)
          Hide
          Thiago H. de Paula Figueiredo added a comment -

          From http://tapestry.apache.org/tapestry5.1/guide/ajax.html

          "Combining Scripts

          In production mode, Tapestry automatically combines JavaScript libraries. A single request (for a virtual asset) will retrieve the combined content of all referenced JavaScript library files. This is a very useful feature, as it reduces the number of requests needed to present a page to the user. As elsewhere, if the client browser supports gzip compression, the combined JavaScript will be compressed."

          I have just tested two different pages that use the same set of Javascript files and they received the same URL: http://domainassets/virtual/H4sIAAAAAAAAAIXNQQrCMBCF4XGhXkREhE500QNN41SqlYS86aKeyat5B4mQgJu6$002ffl47$002fWm9ZNotSWiDR2dAGpw8GmIJn4awwTX8plP3LqYggWbo$002fINxMv2p2Z$002fWPba9$002brtK3dFmkSFpbmiErLaF9WN4u$002fdkC6V1ZJd83eteSggV83nHzax7d8QAQAA.js. I'm not 100% sure, but I think Tapestry, for each requests, checks what Javascript files were included. Then it checks if this file list was already combined into a single one: if not, it does the combining in the spot and sets a far-future expire header on it (for caching). If some of the included Javascript files is changed, then it does the combination again.

          You can also run tests yourself and take a look at the sources.

          Show
          Thiago H. de Paula Figueiredo added a comment - From http://tapestry.apache.org/tapestry5.1/guide/ajax.html "Combining Scripts In production mode, Tapestry automatically combines JavaScript libraries. A single request (for a virtual asset) will retrieve the combined content of all referenced JavaScript library files. This is a very useful feature, as it reduces the number of requests needed to present a page to the user. As elsewhere, if the client browser supports gzip compression, the combined JavaScript will be compressed." I have just tested two different pages that use the same set of Javascript files and they received the same URL: http://domainassets/virtual/H4sIAAAAAAAAAIXNQQrCMBCF4XGhXkREhE500QNN41SqlYS86aKeyat5B4mQgJu6$002ffl47$002fWm9ZNotSWiDR2dAGpw8GmIJn4awwTX8plP3LqYggWbo$002fINxMv2p2Z$002fWPba9$002brtK3dFmkSFpbmiErLaF9WN4u$002fdkC6V1ZJd83eteSggV83nHzax7d8QAQAA.js . I'm not 100% sure, but I think Tapestry, for each requests, checks what Javascript files were included. Then it checks if this file list was already combined into a single one: if not, it does the combining in the spot and sets a far-future expire header on it (for caching). If some of the included Javascript files is changed, then it does the combination again. You can also run tests yourself and take a look at the sources.
          Howard M. Lewis Ship made changes -
          Assignee Howard M. Lewis Ship [ hlship ]
          Howard M. Lewis Ship made changes -
          Status Open [ 1 ] In Progress [ 3 ]
          Hide
          Hudson added a comment -

          Integrated in tapestry-5.2-freestyle #271 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/271/)
          TAP5-73: Fill in some gaps in the unit and integration tests
          TAP5-73: Rename ResourceCache (an internal service) to ResourceDigestManager
          Extend StreamableResource to track the lastModified time of the underlying resource
          TAP5-73: Replace the old implementation of ResourceStreamer with a new one, organized around the new StreamableResourceSource service

          Show
          Hudson added a comment - Integrated in tapestry-5.2-freestyle #271 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/271/ ) TAP5-73 : Fill in some gaps in the unit and integration tests TAP5-73 : Rename ResourceCache (an internal service) to ResourceDigestManager Extend StreamableResource to track the lastModified time of the underlying resource TAP5-73 : Replace the old implementation of ResourceStreamer with a new one, organized around the new StreamableResourceSource service
          Hide
          Hudson added a comment -

          Integrated in tapestry-5.2-freestyle #273 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/273/)
          TAP5-73: Define the ResourceMinimizer service (as a do-nothing placeholder) and thread it into StreamableResourceSource and StackAssetRequestHandler
          TAP5-73: Change the API of StreamableResourceSource to use a single StreamableResourceProcessing value, rather than a set of StreamableResourceFeature values

          Show
          Hudson added a comment - Integrated in tapestry-5.2-freestyle #273 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/273/ ) TAP5-73 : Define the ResourceMinimizer service (as a do-nothing placeholder) and thread it into StreamableResourceSource and StackAssetRequestHandler TAP5-73 : Change the API of StreamableResourceSource to use a single StreamableResourceProcessing value, rather than a set of StreamableResourceFeature values
          Hide
          Hudson added a comment -

          Integrated in tapestry-5.2-freestyle #275 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/275/)
          TAP5-73: Convert the master ResourceMinimizer to use a configuration that maps content types to ResourceMinimizer implementations

          Show
          Hudson added a comment - Integrated in tapestry-5.2-freestyle #275 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/275/ ) TAP5-73 : Convert the master ResourceMinimizer to use a configuration that maps content types to ResourceMinimizer implementations
          Howard M. Lewis Ship made changes -
          Status In Progress [ 3 ] Closed [ 6 ]
          Fix Version/s 5.3.0 [ 12316023 ]
          Resolution Fixed [ 1 ]
          Howard M. Lewis Ship made changes -
          Link This issue incorporates TAP5-741 [ TAP5-741 ]
          Hide
          Hudson added a comment -

          Integrated in tapestry-5.2-freestyle #300 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/300/)
          TAP5-73: Patch together a Maven POM for tapestry-yuicompressor project
          TAP5-73: Add support for CSS minification
          TAP5-73: Add missing @since documentation
          TAP5-73: Turn off line breaks in the minimized JavaScript for a slight reduction in the size of the output
          TAP5-73: Refactor out a base class for implementing minimizers
          TAP5-73: Add license file for tapestry-yuicompressor, and add dependencies licences to NOTICE.txt
          TAP5-73: Add basic tests to demonstrate compression of JavaScript stacks and individual JavaScript files
          TAP5-73: Fix logic for when to cache results to cache always when NOT aggregating
          TAP5-73: Add a test application to demonstrate minification
          TAP5-73: Make the contribution method public, so that it is actually picked up
          TAP5-73: Refactor the execution time logging
          TAP5-73: Initial pass at code for JavaScript compression
          TAP5-73: Flesh out documentation of ResourceTransformer
          TAP5-73: Remove unused import
          TAP5-73: Improve documentation of IOOperation
          TAP5-73: Change a couple of asset-related services to track their IOOperations
          TAP5-73: Add a method to StreamableResource to allow access to the underlying InputStream for the resource's content
          TAP5-73: Add an IOOperation interface (like Runnable, but throws IOException) and a utility method to execute such an operation with an OperationTracker
          TAP5-73: Add empty tapestry-yuicompressor module

          Show
          Hudson added a comment - Integrated in tapestry-5.2-freestyle #300 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/300/ ) TAP5-73 : Patch together a Maven POM for tapestry-yuicompressor project TAP5-73 : Add support for CSS minification TAP5-73 : Add missing @since documentation TAP5-73 : Turn off line breaks in the minimized JavaScript for a slight reduction in the size of the output TAP5-73 : Refactor out a base class for implementing minimizers TAP5-73 : Add license file for tapestry-yuicompressor, and add dependencies licences to NOTICE.txt TAP5-73 : Add basic tests to demonstrate compression of JavaScript stacks and individual JavaScript files TAP5-73 : Fix logic for when to cache results to cache always when NOT aggregating TAP5-73 : Add a test application to demonstrate minification TAP5-73 : Make the contribution method public, so that it is actually picked up TAP5-73 : Refactor the execution time logging TAP5-73 : Initial pass at code for JavaScript compression TAP5-73 : Flesh out documentation of ResourceTransformer TAP5-73 : Remove unused import TAP5-73 : Improve documentation of IOOperation TAP5-73 : Change a couple of asset-related services to track their IOOperations TAP5-73 : Add a method to StreamableResource to allow access to the underlying InputStream for the resource's content TAP5-73 : Add an IOOperation interface (like Runnable, but throws IOException) and a utility method to execute such an operation with an OperationTracker TAP5-73 : Add empty tapestry-yuicompressor module
          Hide
          Hudson added a comment -

          Integrated in tapestry-5.2-freestyle #303 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/303/)
          TAP5-73: Remove unnecessary logic for tracking "virtual libraries", a hold-over from how Tapestry 5.1 handle JavaScript aggregation

          Show
          Hudson added a comment - Integrated in tapestry-5.2-freestyle #303 (See https://hudson.apache.org/hudson/job/tapestry-5.2-freestyle/303/ ) TAP5-73 : Remove unnecessary logic for tracking "virtual libraries", a hold-over from how Tapestry 5.1 handle JavaScript aggregation
          Howard M. Lewis Ship made changes -
          Fix Version/s 5.3 [ 12316024 ]
          Fix Version/s 5.3.0 [ 12316023 ]
          Transition Time In Source Status Execution Times Last Executer Last Execution Date
          Open Open In Progress In Progress
          1229d 16h 3m 1 Howard M. Lewis Ship 11/Feb/11 15:57
          In Progress In Progress Closed Closed
          48d 7h 20m 1 Howard M. Lewis Ship 01/Apr/11 00:17

            People

            • Assignee:
              Howard M. Lewis Ship
              Reporter:
              Howard M. Lewis Ship
            • Votes:
              5 Vote for this issue
              Watchers:
              12 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development