一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

使用 HTTP2 服务端加速 Node.js应用方法

时间:2016-08-23 编辑:简简单单 来源:一聚教程网

我们的目的是让优化 Node.js 网站变得更容易。我们开发了 netjet 中间件来解析 HTML 并自动插入 Link 头。在这个 Express 的例子中,可以看见增加的头部:

我们使用 Ghost 来增强本博客的性能,如果你的浏览器支持 HTTP2,你已经在不知不觉中受益于服务端推送了(请见博客原文——译者注)。下面还有更多。

在 netjet 中,我们使用 PostHTML 项目与一个普通插件一起解析 HTML。现在它查找的是图片、脚本和外链样式表。你也可以在其它环境中实现同样的技术。

在 HTTP 的响应中解析 HTML 有一个缺点:增加加载延迟(或者“首字节到达时间”)。大多数情况下,增加的延迟会被其它环节掩盖,如数据库访问。然而,netjet 包含了一个可伸缩的由 ETag 头实现的 LRU 缓存,允许对于了已经解析过页面快速插入 Link 头。

如果你在设计一个很有野心的应用,你应该在内容中嵌入资源上考虑存储源信息,移除 HTML 的解析过程,以及可能的延迟增加。

Netjet 与任何支持像 Express 中间件一样的 Node.js 框架兼容。入门就如把 netjet 加入中间件链一样简单。

var express = require('express'); 
var netjet = require('netjet'); 
var root = '/path/to/static/folder';

express() 
  .use(netjet({
    cache: {
      max: 100
    }
  }))
  .use(express.static(root))
  .listen(1337);
在没有任何框架的情况下使用 netjet,只需要一点点额外的工作。

var http = require('http');
var netjet = require('netjet');

var port = 1337;
var hostname = 'localhost';
var preload = netjet({
  cache: {
    max: 100
  }
});

var server = http.createServer(function (req, res) {
  preload(req, res, function () {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/html');
      res.end('

Hello World

');
  });
});

server.listen(port, hostname, function () {
  console.log('Server running at http://' + hostname + ':' + port+ '/');
});
关于被支持的选项,请查阅 netjet 文档。

查看推送的资源

Chrome 的开发者工具使得鉴别网站是否使用服务端推送变得很简单。网络选项卡在 initiator 列的开头以 “push” 来标记被推送的资源。

不幸的是,Firefox 的开发者工具没有直接指明资源是否是被推送的。但是你可以查看页面响应头的 cf-h2-pushed 值,它包含了 CloudFlare 推送给浏览器的资源列表。

欢迎为 netjet 及其文档贡献力量。我很愿意听说有人在用 netjet。

Ghost 和服务端推送
Ghost(指 https://ghost.org/ —— 译者注) 是一个令人兴奋的整合平台。在 Ghost 团队的帮助下,我已经把 netjet 整合了进去,在 0.8.0 版本后已经可以作为一个可选的配置。

如果你在运行一个 Ghost 实例,你可以通过修改 config.js 文件、在 production 配置块中增加 preloadHeaders 选项的方式开启服务端推送。

production: { 
  url: 'https://my-ghost-blog.com',
  preloadHeaders: 100,
  // ...
}
Ghost 为用户提供了一个帮助文档 。

补充一下其它加还node.js的方法

异步

根据设计 Node.js 是单线程的。基于这点,同步代码会堵塞整个应用。比如说,多数的文件系统 API 都有它们的同步版本。下面代码演示了文件读取的同步和异步两种操作:

// Asynchronous
fs.readFile('file.txt', function(err, buffer) {
  var content = buffer.toString();
});

// Synchronous
var content = fs.readFileSync('file.txt').toString();
不过要是你执行那种长时间的阻塞操作,主线程就会被阻塞到这些操作完成为止。这大大降低你应用的性能。所以,最好确保你的代码里用的都是异步版本 API,最起码你应该在性能节点异步。而且,你在选用第三方模块的时候也要很小心。因为当你想方设法把同步操作从你代码中剔除之后,一个外部库的同步调用会让你前功尽弃,降低你的应用性能。

缓存

如果你用到一些不经常变化的数据,你应该把它们缓存起来,改善性能。比如说,下面的代码是获取最新帖子并显示的例子:

var router = express.Router();
 
router.route('/latestPosts').get(function(req, res) {
  Post.getLatest(function(err, posts) {
    if (err) {
      throw err;
    }
 
    res.render('posts', { posts: posts });
  });
});

如果你不经常发贴的话,你可以把帖子列表缓存起来,然后一段时间之后再把它们清理掉。比如,我们可以用 Redis 模块来达到这个目的。当然,你必须在你的服务器上装 Redis。然后你可以用叫做 node_redis 的客户端来保存键/值对。下面的例子演示我们怎么缓存帖子:

var redis = require('redis'),
    client = redis.createClient(null, null, { detect_buffers: true }),
    router = express.Router();
 
router.route('/latestPosts').get(function(req,res){
  client.get('posts', function (err, posts) {
    if (posts) {
      return res.render('posts', { posts: JSON.parse(posts) });
    }
 
    Post.getLatest(function(err, posts) {
      if (err) {
        throw err;
      }
 
      client.set('posts', JSON.stringify(posts));   
      res.render('posts', { posts: posts });
    });
  });
});
看到了吧,我们首先检查 Redis 缓存,看看是否有帖子。如果有,我们从缓存中拿这些帖子列表。否则我们就检索数据库内容,然后把结果缓存。此外,一定时间之后,我们可以清理 Redis 缓存,这样就可以更新内容了。

gzip 压缩

开启 gzip 压缩对你的 Web 应用会产生巨大影响。当一个 gzip 压缩浏览器请求某些资源的时候,服务器会在响应返回给浏览器之前进行压缩。如果你不用 gzip 压缩你的静态资源,浏览器拿到它们可能会花费更长时间。
在 Express 应用中,我们可以用内建 express.static() 中间件来处理静态内容。此外,还可以用 compression 中间件压缩和处理静态内容。下面是使用例:

var compression = require('compression');
 
app.use(compression()); //use compression
app.use(express.static(path.join(__dirname, 'public')));

总结

使用 netjet 后,你的 Node.js 应用可以开发使用浏览器预加载,在 CloudFlare 中,HTTP2 的服务端推送可以被开启。

热门栏目