grymt is a python tool that takes a directory full of .html, .css and .js and prepares the html for optimial production use.
For a teaser:
-
Look at the "output" (Note! You have to right-click and view source)
So why did I write my own tool and not use Grunt?!
Glad you asked! The reason is simple: I couldn't get Grunt to work.
Grunt is a framework. It's a place where you say which "recipes" to execute and how. It's effectively a common config framework. Like make.
However, I tried to set up a bunch of recipes in my Gruntfile.js and most of them worked well individually but it was a hellish nightmare to get it all to work together just the way I want it.
For example, the grunt-contrib-uglify is fine for doing the minification but it doesn't work with concatenation and it doesn't deal with taking one input file and outputting to a different file.
Basically, I spent two evenings getting things to work but I could never get exactly what I wanted. So I wrote my own and because I'm quite familiar with this kind of stuff, I did it in Python. Not because it's better than Node but just because I had it near by and was able to quicker build something.
So what sweet features do you get out of grymt?
-
You can easily make an output file have a hash in the filename. E.g.
vendor-$hash.min.js
becomesvendor-64f7425.min.js
and thus the filename is always unique but doesn't change in between deployments unless you change the files. -
It automatically notices which files already have been minified. E.g. no need to minify
somelib.min.js
but do minifyotherlib.js
. -
You can put
$git_revision
anywhere in your HTML and this gets expanded automatically. For example, view the source of buggy.peterbe.com and look at the first 20 lines. -
Images inside CSS get rewritten to have unique names (based on files' modified time) so they can be far-future cached aggresively too.
-
You never have to write down any lists of file names in soome Gruntfile.js equivalent file
-
It copies ALL files from a source directory. This is important in case you have something like this inside your javascript code:
$('<img>').attr('src', 'picture.jpg')
for example. -
You can chose to inline all the minified and concatenated CSS or javascript. Inlining CSS is neat for single page apps where you have a majority of primed cache hits. Instead of one .html and one .css you get just one .html and the amount of bytes is the same. Not having to do another HTTP request can save a lot of time on web performance.
-
The generated (aka. "dist" directory) contains everything you need. It does not refer back to the source directory in any way. This means you can set up your apache/nginx to point directly at the root of your "dist" directory.
So what's the catch?
-
It's not Grunt. It's not a framework. It does only what it does and if you want it to do more you have to work on grymt itself.
-
The files you want to analyze, process and output all have to be in a sub directory.
Look at how I've laid out the files here in this project for example. ALL files that you need is all in one sub-directory calledapp
. So, to rungrymt
I simply run:grymt app
. -
The HTML files you throw into it have to be plain HTML files. No templates for server-side code.
How do you use it?
pip install grymt
Then you need a directory it can process, e.g ./client/
(assumed to contain a .html file(s)).
grymt ./client
For more options, check out
grymt --help
What's in the future of grymt?
If people like it and want to add features, I'm more than happy to accept pull requests. Some future potential feature work:
-
I haven't needed it immediately, yet, myself, but it would be nice to add things like coffeescript, less, sass etc into pre-processing hooks.
-
It would be easy to automatically generate and insert a reference to a appcache manifest. Since every file used and mentioned is noticed, we could very accurately generate an appcache file that is less prone to human error.
-
Spitting out some stats about number bytes saved and number of files reduced.