Subsecciones

Porting to Coffeescript

At this point, let’s port our backend to coffeescript.

You can install js2coffee via npm. So run the following:

npm -g install js2coffee
[~/src/coffee/coffeepress]$ js2coffee --version
2.0.3
[~/src/coffee/coffeepress]$ js2coffee --help
Usage:
    js2coffee FILES [options]

Options:
        --ast          prints the AST (for debugging)
    -V, --verbose      prints more AST stuff (used with --ast)
    -i, --indent N     indent by N spaces (default: 2)
    -i, --indent tab   indent by tabs

Modes:
        --compat       compatibility mode *
                       (implement workarounds to keep full compatibility)

Other options:
    -h, --help         print usage information
    -v, --version      show version info and exit

Vamos a convertir nuestros ficheros *.js a coffee:

~/src/coffee/coffeepress]$ ls *js **/*js bin/*
app.js          bin/www         routes/index.js routes/users.js
[~/src/coffee/coffeepress]$ js2coffee app.js > app.coffee
[~/src/coffee/coffeepress]$ js2coffee routes/index.js > routes/index.coffee
[~/src/coffee/coffeepress]$ js2coffee routes/users.js > routes/users.coffee
Cuando probamos con el main obtenemos un error:
[~/src/coffee/coffeepress]$ js2coffee bin/www > bin/www.coffee
bin/www:1:0: [error] Unexpected token ILLEGAL
El error es debido a la primera línea para la bash con la definición del intérprete:
[/tmp/coffeepress]$ cat -n bin/www 
 1  #!/usr/bin/env node
 2  
 3  /**
 4   * Module dependencies.
 5   */
 6  
 7  var app = require('../app');
 8  var debug = require('debug')('coffeepress:server');
 9  var http = require('http');
10  
11  /**
12   * Get port from environment and store in Express.
13   */
14  
15  var port = normalizePort(process.env.PORT || '3000');
16  app.set('port', port);
17  
18  /**
19   * Create HTTP server.
20   */
21  
22  var server = http.createServer(app);
23  
24  /**
25   * Listen on provided port, on all network interfaces.
26   */
27  
28  server.listen(port);
29  server.on('error', onError);
30  server.on('listening', onListening);
31  
32  /**
33   * Normalize a port into a number, string, or false.
34   */
35  
36  function normalizePort(val) {
37    var port = parseInt(val, 10);
38  
39    if (isNaN(port)) {
40      // named pipe
41      return val;
42    }
43  
44    if (port >= 0) {
45      // port number
46      return port;
47    }
48  
49    return false;
50  }
51  
52  /**
53   * Event listener for HTTP server "error" event.
54   */
55  
56  function onError(error) {
57    if (error.syscall !== 'listen') {
58      throw error;
59    }
60  
61    var bind = typeof port === 'string'
62      ? 'Pipe ' + port
63      : 'Port ' + port
64  
65    // handle specific listen errors with friendly messages
66    switch (error.code) {
67      case 'EACCES':
68        console.error(bind + ' requires elevated privileges');
69        process.exit(1);
70        break;
71      case 'EADDRINUSE':
72        console.error(bind + ' is already in use');
73        process.exit(1);
74        break;
75      default:
76        throw error;
77    }
78  }
79  
80  /**
81   * Event listener for HTTP server "listening" event.
82   */
83  
84  function onListening() {
85    var addr = server.address();
86    var bind = typeof addr === 'string'
87      ? 'pipe ' + addr
88      : 'port ' + addr.port;
89    debug('Listening on ' + bind);
90  }

Obsérvense las líneas:

29  server.on('error', onError);
30  server.on('listening', onListening);

Many objects in Node emit events:

All objects which emit events are instances of events.EventEmitter .

Functions can then be attached to objects, to be executed when an event is emitted. These functions are called listeners.

Volviendo a nuestra traducción de bin/www, si comentamos la primera línea no se producen errores pero si que nos sale un warning:

~/src/coffee/coffeepress]$ js2coffee bin/www > bin/www.coffee
bin/www:37:6: [warning] Variable shadowing ('port') is not fully supported in CoffeeScript
Si cambiamos todas las apariciones de la variable port por p. ej. lport en la definición de la función normalizePort el warning desaparece:
[~/src/coffee/coffeepress(master)]$ js2coffee bin/www > bin/www.coffee 
[~/src/coffee/coffeepress(master)]$
pero cuando ejecutamos el servidor obtenemos un nuevo error:
[~/src/coffee/coffeepress(master)]$ coffee bin/www.coffee 
TypeError: undefined is not a function
  at Object.<anonymous> (/Users/casiano/local/src/coffee/coffeepress/bin/www.coffee:15:8)
  at Object.<anonymous> (/Users/casiano/local/src/coffee/coffeepress/bin/www.coffee:3:1)
  at Module._compile (module.js:456:26)

Movemos la función normalizePort antes de la definición de port y se arregla el asunto.

Ejecución del Servidor

[~/src/coffee/coffeepress(master)]$ coffee bin/www.coffee 
GET / 304 298.379 ms - -
GET /stylesheets/style.css 304 6.048 ms - -
Otra forma de ejecutar el servidor es instalar nodemon
npm install -g nodemon
y ejecutarlo así:
~/src/coffee/coffeepress(master)]$ nodemon bin/www.coffee
6 Apr 14:12:01 - [nodemon] v1.3.7
6 Apr 14:12:01 - [nodemon] to restart at any time, enter `rs`
6 Apr 14:12:01 - [nodemon] watching: *.*
6 Apr 14:12:01 - [nodemon] starting `coffee bin/www.coffee`
Nodemon (see http://nodemon.io/ ) is for use during development of a node.js based application.

nodemon will watch the files in the directory in which nodemon was started, and if any files change, nodemon will automatically restart your node application.

nodemon does not require any changes to your code or method of development. nodemon simply wraps your node application and keeps an eye on any files that have changed. Remember that nodemon is a replacement wrapper for node, think of it as replacing the word "node" on the command line when you run your script.

Otra forma de ejecutar programas escritos en coffee consiste en usar la posibilidad que existe de cargar el coffee desde un programa JavaScript usando coffee-script/register. Modificamos bin/www como sigue:

[~/src/coffee/coffeepress.bak(master)]$ cat bin/www
#!/usr/bin/env node
// Note the new way of requesting CoffeeScript since 1.7.x
require('coffee-script/register');
// This bootstraps your server main file
require('./www.coffee');
y ahora ejecutamos:
[~/src/coffee/coffeepress(master)]$ node bin/www
GET / 304 334.240 ms - -
GET /stylesheets/style.css 304 7.269 ms - -

Casiano Rodríguez León
2016-03-27