Symphonious

Living in a state of accord.

Uglify/Uglify2, Rickshaw, Requirejs and Minification

If you have:

  • A javascript project using require.js
  • Which is optimised using r.js
  • Includes Rickshaw or any other library that uses the prototype class system

Then you are very likely here because you’re trying to enable JavaScript optimization (minification) and finding that suddenly stuff breaks.

The problem is that the prototype class system allows overriding methods to call the original method by adding a $super as the first parameter to the function. From the prototype docs:

When you override a method in a subclass, but still want to be able to call the original method, you will need a reference to it. You can obtain that reference by defining those methods with an extra argument in the front: $super. Prototype will detect this and make the overridden method available to you through that argument. But to the outside world, the Pirate#say method still expects a single argument. Keep this in mind.

The problem is, the first parameter has to be called $super but enabling optimization causes it to be renamed to something shorter, thus breaking prototype’s class system.

The solution, which is easy to find on the internet is to exclude the $super parameter from renaming. What’s not as obvious to find is the exact way to do that since it depends on which optimization engine you’re using.

For uglify, you’re build.js should look a bit like:

({
  ...
  optimize: 'uglify',
  uglify: {
    except: ["$super"]
  },
  ...
})

 For uglify2, you’ll want:

({
  ...
  optimize: 'uglify2',
  uglify2: {
    mangle: {
      except: ["$super"]
    }
  },
  ...
})

 I’d highly recommend using uglify2 and then also enabling source maps with:

({
  ...
  generateSourceMaps: true,
  preserveLicenseComments: false,
  optimize: 'uglify2',
  uglify2: {
    mangle: {
      except: ["$super"]
    }
  }
  ...
})

The key part of getting configuration working for the optimizer is to get the magical nesting level right – lots of places point you towards the “except” config you need, but most put it in the wrong place so it has no effect.

How To Round-Trip Data Via SSH

I keep forgetting this so for the record, you can use SSH to round trip data out to a remote server and back to your own box.  This is most useful for adding latency and bandwidth limitations to a connection when doing website testing.  The trick is to use both local and remote port forwards:

ssh -L 9090:localhost:9091 -R 9091:localhost:80 remote.server.com

The -L argument starts listening on port 9090 locally and sends all that traffic to port 9091 on the remote server (the domain name, localhost, is resolved by the remote server so it refers to the remote server, not your local machine).  Then the -R argument listens on port 9091 of the remote server and forwards all that traffic back to your machine’s port 80 (here localhost is resolved on your local machine).

You don’t have to use localhost as the domain name. For example, if the site you want to test is deployed on your intranet at testmachine.intranet which remote.server.com doesn’t have access to, you could use:

ssh -L 9090:localhost:9091 -R 9091:testmachine.intranet:80 remote.server.com

Or if the test site is publicly available you can do it all without the -R argument:

ssh -L 9090:testmachine.com:80 remote.server.com

In all these cases, you connect to localhost:9090 to utilise the tunnel.

Who’s Committed in my Git Repository?

Note to self: if you ever want to get a simple list of people who have committed to a git repository, the command you want is:

git log --format='%aN <%ae>' | sort -u | uniq

Or for just the e-mail address:

git log --format='%ae' | sort -u | uniq

Or for just the name:

git log --format='%aN' | sort -u | uniq

This is in the help manual but it’s way down the bottom so takes ages to read through to find it.