LogoPhly, boy, phly
the weblog and site of Matthew Weier O'Phinney

Friday, September 5. 2008

Proper Layer files when using Dojo with Zend Framework

During my Dojo and ZF webinar on Wednesday, Pete Higgins of Dojo fame noted that I could do something different and better on one of my slides.

This particular item had to do with how I was consuming custom Dojo build layers within my code. I contacted him afterwards to find out what he suggested, and did a little playing of my own, and discovered some more Dojo and javascript beauty in the process.

The code in question looked like this:


Zend_Dojo::enableView($view);
$view->dojo()->setDjConfigOption('usePlainJson', true)
             // ->setDjConfigOption('isDebug', true)
             ->addStylesheetModule('dijit.themes.tundra')
             ->addStylesheet('/js/dojox/grid/_grid/tundraGrid.css')
             ->setLocalPath('/js/dojo/dojo.js')
             ->addLayer('/js/paste/main.js')
             // ->addLayer('/js/paste/paste.js')
             ->registerModulePath('../paste', 'paste')
             ->addJavascript('paste.main.init();')
             ->disable();
 

The lines he was commenting onwere the addLayer() lines.

As noted in my webinar, layers, or custom builds, are a fantastic feature of Dojo. Dojo is incredibly modular, and acts in many ways like a good server-side library should -- only include what is needed, and when its needed. The problem comes at deployment: the user suddenly experiences a situation where the application is making dozens of requests back to the server to get what it needs. The solution is to create a custom build, which pulls in all dependencies into a single file, inters any templates, and then does minification heuristics on the code prior to stripping all whitespace and compressing it. Once done, you now have a single, small file that needs to load on the request -- making the final deployed application snappy.

When I displayed this during the webinar, I noted that after doing so, you have to change your code to point at the new build -- and that's what the two lines I pointed out are for. In essence, one is for development, the other for production. Of course, this is just ripe for problems -- you forget to switch comments in production, or accidently re-merge the development version, etc.

Pete showed me another solution that was much more elegant, and which also got rid of another line in that solution above, the addJavascript()

The solution is to write your code in the same layer file as you'll compile to. When doing so, you can put all your dojo.require() statements in the file, as well as mixin any code you want in the main module namespace:


dojo.provide("paste.layer");

/* Dojo modules to require... */
dojo.require("dijit.layout.ContentPane");
/* ... */

/* onLoad actions to perform... */
dojo.addOnLoad(function() {
    paste.upgrade();
});

/* mixin functionality to the "paste" namespace: */
dojo.mixin(paste, {
    /* paste.newPasteButton() */
    newPasteButton:  function() {
        var form = dijit.byId("pasteform");
        if (form.isValid()) {
            form.submit();
        }
    },
   
    /* ... */
});
 

In my original code, I had a "paste.main.init" method that performed all my dojo.require and dojo.addOnLoad statements, but these now can be simply a part of the layer -- eliminating more work for me.

Then, when creating the profile, you simply have it create the layer in the same file -- in this case, paste/layer.js -- but also have it create a dependency on the original layer file. The compiler will ensure that the original code gets slurped into the build. As an example:


dependencies = {
    layers: [
        {
            name: "../paste/layer.js",
            dependencies: [
                "paste.layer",
                /* other dependencies...*/
            ]
        },
    ],
    prefixes: [
        [ "paste", "../paste" ],
        /* other prefixes -- dijit, etc. */
    ]
}
 

This changes the original ZF snippet above to simply:


Zend_Dojo::enableView($view);
$view->dojo()->setDjConfigOption('usePlainJson', true)
             // ->setDjConfigOption('isDebug', true)
             ->addStylesheetModule('dijit.themes.tundra')
             ->addStylesheet('/js/dojox/grid/_grid/tundraGrid.css')
             ->setLocalPath('/js/dojo/dojo.js')
             ->addLayer('/js/paste/layer.js')
             ->registerModulePath('../paste', 'paste')
             ->disable();
 

Not much shorter -- but because I no longer need to worry about changing the file name, I can rest easier at night.

I'll be blogging more tips such as these in the coming weeks, to help support the new Dojo integration in Zend Framework.

Posted by Matthew Weier O'Phinney in Dojo, PHP at 09:30 | Comments (8) | Trackbacks (0)
Defined tags for this entry: dojo, php, zend framework
Related entries by tags:
Zend Framework 1.7.0 Released
Vimgrep and Vim Project
Pastebin app updates
ZendCon08 Wrapup
Setting up your Zend_Test test suites

Trackbacks
Trackback specific URI for this entry

No Trackbacks

Comments
Display comments as (Linear | Threaded)

Will it be possible to download the source code to the sample application presented in the webinar? I think it would help many people to see this used in context. Thanks.
#1 Jeff Smith (Link) on 2008-09-05 12:53 (Reply)
Yes -- I'll be releasing it in the next few days. Keep an eye out for an announcement on my blog.
#1.1 Matthew Weier O'Phinney (Link) on 2008-09-05 13:35 (Reply)
Thanks!
#2 Jeff Smith (Link) on 2008-09-05 14:03 (Reply)
Can't wait to see this code example, I think the grid stuff will be literally the only example of it on the entire Internet.
#3 Themselves on 2008-09-08 04:21 (Reply)
@matthew - the layer technique also works with CSS files as well. Say you have /paste/layer.js - so the build already knows about your paste namespace and location relative to dojo.js, so just put a styles.css file in /paste/ folder, containing nothing but inline @import calls and custom css. use cssOptimize=comments.keepLines during build, and all @imports are inlined into a single CSS file as well. The output will be the same relative path, so you would only need one addStylesheetModule('paste.styles'), which includes your tundra and tundraGrid.css, as well as any page styles in one place. This also allows you to modularize your css files for easier maintenance and management, and keep all styles and javascript out of your markup.
#4 Peter Higgins (Link) on 2008-09-08 07:43 (Reply)
Yet another invaluable and awesome technique! My thanks to you, Peter!
#4.1 Matthew Weier O'Phinney (Link) on 2008-09-08 09:17 (Reply)
When I try to use this technique to condense css into a single file, I get the following string of error messages when running the custom build:

release: Optimizing (comments.keepLines) CSS file: ../../release/dojo/mystuff/mystyles.css
release: ../../release/dojo/mystuff/mystyles.css
Cannot inline css import, skipping: dojo-release-1.1.0/dojo/resources/dojo.css
release: ../../release/dojo/mystuff/mystyles.css
Cannot inline css import, skipping: dojo-release-1.1.0/dijit/themes/tundra/tundra.css
release: ../../release/dojo/mystuff/mystyles.css
Cannot inline css import, skipping: dojo-release-1.1.0/dijit/themes/tundra/Toolbar.css
release: ../../release/dojo/mystuff/mystyles.css
Cannot inline css import, skipping: dojo-release-1.1.0/dijit/themes/tundra/Menu.css
release: ../../release/dojo/mystuff/mystyles.css
Cannot inline css import, skipping: dojo-release-1.1.0/dijit/themes/tundra/Calendar.css

Here are the contents of my file mystyles.css:

@import "dojo-release-1.1.0/dojo/resources/dojo.css";
@import "dojo-release-1.1.0/dijit/themes/tundra/tundra.css";
@import "dojo-release-1.1.0/dijit/themes/tundra/Toolbar.css";
@import "dojo-release-1.1.0/dijit/themes/tundra/Menu.css";
@import "dojo-release-1.1.0/dijit/themes/tundra/Calendar.css";

There are no tags in this file.

Thanks very much for the help.
#4.2 Bill Treuman on 2008-10-09 06:26 (Reply)
In your @import directives, you need to specify paths relative to the current file. So, in the pastebin app, my public/js/paste/styles/styles.css file referred to the tundra stylesheet using "@import ../../dijit/themes/tundra/tundra.css" -- note the leading "../../".
#4.2.1 Matthew Weier O'Phinney (Link) on 2008-10-09 09:12 (Reply)

Add Comment

Standard emoticons like :-) and ;-) are converted to images.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

 
 
  • Home
  • Resume
  • Blog
  • Phly PEAR Channel
  • Contact Me
  • About this site

ZCE

Zend Education Advisory Board Member

Add to Technorati Favorites

Calendar

Back November '08 Forward
Mon Tue Wed Thu Fri Sat Sun
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

Quicksearch

Links

  • PHLY - PHp LibrarY
  • Paul M. Jones
  • Mike Naberezny
  • Shahar Evron
  • Planet PHP
  • Zend Where I now work
  • Garden.org Where I once worked

Archives

November 2008
October 2008
September 2008
Recent...
Older...

Categories

XML Linux
XML Personal
XML Aikido
XML Family
XML Programming
XML Dojo
XML Perl
XML PHP

All categories

Syndicate This Blog

XML RSS 0.91 feed
XML RSS 1.0 feed
XML RSS 2.0 feed
ATOM/XML ATOM 0.3 feed
ATOM/XML ATOM 1.0 feed
XML RSS 2.0 Comments

Show tagged entries

xml best practices
xml books
xml conferences
xml dojo
xml dpc08
xml file_fortune
xml linux
xml mvc
xml oop
xml pear
xml personal
xml php
xml phpworks08
xml programming
xml ubuntu
xml vim
xml webinar
xml zendcon
xml zendcon08
xml zend framework
© 2004 - present, Matthew Weier O'Phinney
matthew-web <at> weierophinney.net