Node.JS

十个Node.js开发易犯错误之一:不使用开发工具

 Node.js在过去几年发展迅速,一些大公司如沃尔玛和Paypal都已经采用它,NPM的模块已经超过其他任何语言,在这里我们介绍一下Node程序员最容易犯的错误以及如何避免它们,这些源码案例可以在 github上发现。

1. 不使用开发工具

 不像其它语言如PHP或Ruby,当你修改源码以后,需要重启Node,可以使用工具nodemon 或 supervisor;另外当静态代码改变时,浏览器需要手工刷新,可以采取In-browser live reload 等工具。

 自动重新启动:当我们在编辑器保存源码到文件后,按下[CTRL+C]停止Node应用,然后使用[UP]和[Enter]按键重新其他,现在你可以使用自动工具来做这些事情:

 这些模块会监视文件的改变,然后替你重新启动服务器,我们以nodemon为案例,首先,你可以全局安装它:

npm i nodemon -g

 然后你可以使用nodemon替代node命令启动服务器:

$ nodemon server.js
 14 Nov 21:23:23 - [nodemon] v1.2.1
....
14 Nov 21:24:14 - [nodemon] starting `node server.js`

 下面看看浏览器内的自动刷新,除了服务器这里的重新启动,浏览器中也需要重新刷新,我们可以使用livereload。它会监视文件的变化,然后触发浏览器刷新,刷新是通过注入页面的脚本或浏览器插件完成的。

 下面展示一下如何使用livereload,它会做以下几件事:

  • 观察目录下文件的改变
  • 使用server-sent events发送给所有连接的客户端
  • 触发页面刷新.

 首先我们需要安装NPM依赖如下:

  • express - 用来创建Web应用案例
  • watch - 观察文件改变
  • sendevent - server-sent events, SSE(websockets的替代)
  • uglify-js - 最小化客户端JS文件
  • ejs - 视图模板
 现在我们创建一个简单的Express服务器,渲染输出home视图到前端页面:

var express = require('express');
var app = express();
var ejs = require('ejs');
var path = require('path');
var PORT = process.env.PORT || 1337;

//视图引擎设置
app.engine('html', ejs.renderFile);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');

// 空页面
app.get('/', function(req, res) { res.render('home'); });
app.listen(PORT);

 我们要设置监视的目录,在上面server.js的“视图引擎设置”之前加入代码:

var reloadify = require('./lib/reloadify');
reloadify(app, __dirname + '/views');

 这是设置观察/views目录的改变,reloadify.js代码如下:

var sendevent = require('sendevent');
var watch = require('watch');
var uglify = require('uglify-js');
var fs = require('fs');
var ENV = process.env.NODE_ENV || 'development';

// 创建静态的 JS 文件被该页使用included in the page
var polyfill = fs.readFileSync(__dirname + '/assets/eventsource-polyfill.js', 'utf8');
var clientScript = fs.readFileSync(__dirname + '/assets/client-script.js', 'utf8');
var script = uglify.minify(polyfill + clientScript, { fromString: true }).code;

function reloadify(app, dir) {
if (ENV !== 'development') {
app.locals.watchScript = '';
return;
}

// 创建中间件提交请求到`/eventstream`
var events = sendevent('/eventstream');

app.use(events);

watch.watchTree(dir, function (f, curr, prev) {
events.broadcast({ msg: 'reload' });
});

//分配脚本到本地变量,这样能在视图中被访问
app.locals.watchScript = '<script>' + script + '</script>';
}

module.exports = reloadify;

 代码中已经设置:如果开发环境ENV不是开发环境development,这个中间件功能不好激活,所以,对于生产环境这段代码也无需去除。

 前端JS文件相当简单,只是监听SSE消息,然后根据需要刷新页面:

(function() {

 

  function subscribe(url, callback) {

    var source = new window.EventSource(url);

 

    source.onmessage = function(e) {

      callback(e.data);

    };

 

    source.onerror = function(e) {

      if (source.readyState == window.EventSource.CLOSED) return;

 

      console.log('sse error', e);

    };

 

    return source.close.bind(source);

  };

 

  subscribe('/eventstream', function(data) {

    if (data && /reload/.test(data)) {

      window.location.reload();

    }

  });

 

}());

 

  eventsource-polyfill.js 是个Remy Sharp's polyfill for SSE。最后我们需要在/views/home.html中使用视图帮助导入前端产生的脚本(见reloadify.js中"分配脚本到本地变量"):

<%- watchScript %>

  现在每次你改变home.html页面时,浏览器将自动从服务器刷新新的页面内容给你:http://localhost:1337/。

本节源码下载: Github

下页