

Just One File with Cappuccino 0.8 - sant0sk1
http://cappuccino.org/discuss/2009/11/11/just-one-file-with-cappuccino-0-8/

======
milestinsley
This is the sort of fantastically elegant solution, to a tricky problem, that
we have come to expect from 280North and Cappuccino.

The killer feature here is that "you won’t have to change a single line of
code". I love how seamless this is to implement! Oh, and that the images are
sent as encoded text - pure awesome.

------
pohl
This sounds exactly like the ImageBundle feature in GWT: automatic spriting,
no configuration files, works on IE6 and above... it's a great feature.

~~~
boucher
I believe the GWT thing requires you to specifically create a bundle subclass,
and put all the image files in that bundle (as methods with or without
annotations). Please correct me if I'm wrong.

~~~
pohl
You only need to create a sub-interface, and the annotations are only
necessary if the image filenames cannot be inferred from the method names in
that sub-interface.

It wasn't clear from the original article how Cappuccino handles this...do
they automatically throw any image that happens to be in a magic directory
into the bundle?

There are other details that are different, so I guess I shouldn't have said
"exactly". ImageBundle will make a real PNG for you instead of Base64, for
example. Although in 2.0 the new generalized ClientBundle facility (same
concept, but you can also bundle CSS, XML, a PDF...) promises to use data:
URLs, JSON notation, or other representations when its calculated to be size-
appropriate.

~~~
boucher
The default jakefile we will ship just automatically bundles any image
resource in the project.

ImageBundle sounds pretty solid. I guess they are inferring the orientation of
an image somehow? I'd like to see how that works. If you use an image in
multiple orientations, or if you need to stretch in both directions, using a
single .png file just isn't possible, unless there's something I'm missing.

~~~
pohl
In the current implementation (ImageBundle) you would need to have separate
copies for each orientation & scale. That's a really nice thing that the
Cappuccino implementation brings. The new ClientBundle implementation promises
to, at least, have the compiler flip an image left-to-right when appropriate
for a user's locale:

    
    
          @ImageOptions(flipRtl = true) 
    

...and there's another hint for images that are intended to be tiled:

    
    
          @ImageOptions(repeatStyle=RepeatStyle.Vertical)
    

There's no scaling yet, but the tiling annotation covers some of the cases
where you might want scaling (such as the edges of a corner-rounded/drop-
shadowed box of variable size).

------
gcv
Very cool, but Base64 encoding produces results rather larger than the
original image binaries, no? I guess the benefits outweigh the drawbacks?

~~~
milestinsley
Yes, that's true. I think, generally speaking, base64 encoded images will
result in more bytes than the original. I guess it's probably around 10%-20%.

I think, in the case of spriting, it would be fair to say that the overhead of
loading many images/http requests (and their individual headers) pretty much
nullifies the effects of bloating from the encoding.

~~~
Nycto
Base64 will inflate a list of bytes by 33%. For every three bytes that go in,
4 bytes are returned. Wikipedia has a very good explanation of why this is:

<http://en.wikipedia.org/wiki/Base64>

While we're on the subject, Ascii85 is kind of a cool alternative. By
increasing the number of characters used for the encoded string and breaking a
32 bit integer apart in an interesting way, it is able to reduce the expansion
down to 25%. For every 4 characters in, 5 come out. Again, more info is
available on Wikipedia:

<http://en.wikipedia.org/wiki/Ascii85>

~~~
jacobolus
Incidentally, here's some javascript codecs I wrote for both base64 and
ascii85, if anyone wants to play with using them on their sites:

<http://pastie.textmate.org/695197>

My base64 codec turns out to be quite similar to the Cappucino one; oddly,
most of the javascript base64 codecs with decent google juice are actually
horrible implementations.

------
mcav
I wonder how they're handling caching.

~~~
boucher
Typical cappuccino apps are cached all at once with far future expires. Simply
changing the URL (in an automated way) is enough to break the cache for new
versions.

The caching tradeoff is there for any spriting technique, it will always be a
tradeoff between reducing HTTP requests and increasing caching granularity.

~~~
notauser
Most browsers can handle two concurrent connections.

I wonder if you could create a single diff file for minor revisions. Clients
would get both files in parallel as most are configured to allow two
connections per host.

E.g.:

\- index.html with in-line minor diff + data loader.

\- data file with resource that is patched before extraction.

The right time to blow away the cache and produce a new monolithic data file
would depend on your visitor profile. The nice part is that your changes could
touch multiple files and still have the same overhead.

.......quick example over 10 days........

A user visits every day, 1 change per day, 1% of code modified per change:

\- file re-consolidated/cached on every change, user downloads 1000%

\- with diffs consolidated every 5 days, user downloads 220%

\- best case conventional update, user downloads 109% (but probably a lot
more)

~~~
boucher
Interesting idea. It's worth mentioning that one file in Cappuccino means one
file per bundle, plus the index.html file and Objective-J.js.

A typical app has the Cappuccino bundle, and one bundle for the app code, but
using an external framework means adding an additional bundle. We're exploring
techniques to further concatenate bundles together (we have one in the
project, but it has some negative side effects).

~~~
notauser
I'm curious about your concatenation technique. Dynamically creating multiple
script objects (with document.createElement) from a data file and injecting
them has been reasonably robust for me but I'm not writing a framework so I
have far fewer test cases! :-)

~~~
tolmasky
Cappuccino has a completely custom loader and concatenated file format that
creates a file system representation, such that when you do something akin to
XHR("something/blah") it knows that it already downloaded it and gives it to
you without a request, that way whether you ship concatenated code or not the
code that fetches it is the same.

------
jobenjo
Any way I can do this in Django? (Or--how hard is this to do by hand?). Seems
really promising.

~~~
mnemonik
Someone asked a similar question in the comments and this is the reply he got:

 _The code is all part of Objective-J and the tools, which don't require the
framework itself. You could always use those in your project without using
Cappuccino._

------
delano
Is "Just One File" a reference to Ministry?

