SlimIt - JavaScript minifier
Project description
_____ _ _____ __ __ _____ _______ / ____| | |_ _| \/ |_ _|__ __| | (___ | | | | | \ / | | | | | \___ \| | | | | |\/| | | | | | ____) | |____ _| |_| | | |_| |_ | | |_____/|______|_____|_| |_|_____| |_|
Welcome to SlimIt
SlimIt is a JavaScript minifier written in Python. It compiles JavaScript into more compact code so that it downloads and runs faster.
SlimIt also provides a library that includes a JavaScript parser, lexer, pretty printer and a tree visitor.
http://slimit.readthedocs.org/
Installation
$ [sudo] pip install slimit
Or the bleeding edge version from the git master branch:
$ [sudo] pip install git+https://github.com/rspivak/slimit.git#egg=slimit
There is also an official DEB package available at http://packages.debian.org/sid/slimit
Let’s minify some code
From the command line:
$ slimit -h Usage: slimit [options] [input file] If no input file is provided STDIN is used by default. Minified JavaScript code is printed to STDOUT. Options: -h, --help show this help message and exit -m, --mangle mangle names -t, --mangle-toplevel mangle top level scope (defaults to False) $ cat test.js var foo = function( obj ) { for ( var name in obj ) { return false; } return true; }; $ $ slimit --mangle < test.js var foo=function(a){for(var b in a)return false;return true;};
Or using library API:
>>> from slimit import minify >>> text = """ ... var foo = function( obj ) { ... for ( var name in obj ) { ... return false; ... } ... return true; ... }; ... """ >>> print minify(text, mangle=True, mangle_toplevel=True) var a=function(a){for(var b in a)return false;return true;};
Iterate over, modify a JavaScript AST and pretty print it
>>> from slimit.parser import Parser >>> from slimit.visitors import nodevisitor >>> from slimit import ast >>> >>> parser = Parser() >>> tree = parser.parse('for(var i=0; i<10; i++) {var x=5+i;}') >>> for node in nodevisitor.visit(tree): ... if isinstance(node, ast.Identifier) and node.value == 'i': ... node.value = 'hello' ... >>> print tree.to_ecma() # print awesome javascript :) for (var hello = 0; hello < 10; hello++) { var x = 5 + hello; } >>>
Writing custom node visitor
>>> from slimit.parser import Parser >>> from slimit.visitors.nodevisitor import ASTVisitor >>> >>> text = """ ... var x = { ... "key1": "value1", ... "key2": "value2" ... }; ... """ >>> >>> class MyVisitor(ASTVisitor): ... def visit_Object(self, node): ... """Visit object literal.""" ... for prop in node: ... left, right = prop.left, prop.right ... print 'Property key=%s, value=%s' % (left.value, right.value) ... # visit all children in turn ... self.visit(prop) ... >>> >>> parser = Parser() >>> tree = parser.parse(text) >>> visitor = MyVisitor() >>> visitor.visit(tree) Property key="key1", value="value1" Property key="key2", value="value2"
Using lexer in your project
>>> from slimit.lexer import Lexer >>> lexer = Lexer() >>> lexer.input('a = 1;') >>> for token in lexer: ... print token ... LexToken(ID,'a',1,0) LexToken(EQ,'=',1,2) LexToken(NUMBER,'1',1,4) LexToken(SEMI,';',1,5)
You can get one token at a time using token method:
>>> lexer.input('a = 1;') >>> while True: ... token = lexer.token() ... if not token: ... break ... print token ... LexToken(ID,'a',1,0) LexToken(EQ,'=',1,2) LexToken(NUMBER,'1',1,4) LexToken(SEMI,';',1,5)
LexToken instance has different attributes:
>>> lexer.input('a = 1;') >>> token = lexer.token() >>> token.type, token.value, token.lineno, token.lexpos ('ID', 'a', 1, 0)
Benchmarks
SAM - JQuery size after minification in bytes (the smaller number the better)
Original jQuery 1.6.1 (bytes) |
SlimIt SAM |
rJSmin SAM |
jsmin SAM |
---|---|---|---|
234,995 |
94,290 |
134,215 |
134,819 |
Roadmap
when doing name mangling handle cases with ‘eval’ and ‘with’
foo[“bar”] ==> foo.bar
consecutive declarations: var a = 10; var b = 20; ==> var a=10,b=20;
reduce simple constant expressions if the result takes less space: 1 +2 * 3 ==> 7
IF statement optimizations
if (foo) bar(); else baz(); ==> foo?bar():baz();
if (!foo) bar(); else baz(); ==> foo?baz():bar();
if (foo) bar(); ==> foo&&bar();
if (!foo) bar(); ==> foo||bar();
if (foo) return bar(); else return baz(); ==> return foo?bar():baz();
if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}
remove unreachable code that follows a return, throw, break or continue statement, except function/variable declarations
parsing speed improvements
Acknowledgments
License
The MIT License (MIT)
Change History
0.8.1 (2013-03-26)
Bug fix: https://github.com/rspivak/slimit/pull/45 Fix syntax error in the output of for statement with some form of expressions
0.8.0 (2013-03-23)
Python 3.x support
Bug fix: https://github.com/rspivak/slimit/issues/42 slimit removes parentheses from ternary expression, causes syntax error in jQuery
Bug fix: https://github.com/rspivak/slimit/issues/37 simple identifier in FOR init
Bug fix: https://github.com/rspivak/slimit/issues/36 using $ for mangled function names conflicts with jQuery
0.7.4 (2012-06-5)
Bug fix: https://github.com/rspivak/slimit/issues/34 ‘class’ is reserved keyword now
0.7.3 (2012-05-21)
Bug fix (unary op in FOR init): https://github.com/rspivak/slimit/pull/33
0.7.2 (2012-05-17)
Added support for get/set properties: https://github.com/rspivak/slimit/issues/32
0.7.1 (2012-05-10)
Function call support in FOR init section: https://github.com/rspivak/slimit/pull/31
0.7 (2012-04-16)
Multiline string support: https://github.com/rspivak/slimit/issues/24
0.6.2 (2012-04-07)
0.6.1 (2012-03-15)
Added command-line option -t/–mangle-toplevel to turn on global scope name mangling. As of this version it’s off by default: https://github.com/rspivak/slimit/issues/27
Removed dependency on a ‘distribute’ package
0.6 (2012-02-04)
Added optimization: foo[“bar”] ==> foo.bar
Added base class for custom AST node visitors
Documentation updates
0.5.5 (2011-10-05)
0.5.4 (2011-10-01)
Bugfix: https://github.com/rspivak/slimit/issues/6 Division with “this” fails
0.5.3 (2011-06-29)
0.5.2 (2011-06-14)
0.5.1 (2011-06-06)
0.5 (2011-06-06)
Added name mangling
0.4 (2011-05-12)
Minify more by removing block braces { }
More tests
0.3.2 (2011-05-09)
More hacks to use pre-generated lex and yacc tables when called from the command line
0.3.1 (2011-05-09)
Use pre-generated lex and yacc tables when called from the command line
0.3 (2011-05-09)
Added minifier
0.2 (2011-05-07)
Added a JavaScript parser
Added pretty printer
Added node visitor
0.1 (2011-05-02)
Initial public version. It contains only a JavaScript lexer
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.