教程介绍
- 难度: 中级
- 预计完成时间: 20分钟
如果您的网站对于向客户机发送数据较为依赖,那么使用客户端模板以及WebSocket能够显著提高其性能表现。在今天的教程中,我们就一起来了解如何实现这一目标。
简介
我 们将以现有应用程序为起点,一步步了解如何使其在高流量环境下拥有更快的响应速度与更可靠的运行表现。我将向大家展示如何从应用程序代码中准确定位对应代 码段,如何对其进行修改以提升运行性能。不过首先大家需要下载我准备好的范例应用。这款应用的内容非常简单,运行目的在于随机显示服务器当中的帖子内容 ——不过对于我们这篇指南文章来讲,这已经足够了。
***步: 准备
对我们已经下载完成的文件进行解压,为其选定文件夹或者保存位置,而后加以运行:
现在我们前往http://localhost:8080/并查看其内容。这时大家应该只能看到一个按钮。各位还需要准备一款安装了各类开发者工具的浏览器,这样就能掌握HTTP请求的实际大小。打开开发者工具,而后访问Network标签。接下来点击几下该按钮,注意/getpost请求的大小:
这条请求只有830字节,对吧?好的,想象一下,当我们的网站人气爆棚时,可能同时有一百多万用户想看到这篇帖子,这时请求的数据总量将达到约830MB。请注意,是每篇帖子830MB!这可就不是个小数目了。
第二步: 检查
在 第二步中,我将带领大家了解如何在应用中找到能够提升性能表现的对应代码片段。在前一步中,大家已经找到了用于获取帖子内容的请求,现在我们需要了解代码 是如何实现这一过程的。大家可以利用自己熟悉的代码编辑器打开index.js文件,其中第16到第20行内容如下所示:
- varpostTemplate = dot(fs.readFileSync('./post.dot'));
- app.get('/getpost', function(req, res) {
- res.end(postTemplate(posts[Math.floor(Math.random() * 3)]));
- });
就是它了!首先,帖子的模板会被编译至postTemplate变量当中。接下来,该模板会在/getpostGET请求中实现提交。这是一种非常典型的解决办法,可以说是乏善可陈。我们要对其进行变更以改进性能表现。
第三步: 设置Socket.IO
To begin the improvements, first, install Socket.IO. In your terminal type:为了实现性能提升,我们首先需要安装Socket.IO。大家需要在命令行终端内输入:
- npm installsocket.io
等待命令执行完成。通过将以下代码行添加到index.js的全部require之后将socket.io引入代码:
- varsio = require('socket.io');
现在大家必须对Express的设置进行修改,以使其与Socket.IO顺利协作。首先,在app definition之后加入下列内容:
- varserver = require('http').createServer(app);
- vario = require('socket.io').listen(server);
- server.listen(8080);
接下来移除该文件中的***一行:
之所以这么做,是因为Socket.IO的运作与HTTP Server紧密相关——而非Express app。
现在,如果大家运行该应用,应该会在自己的终端中看到如下所示的内容:
#p#
第四步: 客户端模板
为了着手提升应用性能,大家需要将 经过编译的模板保存在客户端当中。JavaScript文件会驻留在缓存当中,因此我们只要下载一次即可。为了编译模板,我们需要访问 http://olado.github.io/doT/index.html并下滚到Usage部分。由于我们不必在用户每一次访问网站时都对模板进行 编译,因此大家完全可以直接把编译后的函数添加到代码当中。打开post.dot文件,将其内容如下所示粘贴到Template字段当中:
现在将该字段的内容复制并粘贴到static/main.js文件的最初始位置。变更或者移除anonymous函数名称并将其分配至postTemplate变量,具体方式如下:
- varpostTemplate = function(it) { ... }
然后打开index.js文件并移除所有未使用的代码行,因为从现在开始,我们已经不必在服务器端对模板进行编译了:
- vardot = require('dot').template;
- varfs = require('fs');
- ...
- varpostTemplate = dot(fs.readFileSync('./post.dot'));
post.dot 文件也可以删掉,没关系的。
第五步: 从AJAX到WebSocket
相 对于以往利用AJAX实现与服务器通信的做法,现在我们转而使用WebSocket。***的办法是使用Socket.IO,这是因为WebSocket API本身并不提供故障转移功能——理由是用户的浏览器不支持。服务器已经设置完成,因此我们现在需要与之进行对接。首先,将下列代码添加到 static/index.html文件(在main.js之前)的head位置:
- <scriptsrcscriptsrc="/socket.io/socket.io.js"></script>
接下来,打开static/main.js文件并在模板definition之后添加以下代码:
- varsocket = io.connect();
它 将与Socket.IO服务器相连(请注意,大家必须提前将Socket.IO的脚本添加到页面当中)。由于在我们的实验环境中,服务器与客户端运行在同 一台主机当中,因此大家不必再为该函数添加任何额外参数。现在我们要做的是为该socket添加一个事件监听器,这样帖子内容获取完毕后我们就能及时得到 提示。将下列代码添加到之前代码行的后面:
- socket.on('getpost', function(data) {
- $('button').after(postTemplate(data));
- });
如大家所见,回调命令的内容与jQuery的$.ajax()方法中的success回调并无区别,但它会首先运行数据中的模板函数。现在,将$.ajax()调用替代为以下内容:
- socket.emit('getpost');
这一行代码的作用在于通知服务器,用户希望显示一篇新帖子。当然,在现实生活的应用程序内,服务器会在帖子发布后立刻加以发送。
第六步: 发送帖子
到这里,客户端已经能够与服务器对接并请求获取帖子内容,但服务器还无法正确响应随机帖子。现在我们打开index.js文件并对内容加以变更。由原本的:
- app.get('/getpost', function(req, res) {
- res.end(postTemplate(posts[Math.floor(Math.random() * 3)]));
- });
变更为:
- io.sockets.on('connection', function(socket) {
- socket.on('getpost', function() {
- socket.emit('getpost', posts[Math.floor(Math.random() * 3)]);
- });
- });
这 将使服务器将getpost句柄与所有客户端相连,并利用随机帖子内容作为响应。现在大家可以再次运行应用程序以查看实际效果。接下来我们要再次打开浏览 器中的开发者工具、找到Network标签并加以过滤,这样大家就只会看到WebSocket。现在点击这个惟一可见的对象,大家应该看到浏览器与服务器 之间的传输的数据——是的,请求大小与文章开头的初始状态相比有了明显缩减。这是因为刚开始请求当中还包含有服务器端模板与AJAX内容(长度单位为‘字 节’):
总结
如各位所见,利用WebSocket以及客户端模板(几乎一定)能够改进应用程序的性能表现及耐用性。我敢肯定,很多网站都采用这种方式提升自己的响应效果。当然,我也希望各位朋友能够利用这项技巧为自己的移动及桌面系统用户带来更出色的使用体验。
原文链接:http://net.tutsplus.com/tutorials/javascript-ajax/node-js-better-performance-with-socket-io-and-dot/