Edgewall Software

Opened 12 years ago

Last modified 3 years ago

#10672 new enhancement

Automatically minify Javascript and CSS — at Version 7

Reported by: Peter Suter Owned by:
Priority: normal Milestone: next-dev-1.7.x
Component: general Version:
Severity: normal Keywords: javascript css performance
Cc: Ryan J Ollos, leho@…, olemis+trac@…, felix.schwarz@… Branch:
Release Notes:
API Changes:
Internal Changes:

Description (last modified by Peter Suter)

As discussed previously it might be a good idea to introduce a minification step that pre-processes the JavaScript and CSS files stored in source control.

This would allow developing with clean, well-commented source files while improving performance. We could then switch our JavaScript coding style to 4 spaces indentation and add copyright and documentation comments to file headers. (See #10802)

The step / a related step could do JSLint checking.

How should this be implemented?

  • One suggestion was a make minify step.
  • Another idea would be to add it to setup.py. minify or distwebres provide setuptools commands (both use YUI compressor, which requires Java)
  • Alternatively, we could hook it into trac-admin deploy somehow.
  • Or the web frontend could dynamically minify and cache and combine just the files required for a request into one file. (Including scripts by plugins.)

An important requirement might be to keep this step optional.

Change History (8)

comment:1 by Christian Boos, 12 years ago

Good idea! I had a run of the YUI compressor and indeed, this cuts the size of our .js by a half. The .css could also be shrinked down, though the savings are less important.

.js:

File Original size Minified size % of the original
auto_preview.js 4952 1650 33%
babel.js 4747 1406 29%
blame.js 3749 1474 39%
diff.js 4713 2361 50%
expand_dir.js 6321 2542 40%
folding.js 3022 1260 41%
keyboard_nav.js 2819 1230 43%
log_graph.js 1223 649 53%
noconflict.js 228 20 8%
query.js 18270 8405 46%
resizer.js 968 585 60%
search.js 3233 1674 51%
suggest.js 4257 2018 47%
threaded_comments.js 3336 1752 52%
timeline_multirepos.js 267 157 58%
trac.js 3703 2067 55%
wikitoolbar.js 3101 1708 55%
workflow_graph.js 8192 4236 51%

For the messages/*.js, the savings are marginal, between 93% and 97% of the original.

.css:

File Original size Minified size % of the original
about.css 767 667 86%
admin.css 3114 2575 82%
browser.css 6698 5285 78%
changeset.css 942 776 82%
code.css 4672 3855 82%
diff.css 5031 4068 80%
jquery-ui-addons.css 563 428 76%
prefs.css 989 869 87%
report.css 7990 6717 84%
roadmap.css 2901 2356 81%
search.css 605 531 87%
ticket.css 4715 4089 86%
timeline.css 2947 2332 79%
trac.css 18764 15417 82%
wiki.css 3021 2352 77%

As for the tool, minify seems to be the most convenient, as when you easy_install it, it also downloads the YUI compressor. distwebres can't (yet?) be easy_installed.

Also, I think the best solution would be to do this minification step at deploy time, as this will enable us to minify the resources from plugins as well. The .css and .js files would be minified before being copied in to the deploy location (in _do_deploy).

For the last step you suggested, minify and combine on the fly, I'm not sure it's worth the effort, as going through Python for serving .js and .css, no matter what optimization we do at that level, is probably less efficient than letting directly the front-end serve them. And the front-end itself might be able to do such things and more (e.g. mod_pagespeed).

by Christian Boos, 12 years ago

implementing the suggestion of minifying during deployment

in reply to:  1 comment:2 by Christian Boos, 12 years ago

Replying to cboos:

As for the tool, minify seems to be the most convenient, as when you easy_install it, it also downloads the YUI compressor. distwebres can't (yet?) be easy_installed.

Well, as I quickly found out when implementing the above idea, pipy:minify is just a setuptools wrapper for pipy:yuicompressor. If we don't do the minification via setup.py but rather at deploy time, only the latter is necessary (and only to the extent it simplifies the setup, as then it's only a matter of doing an easy_install yuicompressor; we could consider the alternative of asking people to specify the path to their yuicompressor-...jar but people are lazy, downloading, unpacking the YUI compressor and specifying the path is probably goinf to be overkill ;-) ).

comment:3 by Peter Suter, 12 years ago

Very nice!

Two small suggestions:

  • Print some informative message if minification fails, like "Minification of %(filename)s failed. easy_install yuicompressor and java in path are required."
  • yuicompress_all_but_jquery: Is this because jQuery is already minified? Would it make sense to detect a -min suffix instead of a jquery prefix?

in reply to:  3 comment:4 by Christian Boos, 12 years ago

Replying to psuter:

Very nice!

Thanks!

Two small suggestions:

  • Print some informative message if minification fails, like "Minification of %(filename)s failed. easy_install yuicompressor and java in path are required."

Ok, I agree some error reporting can be useful. Added this and also improved the command help, see [f187f18d/cboos.git] and previous.

  • yuicompress_all_but_jquery: Is this because jQuery is already minified? Would it make sense to detect a -min suffix instead of a jquery prefix?

Yes, this is also a good idea: some jquery... files could benefit from minification, and it's nice to be able to tell plugin authors "if you don't want a specific resources to be minified, make sure it ends up with .min.{css,js}". Only problem was for jquery-ui.css, which is not minified (so I didn't want to add .min to the name) but nevertheless should be excluded (as it triggers an error). I now explicitly blacklist that one.

comment:5 by Peter Suter, 12 years ago

Tiny correction:

-log("Package yuicompress is not installed")
+log("Package yuicompressor is not installed")

comment:6 by Christian Boos, 12 years ago

On second thought, I'll rework this to make it an optional component, it's not appropriate to make the core refer to one particular external package. The only drawback is that I think we'll lose the possibility to have a --minify parameter to deploy and instead we'll have to rely on the component being enabled or not.

comment:7 by Peter Suter, 12 years ago

Description: modified (diff)

Subsequent cleanup task extracted to #10802.

Note: See TracTickets for help on using tickets.