Skip to main content

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

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

    1. if (foo) bar(); else baz(); ==> foo?bar():baz();

    2. if (!foo) bar(); else baz(); ==> foo?baz():bar();

    3. if (foo) bar(); ==> foo&&bar();

    4. if (!foo) bar(); ==> foo||bar();

    5. if (foo) return bar(); else return baz(); ==> return foo?bar():baz();

    6. 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

  • The lexer and parser are built with PLY

  • Several test cases and regexes from jslex

  • Some visitor ideas - pycparser

  • Many grammar rules are taken from rkelly

  • Name mangling and different optimization ideas - UglifyJS

  • ASI implementation was inspired by pyjsparser

License

The MIT License (MIT)

Change History

0.7.1 (2012-05-10)

0.7 (2012-04-16)

0.6.2 (2012-04-07)

0.6.1 (2012-03-15)

0.6 (2012-02-04)

0.5.5 (2011-10-05)

0.5.4 (2011-10-01)

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

slimit-0.7.1.zip (85.0 kB view details)

Uploaded Source

slimit-0.7.1.tar.gz (63.7 kB view details)

Uploaded Source

File details

Details for the file slimit-0.7.1.zip.

File metadata

  • Download URL: slimit-0.7.1.zip
  • Upload date:
  • Size: 85.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for slimit-0.7.1.zip
Algorithm Hash digest
SHA256 353b9c29bb6e5d188cee5699fc392a6cd0cc9acacbfc09b7b62808599a36be6d
MD5 c792712cb2ba13497ea4a0ea01f4a5ba
BLAKE2b-256 00a409391826702c2869142be2699f1fc5586fdd860ef6cff4926f23405d057f

See more details on using hashes here.

File details

Details for the file slimit-0.7.1.tar.gz.

File metadata

  • Download URL: slimit-0.7.1.tar.gz
  • Upload date:
  • Size: 63.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for slimit-0.7.1.tar.gz
Algorithm Hash digest
SHA256 6e9a0d078fc3181ef2794feae300b50a1207b4e0a4bdc2754fd65e8866e66c59
MD5 ddf3608f6b7782539e08c2d60adeca1b
BLAKE2b-256 1ce35bdda5e98880fd3a48c42e8b175a6191ec2297946547ccc2c1e604d1b8de

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page