* Speeds up Dragonfly load times (a lot).

This commit is contained in:
halex
2007-07-10 01:25:40 +00:00
parent e52ab32f26
commit afa1db57b0
7 changed files with 212 additions and 106 deletions
+48 -45
View File
@@ -208,34 +208,35 @@ dist_img_DATA := \
jsdir = $(htdocsdir)/js
# These *must* be in the order in which they get loaded in the browser
dist_js_DATA := \
src/www/js/Dragonfly.js \
src/www/js/Format.js \
src/www/js/Gettext.js \
src/www/js/Cookie.js \
src/www/js/Location.js \
src/www/js/Login.js \
src/www/js/Util.js \
src/www/js/Widgets.js \
src/www/js/ValidatingEntry.js \
src/www/js/Preferences.js \
src/www/js/AddressBook.js \
src/www/js/CalendarDrag.js \
src/www/js/CalendarEditor.js \
src/www/js/Calendar.js \
src/www/js/CalendarLayout.js \
src/www/js/CalendarView.js \
src/www/js/CalendarWidgets.js \
src/www/js/Composer.js \
src/www/js/Cookie.js \
src/www/js/Dragonfly.js \
src/www/js/Format.js \
src/www/js/Gettext.js \
src/www/js/BongoCalendar.js \
src/www/js/JCal.js \
src/www/js/Location.js \
src/www/js/Login.js \
src/www/js/MailConversationView.js \
src/www/js/Mail.js \
src/www/js/MailListView.js \
src/www/js/MailWidgets.js \
src/www/js/Calendar.js \
src/www/js/BongoCalendar.js \
src/www/js/CalendarEditor.js \
src/www/js/OccurrenceEditor.js \
src/www/js/Preferences.js \
src/www/js/Search.js \
src/www/js/CalendarView.js \
src/www/js/CalendarLayout.js \
src/www/js/CalendarDrag.js \
src/www/js/CalendarWidgets.js \
src/www/js/Summary.js \
src/www/js/Util.js \
src/www/js/ValidatingEntry.js \
src/www/js/Widgets.js \
src/www/js/Search.js \
src/www/js/Mail.js \
src/www/js/MailWidgets.js \
src/www/js/Composer.js \
src/www/js/MailConversationView.js \
src/www/js/MailListView.js \
src/www/js/Browser.js \
src/www/js/BrowserCheck.js
@@ -246,37 +247,38 @@ dist_prototype_DATA := \
mochidir = $(jsdir)/lib/MochiKit
# These *must* be in the order in which they get loaded in the browser/MochiKit
dist_mochi_DATA := \
src/www/js/lib/MochiKit/Base.js \
src/www/js/lib/MochiKit/Iter.js \
src/www/js/lib/MochiKit/Logging.js \
src/www/js/lib/MochiKit/DateTime.js \
src/www/js/lib/MochiKit/Format.js \
src/www/js/lib/MochiKit/Async.js \
src/www/js/lib/MochiKit/Base.js \
src/www/js/lib/MochiKit/Color.js \
src/www/js/lib/MochiKit/DateTime.js \
src/www/js/lib/MochiKit/DOM.js \
src/www/js/lib/MochiKit/Format.js \
src/www/js/lib/MochiKit/Iter.js \
src/www/js/lib/MochiKit/interpreter.js \
src/www/js/lib/MochiKit/Logging.js \
src/www/js/lib/MochiKit/LoggingPane.js \
src/www/js/lib/MochiKit/MochiKit.js \
src/www/js/lib/MochiKit/MochiKit-packed.js \
src/www/js/lib/MochiKit/MockDOM.js \
src/www/js/lib/MochiKit/__package__.js \
src/www/js/lib/MochiKit/Color.js \
src/www/js/lib/MochiKit/Signal.js \
src/www/js/lib/MochiKit/SimpleTest.js \
src/www/js/lib/MochiKit/Test.js \
src/www/js/lib/MochiKit/TestRunner.js \
src/www/js/lib/MochiKit/Visual.js
src/www/js/lib/MochiKit/Visual.js \
src/www/js/lib/MochiKit/MochiKit.js \
src/www/js/lib/MochiKit/interpreter.js
scriptaculousdir = $(jsdir)/lib/script.aculo.us
dist_scriptaculous_DATA := \
src/www/js/lib/script.aculo.us/builder.js \
src/www/js/lib/script.aculo.us/controls.js \
src/www/js/lib/script.aculo.us/dragdrop.js \
src/www/js/lib/script.aculo.us/effects.js \
src/www/js/lib/script.aculo.us/scriptaculous.js \
src/www/js/lib/script.aculo.us/slider.js \
src/www/js/lib/script.aculo.us/unittest.js
src/www/js/lib/script.aculo.us/effects.js
finaljsdir = $(jsdir)
dist_finaljs_DATA = \
src/www/js/final.js
compress_script := $(top_srcdir)/src/www/compress.py
src/www/js/final.js:
$(compress_script) $(dist_js_DATA) -o src/www/js/compiled.js -m -l 1 && \
$(compress_script) $(dist_prototype_DATA) $(dist_scriptaculous_DATA) $(dist_mochi_DATA) src/www/js/compiled.js -o src/www/js/final.js -q -l 0
install-data-local:: install-dist_htdocsDATA
ln -sf dragonfly.html "$(DESTDIR)$(htdocsdir)/index.html"
@@ -362,7 +364,8 @@ sbin_SCRIPTS += \
src/www/bongo-standalone
dist_noinst_SCRIPTS += \
src/www/l10n/props2json
src/www/l10n/props2json \
src/www/compress.py
templatesdir = $(pkgdatadir)/templates
+149
View File
@@ -0,0 +1,149 @@
#!/usr/bin/env python
#
# Compresses Javascript/CSS.
import re, sys, os
from optparse import OptionParser
class JavascriptCompressor(object):
def __init__(self, compressionLevel=2, removeLineBreaks=False):
self.compressionLevel = compressionLevel
self.removeLineBreaks = removeLineBreaks
# a bunch of regexes used in compression
# first, exempt string literals from compression by transient substitution
findLiterals = re.compile(r'(\'.*?(?<=[^\\])\')|(\".*?(?<=[^\\])\")')
stringMarker = '@s@t@r@'
backSubst = re.compile(stringMarker) # put the string literals back in
mlc = re.compile(r'/\*.*?\*\/', re.DOTALL) # remove multiline comments
slc = re.compile('\/\/.*') # remove single line comments
collapseWs = re.compile('(?<=\S)[ \t]+') # collapse successive non-leading white space characters into one
squeeze = re.compile(
'''
\s+(?=[\}\]\)]) | # remove whitespace including linebreaks preceding closing brackets or braces
(?<=[\{\;\,\(])\s+ | # ... or following such
[ \t]+(?=\W) | # remove spaces or tabs preceding non-word characters
(?<=\W)[ \t]+ # ... or following such. This also will remove leading whitespace
'''
, re.DOTALL | re.VERBOSE)
def compress(self, script):
'''
perform compression and return compressed script
'''
if not self.compressionLevel:
return script
# first, substitute string literals by placeholders to prevent the regexes messing with them
literals = []
def insertMarker(mo):
literals.append(mo.group())
return self.stringMarker
script = self.findLiterals.sub(insertMarker, script)
# now, to the literal-free carcass, apply some kludgy regexes for deflation...
script = self.slc.sub('', script) # remove single line comments
script = self.mlc.sub('\n', script) # replace multiline comments by newlines
script = self.collapseWs.sub(' ', script) # collapse multiple whitespace characters
# remove empty lines and trailing whitespace
script = '\n'.join([l.rstrip() for l in script.splitlines() if l.strip()])
if self.compressionLevel > 1:
script = self.squeeze.sub('', script) # squeeze out any dispensible white space
if self.removeLineBreaks:
script = script.replace('\n', '') # get rid of any new lines
# now back-substitute the string literals
literals.reverse()
script = self.backSubst.sub(lambda mo: literals.pop(), script)
return script
if __name__ == "__main__":
parser = OptionParser(version="%prog 1.0");
parser.add_option('-n', '--nolinebreaks',
dest='linebreaks',
action='store_true',
default=False,
help="remove all line breaks in the resulting file [default: %default]")
parser.add_option('-q', '--quiet',
dest='quiet',
action='store_true',
default=False,
help="be vewwy quiet!")
parser.add_option('-m', '--measure',
dest='measure',
default=False,
action='store_true',
help="print compression statistics")
parser.add_option('-o', '--output',
dest='output',
help="file to save resulting compressed javascript file(s) to")
parser.add_option('-l', '--level',
dest='compression',
default=1,
type='int',
help="level of compression (0 is none, 2 is maximum) [default: %default]")
(options, args) = parser.parse_args()
if options.compression > 2 or options.compression < 0:
print "Level of compression must be not be less than zero or more than two."
sys.exit(1)
if options.output and os.path.exists(options.output):
if options.quiet:
print "Warning: output file already exists - overwriting."
os.remove(options.output)
lengthBefore = 0
lengthAfter = 0
c = JavascriptCompressor(compressionLevel=options.compression, removeLineBreaks=options.linebreaks)
for arg in args:
fn = arg
if not options.quiet:
print "Compressing " + fn + "..."
try:
f = open(fn)
destfn = fn + '.compressed'
writemode = 'w'
if options.output:
destfn = options.output
writemode = 'a'
r = open(destfn, writemode)
try:
data = f.read()
lengthBefore += float(len(data))
cpr = c.compress(data)
lengthAfter += float(len(cpr))
r.write(cpr)
r.close()
finally:
f.close()
r.close()
except:
if not options.quiet:
print "Warning: failed to compress file " + fn + "."
if not options.quiet:
if options.measure:
# Print stats.
squeezeRate = int(100*(1-(lengthAfter/lengthBefore)))
kbsize = round((lengthBefore - lengthAfter) / 1024, 2)
print
print "Complete! (overall size reduction of %s" % squeezeRate + "% - " + str(kbsize) + "KB)"
elif lengthAfter != 0 and lengthBefore != 0:
print
print "Complete!"
else:
print "Error: no input files specified."
+2 -49
View File
@@ -15,12 +15,8 @@
@import url(css/contacts.css);
@import url(css/calendar.css);
@import url(css/summary.css);
@import url(css/modal.css);
@import url(css/tabs.css);
</style>
<style type="text/css" media="print">
@import url(css/print.css);
</style>
<style type="text/css" media="print">@import url(css/print.css);</style>
</head>
<body>
<!-- Javascript Warning -->
@@ -37,50 +33,7 @@
document.write ('<h1 id="loading">Loading...</h1>');
// -->
</script>
<script type="text/javascript" src="js/lib/prototype/prototype.js"></script>
<script type="text/javascript" src="js/lib/script.aculo.us/effects.js"></script>
<script type="text/javascript" src="js/lib/script.aculo.us/controls.js"></script>
<script type="text/javascript" src="js/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="js/lib/MochiKit/interpreter.js"></script>
<script type="text/javascript" src="js/Dragonfly.js"></script>
<script type="text/javascript" src="js/Format.js"></script>
<script type="text/javascript" src="js/Gettext.js"></script>
<script type="text/javascript" src="js/Cookie.js"></script>
<script type="text/javascript" src="js/Location.js"></script>
<script type="text/javascript" src="js/Login.js"></script>
<script type="text/javascript" src="js/Util.js"></script>
<script type="text/javascript" src="js/Widgets.js"></script>
<script type="text/javascript" src="js/ValidatingEntry.js"></script>
<script type="text/javascript" src="js/Preferences.js"></script>
<script type="text/javascript" src="js/Modal.js"></script>
<script type="text/javascript" src="js/AddressBook.js"></script>
<script type="text/javascript" src="js/JCal.js"></script>
<script type="text/javascript" src="js/Calendar.js"></script>
<script type="text/javascript" src="js/BongoCalendar.js"></script>
<script type="text/javascript" src="js/CalendarEditor.js"></script>
<script type="text/javascript" src="js/OccurrenceEditor.js"></script>
<script type="text/javascript" src="js/CalendarView.js"></script>
<script type="text/javascript" src="js/CalendarLayout.js"></script>
<script type="text/javascript" src="js/CalendarDrag.js"></script>
<script type="text/javascript" src="js/CalendarWidgets.js"></script>
<script type="text/javascript" src="js/Summary.js"></script>
<script type="text/javascript" src="js/Search.js"></script>
<script type="text/javascript" src="js/Mail.js"></script>
<script type="text/javascript" src="js/MailWidgets.js"></script>
<script type="text/javascript" src="js/Composer.js"></script>
<script type="text/javascript" src="js/MailConversationView.js"></script>
<script type="text/javascript" src="js/MailListView.js"></script>
<script type="text/javascript" src="js/final.js"></script>
<script language="javascript">
<!--
+1 -1
View File
@@ -444,4 +444,4 @@ Dragonfly.Calendar.monthDragMove = function (occurrence, pos, origin)
var state = Dragonfly.Calendar.dragstate;
state.buble.style.left = (pos.x - origin.x) + 'px';
state.buble.style.top = (pos.y - origin.y) + 'px';
}
};
+1
View File
@@ -916,6 +916,7 @@ Dragonfly.translateElements = function ()
Dragonfly.start = function ()
{
var d = Dragonfly;
var p = d.Preferences;
var c = d.Calendar;
+2 -2
View File
@@ -51,10 +51,10 @@ Dragonfly.login = function (user)
if (!d.authToken) {
d.authToken = btoa (user + ':');
}
d.setLoginMessage (_('loggingInMessage'));
d.setLoginDisabled (true);
p.load().addCallbacks (
function (prefs) {
return loginSucceeded ();
+9 -9
View File
@@ -136,7 +136,7 @@ Dragonfly.Preferences.reset = function()
var p = Dragonfly.Preferences;
p.prefs = deepclone (p.defaultPrefs);
p.save();
}
};
/*
Dragonfly.Preferences._lookup (obj, path)
@@ -159,7 +159,7 @@ Dragonfly.Preferences._lookup = function (obj, path)
} catch (e) {
return undefined;
}
}
};
/*
Dragonfly.Preferences.get (key)
@@ -194,7 +194,7 @@ Dragonfly.Preferences.get = function (key)
}
throw new Error ('Invalid Preference Key ' + key);
}
};
Dragonfly.Preferences.set = function (key, value)
{
@@ -207,7 +207,7 @@ Dragonfly.Preferences.set = function (key, value)
return p.save();
}
throw new Error ('Invalid Preference Key ' + key);
}
};
/*
The Preferences editor (the UI component)
@@ -303,7 +303,7 @@ Dragonfly.Preferences.Editor.build = function (loc)
}
logDebug('We just got built.');
}
};
Dragonfly.Preferences.Editor.save = function ()
@@ -315,7 +315,7 @@ Dragonfly.Preferences.Editor.save = function ()
d.Preferences.save();
this.dispose();
}
};
Dragonfly.Preferences.Editor.dispose = function ()
{
@@ -324,7 +324,7 @@ Dragonfly.Preferences.Editor.dispose = function ()
// Send user back to summary.
var loc = new d.Location({tab: 'summary'});
d.go('#' + loc);
}
};
Dragonfly.Preferences.Editor.load = function (loc, jsob)
{
@@ -336,7 +336,7 @@ Dragonfly.Preferences.Editor.load = function (loc, jsob)
$('from').value = jsob.mail.from;
logDebug('We just loaded.');
}
};
Dragonfly.Preferences.Editor.buildInterface = function (children, actions, observer)
{
@@ -360,4 +360,4 @@ Dragonfly.Preferences.Editor.buildInterface = function (children, actions, obser
Event.observe (ids[i], 'click', bind (clickHandler, observer || this));
logDebug('Done!');
}
}
};