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 toapplication/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 bbot.org, 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 bbot.org/prettify.es 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