Permalink
Browse files

Added the `minify` setting, which uses uglify-js to minify the outputs

of `serve zappa`, `client`, `shared`, `coffee` and `js`.

Closes #70 (thanks @jacobrask).
  • Loading branch information...
1 parent 9f18bcb commit 3a77b2d3a808e7448dfa9f586801118b7d41e35e @mauricemach mauricemach committed Sep 7, 2011
Showing with 65 additions and 7 deletions.
  1. +3 −1 CHANGELOG.md
  2. +4 −0 docs/reference.md
  3. +17 −3 docs/zappa.html
  4. +2 −1 package.json
  5. +15 −1 src/zappa.coffee
  6. +24 −1 tests/assets.coffee
View
@@ -4,7 +4,7 @@
- Fixed: inline templates with multiple apps.
- - Added `stylus` to the root scope.
+ - Added `stylus` to the root scope (compiles string with stylus and serves it as css).
- Fixed #58: multiple socket events fail. Also applied the same fix to helpers.
@@ -13,6 +13,8 @@
- Fixed #64: require does not pick up node_modules in app dir. [Jason King]
- Added: setting views dir to `__dirname + '/views'` by default. Closes #71. [rachel-carvalho]
+
+ - Added the `minify` setting, which uses uglify-js to minify the outputs of `serve zappa`, `client`, `shared`, `coffee` and `js`. Closes #70 (thanks @jacobrask).
**v0.2.0beta** (2011-08-02):
View
@@ -481,6 +481,10 @@ Serves `/zappa/jquery.js` (minified jQuery 1.6.2 from npm).
Serves `/zappa/sammy.js` (minified Sammy 0.6.3).
+### minify
+
+Uses uglify-js to minify the outputs of `serve zappa`, `client`, `shared`, `coffee` and `js`.
+
### default layout
If enabled, zappa adds the following template with the name `layout`:
View
@@ -11,7 +11,8 @@
<span class="nv">socketio = </span><span class="nx">require</span> <span class="s1">&#39;socket.io&#39;</span>
<span class="nv">jsdom = </span><span class="nx">require</span> <span class="s1">&#39;jsdom&#39;</span>
<span class="nv">jquery = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">&#39;/../node_modules/jquery/dist/node-jquery.min.js&#39;</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span>
-<span class="nv">sammy = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">&#39;/../vendor/sammy-latest.min.js&#39;</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>CoffeeScript-generated JavaScript may contain anyone of these; when we "rewrite"
+<span class="nv">sammy = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">&#39;/../vendor/sammy-latest.min.js&#39;</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span>
+<span class="nv">uglify = </span><span class="nx">require</span> <span class="s1">&#39;uglify-js&#39;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>CoffeeScript-generated JavaScript may contain anyone of these; when we "rewrite"
a function (see below) though, it loses access to its parent scope, and consequently to
any helpers it might need. So we need to reintroduce these helpers manually inside any
"rewritten" function.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">coffeescript_helpers = </span><span class="s2">&quot;&quot;&quot;</span>
@@ -36,7 +37,13 @@
<span class="nv">code = </span><span class="s2">&quot;#{coffeescript_helpers}return (#{code}).apply(context, args);&quot;</span>
<span class="k">for</span> <span class="nx">name</span> <span class="k">in</span> <span class="nx">locals_names</span>
<span class="nv">code = </span><span class="s2">&quot;var #{name} = locals.#{name};&quot;</span> <span class="o">+</span> <span class="nx">code</span>
- <span class="k">new</span> <span class="nb">Function</span><span class="p">(</span><span class="s1">&#39;context&#39;</span><span class="p">,</span> <span class="s1">&#39;locals&#39;</span><span class="p">,</span> <span class="s1">&#39;args&#39;</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Builds an array of unique names from the desired scopes.
+ <span class="k">new</span> <span class="nb">Function</span><span class="p">(</span><span class="s1">&#39;context&#39;</span><span class="p">,</span> <span class="s1">&#39;locals&#39;</span><span class="p">,</span> <span class="s1">&#39;args&#39;</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span>
+
+<span class="nv">minify = </span><span class="nf">(js) -&gt;</span>
+ <span class="nv">ast = </span><span class="nx">uglify</span><span class="p">.</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">js</span><span class="p">)</span>
+ <span class="nv">ast = </span><span class="nx">uglify</span><span class="p">.</span><span class="nx">uglify</span><span class="p">.</span><span class="nx">ast_mangle</span><span class="p">(</span><span class="nx">ast</span><span class="p">)</span>
+ <span class="nv">ast = </span><span class="nx">uglify</span><span class="p">.</span><span class="nx">uglify</span><span class="p">.</span><span class="nx">ast_squeeze</span><span class="p">(</span><span class="nx">ast</span><span class="p">)</span>
+ <span class="nx">uglify</span><span class="p">.</span><span class="nx">uglify</span><span class="p">.</span><span class="nx">gen_code</span><span class="p">(</span><span class="nx">ast</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Builds an array of unique names from the desired scopes.
Ex.: select names, 'http + defs + helpers'</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">select = </span><span class="nf">(names, scopes) -&gt;</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">union</span> <span class="p">(</span><span class="nx">names</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="k">for</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">scopes</span><span class="p">.</span><span class="nx">split</span> <span class="s1">&#39; + &#39;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>The stringified zappa client.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">client = </span><span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./client&#39;</span><span class="p">).</span><span class="nx">build</span><span class="p">(</span><span class="nx">zappa</span><span class="p">.</span><span class="nx">version</span><span class="p">,</span> <span class="nx">coffeescript_helpers</span><span class="p">,</span> <span class="nx">rewrite_function</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Keep inline views at the module level and namespaced by app id
so that the monkeypatched express can look them up.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">views = </span><span class="p">{}</span>
@@ -111,16 +118,19 @@
<span class="nx">app</span><span class="p">.</span><span class="nx">enable</span> <span class="s1">&#39;serve zappa&#39;</span>
<span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">obj</span>
<span class="nv">js = </span><span class="s2">&quot;;zappa.run(#{v});&quot;</span>
+ <span class="nv">js = </span><span class="nx">minify</span><span class="p">(</span><span class="nx">js</span><span class="p">)</span> <span class="k">if</span> <span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">[</span><span class="s1">&#39;minify&#39;</span><span class="p">]</span>
<span class="nx">routes</span><span class="p">.</span><span class="nx">push</span> <span class="nv">verb: </span><span class="s1">&#39;get&#39;</span><span class="p">,</span> <span class="nv">path: </span><span class="nx">k</span><span class="p">,</span> <span class="nv">handler: </span><span class="nx">js</span><span class="p">,</span> <span class="nv">contentType: </span><span class="s1">&#39;js&#39;</span>
<span class="nv">root_locals.coffee = </span><span class="nf">(obj) -&gt;</span>
<span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">obj</span>
<span class="nv">js = </span><span class="s2">&quot;;#{coffeescript_helpers}(#{v})();&quot;</span>
+ <span class="nv">js = </span><span class="nx">minify</span><span class="p">(</span><span class="nx">js</span><span class="p">)</span> <span class="k">if</span> <span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">[</span><span class="s1">&#39;minify&#39;</span><span class="p">]</span>
<span class="nx">routes</span><span class="p">.</span><span class="nx">push</span> <span class="nv">verb: </span><span class="s1">&#39;get&#39;</span><span class="p">,</span> <span class="nv">path: </span><span class="nx">k</span><span class="p">,</span> <span class="nv">handler: </span><span class="nx">js</span><span class="p">,</span> <span class="nv">contentType: </span><span class="s1">&#39;js&#39;</span>
<span class="nv">root_locals.js = </span><span class="nf">(obj) -&gt;</span>
<span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">obj</span>
<span class="nv">js = </span><span class="nb">String</span><span class="p">(</span><span class="nx">v</span><span class="p">)</span>
+ <span class="nv">js = </span><span class="nx">minify</span><span class="p">(</span><span class="nx">js</span><span class="p">)</span> <span class="k">if</span> <span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">[</span><span class="s1">&#39;minify&#39;</span><span class="p">]</span>
<span class="nx">routes</span><span class="p">.</span><span class="nx">push</span> <span class="nv">verb: </span><span class="s1">&#39;get&#39;</span><span class="p">,</span> <span class="nv">path: </span><span class="nx">k</span><span class="p">,</span> <span class="nv">handler: </span><span class="nx">js</span><span class="p">,</span> <span class="nv">contentType: </span><span class="s1">&#39;js&#39;</span>
<span class="nv">root_locals.css = </span><span class="nf">(obj) -&gt;</span>
@@ -199,6 +209,7 @@
<span class="nx">app</span><span class="p">.</span><span class="nx">enable</span> <span class="s1">&#39;serve zappa&#39;</span>
<span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">obj</span>
<span class="nv">js = </span><span class="s2">&quot;;zappa.run(#{v});&quot;</span>
+ <span class="nv">js = </span><span class="nx">minify</span><span class="p">(</span><span class="nx">js</span><span class="p">)</span> <span class="k">if</span> <span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">[</span><span class="s1">&#39;minify&#39;</span><span class="p">]</span>
<span class="nx">routes</span><span class="p">.</span><span class="nx">push</span> <span class="nv">verb: </span><span class="s1">&#39;get&#39;</span><span class="p">,</span> <span class="nv">path: </span><span class="nx">k</span><span class="p">,</span> <span class="nv">handler: </span><span class="nx">js</span><span class="p">,</span> <span class="nv">contentType: </span><span class="s1">&#39;js&#39;</span>
<span class="nv">rewritten_shared = </span><span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + root + externals&#39;</span><span class="p">)</span>
@@ -227,9 +238,12 @@
<span class="nx">postrenders</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rewrite_function</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">select</span> <span class="nx">names</span><span class="p">,</span> <span class="s1">&#39;globals + postrender + externals + helpers + defs&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">[</span><span class="s1">&#39;serve zappa&#39;</span><span class="p">]</span>
+ <span class="nv">js = </span><span class="s2">&quot;;#{coffeescript_helpers}(#{client})();&quot;</span>
+ <span class="nv">js = </span><span class="nx">minify</span><span class="p">(</span><span class="nx">js</span><span class="p">)</span> <span class="k">if</span> <span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">[</span><span class="s1">&#39;minify&#39;</span><span class="p">]</span>
+
<span class="nx">app</span><span class="p">.</span><span class="nx">get</span> <span class="s1">&#39;/zappa/zappa.js&#39;</span><span class="p">,</span> <span class="nf">(req, res) -&gt;</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">contentType</span> <span class="s1">&#39;js&#39;</span>
- <span class="nx">res</span><span class="p">.</span><span class="nx">send</span> <span class="s2">&quot;;#{coffeescript_helpers}(#{client})();&quot;</span>
+ <span class="nx">res</span><span class="p">.</span><span class="nx">send</span> <span class="nx">js</span>
<span class="k">if</span> <span class="nx">app</span><span class="p">.</span><span class="nx">settings</span><span class="p">[</span><span class="s1">&#39;serve jquery&#39;</span><span class="p">]</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">get</span> <span class="s1">&#39;/zappa/jquery.js&#39;</span><span class="p">,</span> <span class="nf">(req, res) -&gt;</span>
View
@@ -12,7 +12,8 @@
"jsdom": "0.2.4",
"jquery": "1.6.2",
"coffeekup": "0.3.0",
- "node-uuid": "1.2.0"
+ "node-uuid": "1.2.0",
+ "uglify-js": "1.0.7"
},
"devDependencies": {
"request": "2.1.1",
View
@@ -14,6 +14,7 @@ socketio = require 'socket.io'
jsdom = require 'jsdom'
jquery = fs.readFileSync(__dirname + '/../node_modules/jquery/dist/node-jquery.min.js').toString()
sammy = fs.readFileSync(__dirname + '/../vendor/sammy-latest.min.js').toString()
+uglify = require 'uglify-js'
# CoffeeScript-generated JavaScript may contain anyone of these; when we "rewrite"
# a function (see below) though, it loses access to its parent scope, and consequently to
@@ -46,6 +47,12 @@ rewrite_function = (func, locals_names) ->
code = "var #{name} = locals.#{name};" + code
new Function('context', 'locals', 'args', code)
+minify = (js) ->
+ ast = uglify.parser.parse(js)
+ ast = uglify.uglify.ast_mangle(ast)
+ ast = uglify.uglify.ast_squeeze(ast)
+ uglify.uglify.gen_code(ast)
+
# Builds an array of unique names from the desired scopes.
# Ex.: select names, 'http + defs + helpers'
select = (names, scopes) ->
@@ -180,16 +187,19 @@ zappa.app = ->
app.enable 'serve zappa'
for k, v of obj
js = ";zappa.run(#{v});"
+ js = minify(js) if app.settings['minify']
routes.push verb: 'get', path: k, handler: js, contentType: 'js'
root_locals.coffee = (obj) ->
for k, v of obj
js = ";#{coffeescript_helpers}(#{v})();"
+ js = minify(js) if app.settings['minify']
routes.push verb: 'get', path: k, handler: js, contentType: 'js'
root_locals.js = (obj) ->
for k, v of obj
js = String(v)
+ js = minify(js) if app.settings['minify']
routes.push verb: 'get', path: k, handler: js, contentType: 'js'
root_locals.css = (obj) ->
@@ -268,6 +278,7 @@ zappa.app = ->
app.enable 'serve zappa'
for k, v of obj
js = ";zappa.run(#{v});"
+ js = minify(js) if app.settings['minify']
routes.push verb: 'get', path: k, handler: js, contentType: 'js'
rewritten_shared = rewrite_function(v, select names, 'globals + root + externals')
@@ -311,9 +322,12 @@ zappa.app = ->
postrenders[k] = rewrite_function(v, select names, 'globals + postrender + externals + helpers + defs')
if app.settings['serve zappa']
+ js = ";#{coffeescript_helpers}(#{client})();"
+ js = minify(js) if app.settings['minify']
+
app.get '/zappa/zappa.js', (req, res) ->
res.contentType 'js'
- res.send ";#{coffeescript_helpers}(#{client})();"
+ res.send js
if app.settings['serve jquery']
app.get '/zappa/jquery.js', (req, res) ->
View
@@ -135,4 +135,27 @@ port = 15200
c = t.client(zapp.app)
c.get '/zappa/zappa.js', (err, res) ->
t.equal 'content-type', res.headers['content-type'], 'application/javascript'
- t.equal 'length', res.headers['content-length'], '7037'
+ t.equal 'length', res.headers['content-length'], '7037'
+
+ minify: (t) ->
+ t.expect 'zappa', 'client', 'shared', 'coffee', 'js'
+ t.wait 3000
+
+ zapp = zappa port++, ->
+ enable 'serve zappa', 'minify'
+ client '/client.js': -> alert 'foo'
+ shared '/shared.js': -> alert 'foo' if window?
+ coffee '/coffee.js': -> alert 'foo'
+ js '/js.js': "alert('foo');"
+
+ c = t.client(zapp.app)
+ c.get '/zappa/zappa.js', (err, res) ->
+ t.equal 'zappa', res.headers['content-length'], '3258'
+ c.get '/client.js', (err, res) ->
+ t.equal 'client', res.headers['content-length'], '42'
+ c.get '/shared.js', (err, res) ->
+ t.equal 'shared', res.headers['content-length'], '87'
+ c.get '/coffee.js', (err, res) ->
+ t.equal 'coffee', res.headers['content-length'], '475'
+ c.get '/js.js', (err, res) ->
+ t.equal 'js', res.headers['content-length'], '12'

0 comments on commit 3a77b2d

Please sign in to comment.