Thu Feb 16 09:12:36 EST 2012

using application/ecmascript on nginx

So while I was browsing the Wikipedia article on Internet Media Types, (I am a very boring person) I noticed this:

  • application/ecmascript: ECMAScript/JavaScript; Defined in RFC 4329 (equivalent to application/javascript but with stricter processing rules)

Hey now, what's all this then? "Stricter processing rules?" I love stricter processing rules! Let's look at that RFC:

3.  Deployed Scripting Media Types and Compatibility

   Various unregistered media types have been used in an ad-hoc fashion
   to label and exchange programs written in ECMAScript and JavaScript.
   These include:

      | text/javascript          | text/ecmascript          |
      | text/javascript1.0       | text/javascript1.1       |
      | text/javascript1.2       | text/javascript1.3       |
      | text/javascript1.4       | text/javascript1.5       |
      | text/jscript             | text/livescript          |
      | text/x-javascript        | text/x-ecmascript        |
      | application/x-javascript | application/x-ecmascript |
      | application/javascript   | application/ecmascript   |

So, it looks like a typical web "standards" clusterfuck. I had been wondering why nginx served Javascript with the application/x-javascript mime-type, which was used for non-standard protocols, and now I know.

The only use of JavaScript on, prettify.js, a Javascript-based code prettyprinting package, is actually a prime use for bleeding edge standards wankery. Code highlighting is pure progressive enhancement so the readers still using IE6 on their 2002-vintage PowerPC iMacs shouldn't miss anything.

(My prettify.js implementation is actually backported from my low-signal, high-noise adjunct blog, where I wrote a pair of posts on the topic.)

Enabling it on nginx is fairly easy. Just add a line to /etc/nginx/mime.types:

    application/ecmascript                es;

This will deliver any file with the .es extension as application/ecmascript, which should Just Work in any modern browser. Pow! Whammo! Easy!

However, nginx by default will serve it uncompressed, and with a fairly short cache lifetime. Let's change that.

First, add application/ecmascript to wherever you keep your gzip_type declarations. (In my case, conf.d/compression.conf ) Next, tell nginx to deliver it with the proper cache headers. In my case, I already had a location{} block inside my server{} virtual host block that did that for a bunch of filetypes, so I added es to it:

location ~* \.(?:ico|css|js|gif|jpe?g|png|es)$ {
  expires max;
  add_header Cache-Control public;

This matches against a bunch of extensions, (including both jpg and jpeg) and delivers them with the Cache-Control: public header, as well as the maximum allowable time for the Expires header, which for nginx is Thu, 31 Dec 2037 23:55:55 GMT. This is a bit silly, since any browser will request a new copy long, long before the year 2037, but hey, why the hell not. Here's what the complete headers look like now:

bbot@neon:~$ curl -I --compressed
HTTP/1.1 200 OK
Server: nginx/1.1.8
Date: Thu, 16 Feb 2012 13:48:01 GMT
Content-Type: application/ecmascript
Last-Modified: Thu, 16 Feb 2012 12:53:10 GMT
Connection: keep-alive
Vary: Accept-Encoding
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Cache-Control: public
Content-Encoding: gzip

Posted by | Permanent link | File under: important, Linux