thoughts on better wro4j, JavaScript & CSS integration

188 views
Skip to first unread message

James Strachan

unread,
Sep 13, 2011, 6:48:50 AM9/13/11
to sca...@googlegroups.com
Matts recent mail on wro4j got me thinking.
http://code.google.com/p/wro4j/

So we can easily just reuse wro4j as a separate filter to let us group
CSS and JS files together for minimising and turning into a single
browser request to boost page load times and increasing modularity of
files etc.

I wondered if we could do a little better though. A few background motivations:

* sometimes layouts declare a dependency on some css/JS and sometimes
its a snippet/template/dynamic include etc.

e.g. its quite common to have global CSS/JS for a site, then custom
pages add a few extra bits and bobs which you want to replace with a
single group file. So the set of includes could be dynamic at runtime;
but we still may wish to have a single cached, static file with those
files together

* maintaining the separate groups file seems a separate level of
indirection that makes it harder to just hack up templates and
refactor them into layouts / includes / snippets etc.

* I prefer hacking jade + scala to XML :)

* in development we often want to use the actual individual includes
as its then easier to use line numbers and see which files need
changing in the developer console in Safari/Chrome/FireBug etc.

So rather than doing this...
http://code.google.com/p/wro4j/wiki/GettingStarted

<groups xmlns="http://www.isdc.ro/wro">
<group name="g1">
<js>classpath:com/mysite/resource/js/1.js</js>
<css>classpath:com/mysite/resource/css/1.css</css>
<group-ref>g2</group-ref>
</group>

<group name="g2">
<js>/dwr/engine.js</js>
<group-ref>g3</group-ref>
<css>classpath:/static/css/2.css</css>
<js>classpath:/static/*.js</js>
</group>

<group name="g3">
<css>/static/css/style.css</css>
<css>/static/css/global/*.css</css>
<js>/static/js/**</js>
<js>http://www.site.com/static/plugin.js</js>
</group>

</groups>

then doing this... in a jade layout

html
head
link(rel="stylesheet" type="text/css" href="/wro/g2.css")
script(type="text/javascript" src="/wro/g2.js")

we could instead just leave the actual includes in the templates using
the real names; then dynamically render them either as separate files
or a single group file.

e.g. anywhere in a template, snippet or layout we could include code
like this (allowing multiple arguments)...

- linkCss("/static/css/2.css")
- scriptJs("http://www.site.com/static/plugin.js")

then in the template

html
head
- linkCss("/static/css/3.css")
- scriptJs("foo/bar.js")
= includeCssAndJs

then the includeCssAndJs function can firstly get rid of any duplicate
link/script tags (using the URIs of the sources as the unique key),
but it can also either use the actual separate link/script tags if in
development mode or replace the current set of includes with some
'group' link/script and generate the wro4j group on the fly without
having to maintain a separate XML file.

e.g. depending on the development mode (and/or flag in the Scalate
Console) we could render the above as

<html>
<head>
<link href="/static/css/2.css" rel="stylesheet" type="text/css"></link>
<link href="/static/css/3.css" rel="stylesheet" type="text/css"></link>
<script type='text/javascript'
src="http://www.site.com/static/plugin.js"></script>
<script type='text/javascript' src="foo/bar.js"></script>
</head>
...
</head>

or the 'minimised' version

<html>
<head>
<link href="/groups/g1.css" rel="stylesheet" type="text/css"></link>
<script type='text/javascript' src="groups/g1.js"></script>
</head>
...
</head>

where it could just auto-generate numbered groups; or we could provide
a little mapping of lists of URIs => group names.

All we'd need is a few new helper scala functions to declare new
link/script tags (with helper methods for CSS and JS the common
flavours of those) and a includeCssAndJs method to render them in the
layout.

Thoughts?

--
James
-------
FuseSource
Email: ja...@fusesource.com
Web: http://fusesource.com
Twitter: jstrachan, fusenews
Blog: http://macstrac.blogspot.com/

Open Source Integration and Messaging

Tristan Burch

unread,
Sep 13, 2011, 11:17:41 AM9/13/11
to sca...@googlegroups.com
I think this makes a lot of sense. We're already doing something similar by having each page declare the js/css is needs and then when the layout is rendered, there is are 2 js script elements and 2 css link elements. The idea is that there are global js/css that all pages need (ideally this is cached after the first page is loaded) and then each page can add whatever it needs. All of these links point to an endpoint that minifies the requested js/css files with the YUI compressor.

-Tristan

Matt Raible

unread,
Sep 21, 2011, 4:15:46 PM9/21/11
to sca...@googlegroups.com

I think this sounds great! I'd like to suggest different names though. Is this possible?

> - css("/static/css/3.css","/static/css/4.css")
> - script("foo/bar.js")
> = assets

Maybe even allow a default group to be defined in a layout (like above) and overridden (or added to) in templates. Something like:

- css(default, "/static/css/4.css")

Or leave out "default" if you want to completely override.

This might be out of scope for Scalate, but it'd also be interesting to have the URLs versioned when assets change.

http://raibledesigns.com/rd/entry/versioning_static_assets_with_urlrewritefilter

Is this something that you plan on implementing soon? Is there anything I can do to help test it?

Thanks,

Matt

Reply all
Reply to author
Forward
0 new messages