google-code-export / wro4j

Automatically exported from code.google.com/p/wro4j
1 stars 1 forks source link

Enable Custom Bundle Naming in WRO Run-time Mode #741

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Use of NamingStrategy is currently limited to WRO's build-time mode.  But the 
need to create cache busting bundle names exists in run-time mode too.  

Because bundle names must be included in web pages before the bundles exist, 
WRO should enable processing the wroModel (to generate bundle names) before the 
page is rendered.  

The only way to trigger wroModel processing now is to install a 
WroContextFilter, to workaround ModelFactory's need for a Context.  A better 
solution is to enable ModelFactory to accept a NoOp Context programmatically 
for wroModel processing. 

This feature request has been made on the Forums before, but I don't see it 
listed as an official request.  Here are links to previous discussions about 
the need for this enhancement.

http://code.google.com/p/wro4j/issues/detail?id=454
https://groups.google.com/forum/#!msg/wro4j/OfljdZU2n9Y/GdMA3ORcIxcJ

Thank you for considering this feature request.

Original issue reported on code.google.com by devdanw...@gmail.com on 6 Jun 2013 at 9:19

GoogleCodeExporter commented 9 years ago
This is already possible using wro4j taglib: 
https://github.com/Orange-OpenSource/wro4j-taglib

I think it doesn't worth reinventing the wheel. Something similar would be 
implemented eventually if the wro4j-taglib is discontinued or has too little 
activity. Until then, I would rather focus on fixing existing bugs or adding 
other missing features.

If you would still prefer to have it in wro4j-core, you might consider 
contributing.

Thanks,
Alex

Original comment by alex.obj...@gmail.com on 7 Jun 2013 at 7:38

GoogleCodeExporter commented 9 years ago
Hello Alex,

It is nice to get your feedback.  Here is my reaction:

Not everyone uses JSP.  My company uses Handlebar templates instead of
JSP.  Freemarker and Velocity are also popular alternatives to JSP.

I looked at the Orange JSP taglib solution you suggested. It seems
needlessly complex. As far as I can tell, it requires pre-processing
by a Maven plugin.  There should be no need for that.

I've implemented a solution, as a ModelTransformer.  But my renaming
doesn't happen until a web request arrives.  That's too late.

It would be better to process the model, and calculate MD5 digests on
resources, when the container starts.  For webapps, we want to fail
fast if there's a problem with the resources or config.  We don't want
users to discover it later.

But I couldn't find a way to do this when the container starts.  The
current WRO architecture  requires the WroContextFilter and WRO
ServletContextListener, which add a lot of configuration complexity.
Yet that complexity isn't in the WRO Maven plugin.

Thanks for your cool WRO project.  Also, thanks for responding so
soon.  If you're not planning to work on it, that increases the chance
that I will.

My guess is that your WRO Maven plugin is the best approach to
enabling NamingStrategy to work at run-time.

Original comment by devdanw...@gmail.com on 7 Jun 2013 at 8:16

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I agree that enabling namingStrategy for runtime solution can be solved not 
only with jsp tag. That is why, the scope of this task is very unclear. Let's 
narrow it down and make it more clear.

There is already an open issue for creating a jsp tag (official implementation 
similar to what wro4j-taglib already does). Besides taglib, there are numerous 
other solutions to this problem, but we must define what exactly you need. For 
instance, if you would use a web framework like wicket or tapestry, you would 
probably solve this differently. I'm not sure how this could be solved with 
handlebars, since handlebars is used by wro4j as a processor... Using 
ModelTransformer for solving this problem doesn't seems to be right. 

I'm open to discuss about it and provide with any support, but I cannot commit 
on implementing it, since there are hundreds of other tasks which worth fixing 
and my spare time is not endless. Distributing the effort and accepting 
contribution would definitely scale better.

Original comment by alex.obj...@gmail.com on 7 Jun 2013 at 8:28

GoogleCodeExporter commented 9 years ago
While naturally I totally understand Alex, I would personally vote for this 
feature in WRO. Here at www.mobile.de/ro we do not use JSP pages Runtime 
solution of WRO and would love to benefit from hashed urls for site performance 
reasons.

Original comment by Mateusz....@gmail.com on 22 Jul 2013 at 3:53

GoogleCodeExporter commented 9 years ago
Moreover, I actually wouldn't mind helping to implement this in WRO if I only 
knew the right approach to do this, I am still learning WRO.

Original comment by Mateusz....@gmail.com on 22 Jul 2013 at 3:54

GoogleCodeExporter commented 9 years ago
@Mateusz you are saying that you are not using jsp's. I'm curious, how do you 
use it? How would you like this feature to be implemented? This kind of 
information are very useful to understand the problem and find the proper 
solution.

Contributions are welcome. And by contribution I don't mean only coding, but 
also suggestions, tests, demos, design ideas, code reviews, documentation, 
blogs, etc.... 

Original comment by alex.obj...@gmail.com on 22 Jul 2013 at 4:06

GoogleCodeExporter commented 9 years ago
@Alex:

Basically we would like to get a hash encoded inside wro resources, e.g. for a 
homepage:
http://www.mobile.de/wro/home-HASH.js
and http://www.mobile.de/wro/home-HASH.css

At the moment I am trying to implement this myself but I would prefer support 
in framework. For templating we use Google Closure (Soy) files so far from JSPs.

How would you recommend providing a support for this, I saw you didn't like 
ModelTransformer solution somebody else provided.

One more question:
Does it even make any sense to combine maven approach with runtime approach? 
The reason I ask is because we need to preload all WRO urls before we launch 
the site so that our customers have a full working site and this is a pain (we 
do this during deployment step)

By the way: if you are looking for a job, eBay.de (mobile.de/ro is part of it) 
is recruiting in Berlin! Let me know!

Original comment by Mateusz....@gmail.com on 22 Jul 2013 at 6:32

GoogleCodeExporter commented 9 years ago
Since it is impossible to provide support out of the box for all existing 
technologies (ex: google soy, jsp, etc), I see the following options:

1) Use runtime solution during development and maven plugin for production. 
Maven plugin has a feature which allows generating a property file containing 
the mapping between original group name and renamed one
2) Server-side computation of the hash. This require custom coding to fit with 
your technology (google closure soy). Also, don't forget that in order to 
compute the hash, the Context object should be available. That means that it 
requires to access the HttpServletRequest and HttpServletResponse objects which 
are used for locating resources.. This approach should work fine and if you 
think it worth the effort, we could try a proof of concept in a branch (maybe a 
new module in wro4j-examples?)
3) Client-side computation of the hash, using the Rest API exposed by wro4j 
using RequestHandlers (https://code.google.com/p/wro4j/wiki/RequestHandler). 
Basically, the idea is to include the javascript and css lazily using a 
bootstrap js which would call the wro4j rest api to get the actual url of the 
resources (containing the hash).

Let me know what you think about it.

Original comment by alex.obj...@gmail.com on 22 Jul 2013 at 8:18

GoogleCodeExporter commented 9 years ago
@Alex:

ad 1) Runtime vs Maven
I can include maven but then again I need to make sure that Filter is in such 
cases disabled, right? Do you have an idea how to achieve this? Perhaps there 
is a configuration parameter that can be passed to web.xml?

Actually the two reasons that we would want to have both is that md5 group 
hashing doesnt work and we would like to compile all resources for production 
deployment. As I said now we have a hack, that we call all resource urls once 
deployment is done to eagerly preload resourced and force compilation.

Now that I understand wro more, it would make sense to include a Wro 
RequestHandler out of the box that would compileAllResources.
e.g. /wro/api/compileGroup/all or /wro/api/compileGroup/home or similar. What 
do you think?

ad 2) Yesterday, at home I actually almost got a runtime solution to work but 
without using wroAPI, basically
I created urls in the form like:
http://mobile.de/wro/home.js?v=md5
I achieved this because I was able to access WroModel, using a bit of code from 
James Bloom (WroModelHolder). For that I needed to insert in web.xml WroContext 
and also WroListener, one of them or both in fact broke the front page, 
suddenly I started to receive issues in accessing img files, for some reason 
WRO started to process image files referenced in css or our less files. I have 
a feeling that this cssRenamingPreProcessor is for that but I am not sure. 
Anyway, your solution with WroApi?group="home" seems to be more generic but has 
a drawback that a a restful endpoint locally has to be called. 

You are saying it is not possible to do this in a generic way, I am not so 
sure, you see at the moment we are generating a link on the *server side* and 
pass this link via a variable to templating layer.
It would seem to be possible to create something like
WroResourceLinkComposer, which composes a link for CSS and JS. e.g.

public String composeUrl(String homebaseUrl, String wroGroupName);

In turn the composer would use NamingStrategy and HashStrategy from wro and 
would have access to WroModel. It would have to be request specific but in our 
case we generate links once a http servlet request is fired.

3. For the first time yesterday I also managed to launch successfully a request 
handler, those available by default, are already useful -> e.g. reloadCache one 
doesn't require JMX call.

Original comment by Mateusz....@gmail.com on 23 Jul 2013 at 11:53

GoogleCodeExporter commented 9 years ago
@Alex:
By the way, I worked for Betfair and visited Cluj-Napaca. I worked in London 
and my boss was Phil Dixon (your CTO)... we actually worked together also in 
another company (Shopzilla). James Bloom was also in London office but we 
didn't know each other that much.

Cluj-Napoca is a nice place!

Original comment by Mateusz....@gmail.com on 23 Jul 2013 at 11:55

GoogleCodeExporter commented 9 years ago
Good to know you are my ex-colleague. Hope you'll have opportunity to visit it 
sometime again :).

Original comment by alex.obj...@gmail.com on 23 Jul 2013 at 12:24

GoogleCodeExporter commented 9 years ago
1) Disabling WroFilter
This is possible. The WroFilter has a flag (enabled - true by default) which 
can be changed using setEnabled(boolean) method. You could configure the 
WroFilter conditionally using spring or guice.

Creating custom RequestHandler also does make sense and as long as it does 
exactly what is suitable for your use-case. 

2) Exposing a LinkComposer is a great idea. This could be used by any 
server-side framework. I will create an issue, just to be sure I won't forget 
it.

3) I also find the RequestHandler's very useful, since it allows you to inspect 
the model and expose other triggers which would normally require an application 
restart.

I would be interested in solution you will choose after all. It would be great 
to see a working demo on github. I could add it to wro4j-examples module. Your 
experience might inspire or help other peoples.

Thanks,
Alex

Original comment by alex.obj...@gmail.com on 23 Jul 2013 at 2:24

GoogleCodeExporter commented 9 years ago
@Alex:
The interesting thing is that we moved from maven solution to runtime solution 
because we didn't want to redeploy and recompile all the time. We could not 
figure out in maven solution the way to force only recompilation of resources 
on a running system. Have you achieved that?

Commercially I think I will go for both runtime and compile time solution with 
a flag, privately I still think there is some benefit for users to have this 
RequestHandler. There is even a ticket for this I noticed. As for LinkComposer, 
this is not that easy because it requires access to WroModel from LinkComposer, 
so it makes sense to be done within Wro component base rather than as an 
example project?

One question to maven build option, once I rename all the resources with hash 
inside of names using NamingStrategy and HashingStrategy, one can I know how to 
access to urls? After all I don't know what md5 hash is there from a webpage 
perspective?

Original comment by Mateusz....@gmail.com on 23 Jul 2013 at 4:51

GoogleCodeExporter commented 9 years ago
Actually I figured it out but my new generated file as per configuration 
variable is wrong:
#Mapping of defined group name to renamed group name
#Tue Jul 23 22:19:20 CEST 2013
vipsemitrailertruck.css=vipsemitrailertruck.css
error.css=error.css
common-all-pages.css=common-all-pages.css
home.js=home.js
vipconstructionmachine.css=vipconstructionmachine.css
dspcar.js=dspcar.js
imprint.css=imprint.css
vipvanupto7500.js=vipvanupto7500.js
srp.css=srp.css
vipvanupto7500.css=vipvanupto7500.css
vipsemitrailertruck.js=vipsemitrailertruck.js
common-dsp-pages.js=common-dsp-pages.js
contactus.css=contactus.css
links.js=links.js
error.js=error.js

Do you know why this may be happeninig?

Wro directory example:
-rw-r--r--    1 mati  staff  107800 23 Jul 20:28 
vipforklifttruck-693f7dfa25a5f33e8212025df528b4e3.js
-rw-r--r--    1 mati  staff   86593 23 Jul 20:28 
vipforklifttruck-bee33b708c9b4b68223a0f503a8ee0c3.css
-rw-r--r--    1 mati  staff  119039 23 Jul 22:19 vipforklifttruck.css
-rw-r--r--    1 mati  staff  107789 23 Jul 22:19 vipforklifttruck.js
-rw-r--r--    1 mati  staff  107800 23 Jul 20:28 
vipsemitrailer-693f7dfa25a5f33e8212025df528b4e3.js
-rw-r--r--    1 mati  staff   86593 23 Jul 20:28 
vipsemitrailer-bee33b708c9b4b68223a0f503a8ee0c3.css
-rw-r--r--    1 mati  staff  119039 23 Jul 22:19 vipsemitrailer.css
-rw-r--r--    1 mati  staff  107789 23 Jul 22:19 vipsemitrailer.js
-rw-r--r--    1 mati  staff  107800 23 Jul 20:28 
vipsemitrailertruck-693f7dfa25a5f33e8212025df528b4e3.js
-rw-r--r--    1 mati  staff   86593 23 Jul 20:28 
vipsemitrailertruck-bee33b708c9b4b68223a0f503a8ee0c3.css
-rw-r--r--    1 mati  staff  119039 23 Jul 22:19 vipsemitrailertruck.css
-rw-r--r--    1 mati  staff  107789 23 Jul 22:19 vipsemitrailertruck.js
-rw-r--r--    1 mati  staff  107800 23 Jul 20:28 
viptrailer-693f7dfa25a5f33e8212025df528b4e3.js
-rw-r--r--    1 mati  staff   86593 23 Jul 20:28 
viptrailer-bee33b708c9b4b68223a0f503a8ee0c3.css
-rw-r--r--    1 mati  staff  119039 23 Jul 22:19 viptrailer.css
-rw-r--r--    1 mati  staff  107789 23 Jul 22:19 viptrailer.js
-rw-r--r--    1 mati  staff  107800 23 Jul 20:28 
viptruckover7500-693f7dfa25a5f33e8212025df528b4e3.js
-rw-r--r--    1 mati  staff   86593 23 Jul 20:28 
viptruckover7500-bee33b708c9b4b68223a0f503a8ee0c3.css
-rw-r--r--    1 mati  staff  119039 23 Jul 22:19 viptruckover7500.css
-rw-r--r--    1 mati  staff  107789 23 Jul 22:19 viptruckover7500.js
-rw-r--r--    1 mati  staff  107800 23 Jul 20:28 
vipvanupto7500-693f7dfa25a5f33e8212025df528b4e3.js
-rw-r--r--    1 mati  staff   86593 23 Jul 20:28 
vipvanupto7500-bee33b708c9b4b68223a0f503a8ee0c3.css
-rw-r--r--    1 mati  staff  119039 23 Jul 22:19 vipvanupto7500.css
-rw-r--r--    1 mati  staff  107789 23 Jul 22:19 vipvanupto7500.js

Original comment by Mateusz....@gmail.com on 23 Jul 2013 at 8:21

GoogleCodeExporter commented 9 years ago
This might be a bug. Expected behavior is to have correct mapping respecting 
the namingStrategy configured. Could you provide more details regarding your 
configuration?

Original comment by alex.obj...@gmail.com on 23 Jul 2013 at 8:50

GoogleCodeExporter commented 9 years ago
Well, the bug was only happening in a case where in wro.proprerties there was 
hashStrategy but no naming strategy. I modified it and now I have correct links 
in mapping file but I ran into another issue :(. Issue is that those files are 
constantly accumulated from somewhere and worse of all, when I do mvn clean 
install, all the old ones still appear here, I see multiple files with 
different hashes.

What is the correct way to generate links to those files? Load this properly 
mapping files in a webapp and then lookup a renamed file for my wro group?

Original comment by Mateusz....@gmail.com on 24 Jul 2013 at 8:18

GoogleCodeExporter commented 9 years ago
The mapping file should contain only the most recent changes. Probably the 
reason why the old mappings are accumulated is because the incremental build 
change support 
(https://community.jboss.org/en/tools/blog/2012/01/17/css-and-js-minification-us
ing-eclipse-maven-and-wro4j)

Probably when incremental build change is not used, the mapping file should be 
cleared.
I will create an issue for this and hopefully this will be fixed in next 
version.

Original comment by alex.obj...@gmail.com on 24 Jul 2013 at 8:41

GoogleCodeExporter commented 9 years ago
It is not that actually mapping file contains old entries but rather is 
directory there are old files present, like old generated files.

Original comment by Mateusz....@gmail.com on 24 Jul 2013 at 10:54

GoogleCodeExporter commented 9 years ago
Well, in that case unless the generated file is located in target folder (which 
is removed during clean phase), there is nothing else the plugin can do out of 
the box. Removing stale files could be dangerous, especially when you use one 
of the source folder as a output folder location.

Original comment by alex.obj...@gmail.com on 24 Jul 2013 at 1:39

GoogleCodeExporter commented 9 years ago
@Alex:
I found the problem, simply wro files are written to src/main/webapp/wro, this 
is as per example from the web, I guess this is a wrong pattern to follow? It 
should be written to target folder in maven?

Original comment by Mateusz....@gmail.com on 26 Jul 2013 at 4:21

GoogleCodeExporter commented 9 years ago
Solved it:
This is a better example for wiki page:
                            <destinationFolder>${project.build.directory}/${project.build.finalName}/wro/</destinationFolder>

Original comment by Mateusz....@gmail.com on 26 Jul 2013 at 5:23

GoogleCodeExporter commented 9 years ago
Yes, using build directory is a good solution.

in WRO Run-time Mode

<destinationFolder>${project.build.directory}/${project.build.finalName}/wro/</d
estinationFolder>

Original comment by alex.obj...@gmail.com on 26 Jul 2013 at 5:48

GoogleCodeExporter commented 9 years ago
Why in RunTime mode? I am using this in Build Time Mode... this configuration 
variable:
<destinationFolder>${project.build.directory}/${project.build.finalName}/wro/</d
estinationFolder>

Seems to work fine now.

By the way, now I ran into another issue, ySlow shows that in Build Time Mod, 
which we are using for production (using maven plugin) my resources are not 
sent gziped. With Runtime Approach this is gzipped, what do I have to do to 
make them gzippable?

Mateusz

Original comment by Mateusz....@gmail.com on 26 Jul 2013 at 8:53

GoogleCodeExporter commented 9 years ago
Configure your continer to gzip static resources. This is something that
should make difference between clients that support gzip and those who
don't.

Original comment by alex.obj...@gmail.com on 26 Jul 2013 at 9:16