You should be able to do things less hacky if you use the advagg module. Supports external JS and provides many other hooks for various modules. Checkout the readme for more info & let me know if your trying to do something that I don't support.
The issues I was having with built-in Drupal aggregation is that it totally lost track of the location of other resources dynamically loaded by Dojo. Dojo has its own pretty sophisticated build system, allowing you to build sets of modules in "layers", and it can load other items dynamically as needed so you can keep your layer files small while still delivering decent performance.
And for dojox.graphics, it's necessary to not aggregate certain javascript files -- the rendering libraries for IE are different than those for HTML5/SVG compliant browsers, so the appropriate rendering module gets loaded on demand.
I'm wondering, though, if we'd be able to implement a hook that advagg calls to trigger a Dojo re-build...
Drupal does not provide a reasonable way to load remote stylesheets. This
function uses drupal_add_css if the dojo build is local, or assembles a list
of css stylesheets to add if the stylesheet is remote. Should only be called
to load CSS templates inside the dojo tree -- most module css should use
the normal drupal_add_css.
Sounds like a feature request for advagg. I already do this for JS. In short the goal of AdvAgg is to make the usage of hook_preprocess_page for CSS/JS manipulation a thing of the past. External files I would load before anything else, let me know if this needs to be adjusted.
Or in your case do something even better and have a dojo cdn sub module; where you change the local JS & CSS to use external sources. See the advagg_js_cdn module for the details on how I rewrite jquery.js and jquery-ui.js to point towards Googles CDN.
I should add that you could always do this with advagg
drupal_add_js('http://www...', 'external');
A CDN submodule is the best way to implement this though.
Hmm. So you're suggesting that I move the CDN version into a submodule, which I can then add a dependency to advagg_*_cdn modules, and just use drupal_add_css/drupal_add_js? That definitely gets simple.
For doing builds, I'm a little behind dojo development -- I think they've actually built an in-browser build tool (previously you had to have Java installed and use a shell script that assembles it in Rhino). Builds of a sizable Dojo application on my ancient laptop takes minutes--6 - 10 minutes for our largest apps. I'm wondering if there's an effective way to fork a process to start a build on demand, but return the un-built files for requests that arrive in the meantime.
And again, the question becomes how to handle files that need to get loaded dynamically based on browser -- this is something Dojo already handles itself, but it's one reason to use their build system, to exclude those files and load them on request. The main example being gfx rendering -- there are renderers for VML, native SVG, SVGWeb (a Flash svg viewer), Canvas, and Silverlight. You can specify at page load time the order to load the rendering engine and Dojo detects what's available, loads the first match. Would this cause any issues with advagg?
In advagg I essentially fork a PHP process and generate the CSS & JS aggregates in the background so the html can be generated quicker. It's one of my tricks that I use in a lot of my modules; allows one to make php multi-process in short.
So what I'm doing here http://drupalcode.org/project/advagg.git/blob/8d5a8bfe175a8331bed8353038... is requesting the file via a http request and then continuing like it already exists; request times out after 1 second, but the file gets generated and by the time the browser requests it, it's ready 2 go. If AdvAgg was a php5 only module I could send the request out and drop it instantly not waiting for anything; something I plan to do for the D7/8 port.
I'm sure you can make your module do something similar. We have no need for Dojo, my goal of advagg is to make it into core for D8; finding the edge cases and making sure they work is key.
I just spent some time on this module, updating it for Dojo's newly defined "AMD" -- Asynchronous Module Definition format, which Dojo has moved to in version 1.7 and beyond.
Basically, AMD allows you to lazyload resources on demand, right before actual use. It also has a build process for doing its own aggregation.
The biggest challenge this poses to aggregation is that modules that get loaded asynchronously need to know where to be found, relative to the main dojo.js file.
With a dojo build, the module files get copied into the build directory so they can be included even from a built version of Dojo (build=aggregation) -- and for certain things like Graphics libraries, this is necessary because the renderers get loaded after browser sniffing to determine which renderer to use (e.g. SVG vs Canvas vs Silverlight). Furthermore, builds can be layered, and entire layers loaded on demand.
So I guess overall, I would like to exclude the Dojo script from aggregation entirely, but am still hacking in my own solution for a couple things advagg might? provide:
1. Ability to load script from CDN.
2. Ability to run some inline JS immediately before the Dojo.js script tag -- most configuration is done by setting a global dojoConfig variable with your settings, and this needs to happen before the dojo script tag.
3. Ability to load a remote CSS file from a CDN (which can of course be aggregated, or not)
4. Ability to exclude the dojo.js script from aggregation -- and/or locate the aggregated script file in the same directory as the other supporting module/layer scripts.
Comments
Comment #1
freelockI'll definitely take a look... Looks pretty cool!
The issues I was having with built-in Drupal aggregation is that it totally lost track of the location of other resources dynamically loaded by Dojo. Dojo has its own pretty sophisticated build system, allowing you to build sets of modules in "layers", and it can load other items dynamically as needed so you can keep your layer files small while still delivering decent performance.
And for dojox.graphics, it's necessary to not aggregate certain javascript files -- the rendering libraries for IE are different than those for HTML5/SVG compliant browsers, so the appropriate rendering module gets loaded on demand.
I'm wondering, though, if we'd be able to implement a hook that advagg calls to trigger a Dojo re-build...
Comment #2
mikeytown2 commentedSounds like a feature request for advagg. I already do this for JS. In short the goal of AdvAgg is to make the usage of hook_preprocess_page for CSS/JS manipulation a thing of the past. External files I would load before anything else, let me know if this needs to be adjusted.
Comment #3
mikeytown2 commented#1121608: Load external CSS files
if using advagg you can now do this
Snapshot download to test this new functionality out: http://drupalcode.org/project/advagg.git/snapshot/8d5a8bfe175a8331bed835...
Or in your case do something even better and have a dojo cdn sub module; where you change the local JS & CSS to use external sources. See the advagg_js_cdn module for the details on how I rewrite jquery.js and jquery-ui.js to point towards Googles CDN.
I should add that you could always do this with advagg
A CDN submodule is the best way to implement this though.
Comment #4
freelockHmm. So you're suggesting that I move the CDN version into a submodule, which I can then add a dependency to advagg_*_cdn modules, and just use drupal_add_css/drupal_add_js? That definitely gets simple.
For doing builds, I'm a little behind dojo development -- I think they've actually built an in-browser build tool (previously you had to have Java installed and use a shell script that assembles it in Rhino). Builds of a sizable Dojo application on my ancient laptop takes minutes--6 - 10 minutes for our largest apps. I'm wondering if there's an effective way to fork a process to start a build on demand, but return the un-built files for requests that arrive in the meantime.
And again, the question becomes how to handle files that need to get loaded dynamically based on browser -- this is something Dojo already handles itself, but it's one reason to use their build system, to exclude those files and load them on request. The main example being gfx rendering -- there are renderers for VML, native SVG, SVGWeb (a Flash svg viewer), Canvas, and Silverlight. You can specify at page load time the order to load the rendering engine and Dojo detects what's available, loads the first match. Would this cause any issues with advagg?
Comment #5
mikeytown2 commentedIn advagg I essentially fork a PHP process and generate the CSS & JS aggregates in the background so the html can be generated quicker. It's one of my tricks that I use in a lot of my modules; allows one to make php multi-process in short.
So what I'm doing here http://drupalcode.org/project/advagg.git/blob/8d5a8bfe175a8331bed8353038... is requesting the file via a http request and then continuing like it already exists; request times out after 1 second, but the file gets generated and by the time the browser requests it, it's ready 2 go. If AdvAgg was a php5 only module I could send the request out and drop it instantly not waiting for anything; something I plan to do for the D7/8 port.
I'm sure you can make your module do something similar. We have no need for Dojo, my goal of advagg is to make it into core for D8; finding the edge cases and making sure they work is key.
Comment #6
freelock@mikeytown, if you're listening here...
I just spent some time on this module, updating it for Dojo's newly defined "AMD" -- Asynchronous Module Definition format, which Dojo has moved to in version 1.7 and beyond.
Basically, AMD allows you to lazyload resources on demand, right before actual use. It also has a build process for doing its own aggregation.
The biggest challenge this poses to aggregation is that modules that get loaded asynchronously need to know where to be found, relative to the main dojo.js file.
With a dojo build, the module files get copied into the build directory so they can be included even from a built version of Dojo (build=aggregation) -- and for certain things like Graphics libraries, this is necessary because the renderers get loaded after browser sniffing to determine which renderer to use (e.g. SVG vs Canvas vs Silverlight). Furthermore, builds can be layered, and entire layers loaded on demand.
So I guess overall, I would like to exclude the Dojo script from aggregation entirely, but am still hacking in my own solution for a couple things advagg might? provide:
1. Ability to load script from CDN.
2. Ability to run some inline JS immediately before the Dojo.js script tag -- most configuration is done by setting a global dojoConfig variable with your settings, and this needs to happen before the dojo script tag.
3. Ability to load a remote CSS file from a CDN (which can of course be aggregated, or not)
4. Ability to exclude the dojo.js script from aggregation -- and/or locate the aggregated script file in the same directory as the other supporting module/layer scripts.
Thoughts?