Chapter 8, Exercise 3 – Minifying JavaScript

Find and test some online minifier and obfuscation services. Compare the file size of the output code to the size of the original source.

Taking game.js and running it through Google’s Closure compiler at http://closure-compiler.appspot.com/ gives the following:

var BubbleShoot=window.BubbleShoot||{}; BubbleShoot.Game=function(d){window.requestAnimationFrame=Modernizr.prefixed("requestAnimationFrame",window)||function(d){window.setTimeout(function(){d()},40)};return function(){var g,e,l,m=[],n=0,h=0,f=0,p;this.init=function(){BubbleShoot.Renderer?BubbleShoot.Renderer.init(function(){d(".but_start_game").click("click",q)}):d(".but_start_game").click("click",q);window.localStorage&&localStorage.getItem("high_score")&&(f=parseInt(localStorage.getItem("high_score")));BubbleShoot.ui.drawHighScore(f)}; var q=function(){d(".but_start_game").unbind("click");l=70-5*n;BubbleShoot.ui.hideDialog();e=new BubbleShoot.Board;m=e.getBubbles();BubbleShoot.Renderer?p||(p=requestAnimationFrame(t)):BubbleShoot.ui.drawBoard(e);g=u();d("#game").bind("click",w);BubbleShoot.ui.drawScore(h);BubbleShoot.ui.drawLevel(n)},u=function(){var b=BubbleShoot.Bubble.create();m.push(b);b.setState(BubbleShoot.BubbleState.CURRENT);b.getSprite().addClass("cur_bubble");var c=(d("#board").width()-BubbleShoot.ui.BUBBLE_DIMS)/2;b.getSprite().css({top:470, left:c});d("#board").append(b.getSprite());BubbleShoot.ui.drawBubblesRemaining(l);l--;return b},w=function(b){var c=BubbleShoot.ui.getBubbleAngle(g.getSprite(),b);b=750;var a=BubbleShoot.CollisionDetector.findIntersection(g,e,c);if(a){var d=a.coords;b=Math.round(b*a.distToCollision/1E3);e.addBubble(g,d);c=e.getGroup(g,{});if(3<=c.list.length){v(c.list,b);for(var a=e.getRows()[0],k=[],f=0;f<a.length;f++)a[f]&&k.push(a[f]);5>=k.length&&(v(k,b),c.list.concat(k));k=e.findOrphans();a=b+200+30*c.list.length; x(k,a);c=50*[].concat(c.list,k).length;h+=c;setTimeout(function(){BubbleShoot.ui.drawScore(h)},a)}}else d=1E3*Math.sin(c),c=1E3*Math.cos(c),a=BubbleShoot.ui.getBubbleCoords(g.getSprite()),d={x:a.left+d,y:a.top-c};BubbleShoot.ui.fireBubble(g,d,b);11<e.getRows().length?r(!1):0==l?r(!1):e.isEmpty()?r(!0):g=u(e)},v=function(b,c){d.each(b,function(){var a=this;setTimeout(function(){a.setState(BubbleShoot.BubbleState.POPPING);a.animatePop();setTimeout(function(){a.setState(BubbleShoot.BubbleState.POPPED)}, 200);BubbleShoot.Sounds.play("_mp3/pop.mp3",.5*Math.random()+.5)},c);e.popBubbleAt(this.getRow(),this.getCol());setTimeout(function(){a.getSprite().remove()},c+200);c+=60})},x=function(b,c){d.each(b,function(){var a=this;e.popBubbleAt(a.getRow(),a.getCol());setTimeout(function(){a.setState(BubbleShoot.BubbleState.FALLING);a.getSprite().kaboom({callback:function(){a.getSprite().remove();a.setState(BubbleShoot.BubbleState.FALLEN)}})},c)})},t=function(){d.each(m,function(){this.getSprite().updateFrame&& this.getSprite().updateFrame()});BubbleShoot.Renderer.render(m);p=requestAnimationFrame(t)},r=function(b){h>f?(f=h,d("#new_high_score").show(),BubbleShoot.ui.drawHighScore(f),window.localStorage&&localStorage.setItem("high_score",f)):d("#new_high_score").hide();b?n++:n=h=0;d(".but_start_game").click("click",q);d("#board .bubble").remove();BubbleShoot.ui.endGame(b,h)}}}(jQuery);

This is reported as a saving of 45%, and the code is certainly going to be more difficult to read if someone wants to cheat. Make sure you keep un-minified versions of your code otherwise you’re going to have a lot of trouble making changes to the game in the future!

Leave a Reply