讓你的 Node.js 應用跑得更快的 10 個技巧

Node.js 受益於它的事件驅動和異步的特徵,已經很快了。可是,在現代網絡中只是快是不行的。若是你打算用 Node.js 開發你的下一個Web 應用的話,那麼你就應該無所不用其極,讓你的應用更快,異常的快。本文將介紹 10 條,通過檢驗得知可大大提升 Node 應用的技巧。廢話很少說,讓咱們逐條來看看。node

1. 並行

建立 Web 應用的時候,你可能要屢次調用內部 API 來獲取各類數據。好比說,假設在 Dashboard 頁面上,你要執行下面這幾個調用:nginx

  • 用戶信息 -getUserProfile().
  • 當前活動 -getRecentActivity().
  • 訂閱內容 -getSubscriptions().
  • 通知內容 -getNotifications().

爲了拿到這些信息,你應該會爲每一個方法建立獨立的中間件,而後將它們連接到 Dashboard 路由上。不過問題是,這些方法的執行是線性的,上一個沒結束以前下一個不會開始。可行解決案是並行調用它們。git

如你所知因爲異步性,Node.js 很是擅長並行調用多個方法。咱們不能暴殄天物。我上面提到的那些方法沒有依賴性,因此咱們能夠並行執行它們。這樣咱們能夠削減中間件數量,大幅提升速度。angularjs

咱們能夠用 async.js 來處理並行,它是一個專門用來調教 JavaScript 異步的 Node 模塊。下面代碼演示怎樣用 async.js 並行調用多個方法的:github

function runInParallel() {
  async.parallel([
    getUserProfile,
    getRecentActivity,
    getSubscriptions,
    getNotifications
  ], function(err, results) {
    //This callback runs when all the functions complete
  });
}

若是你想更深刻了解 async.js ,請移步它的 GitHub 頁面。web

2. 異步

根據設計 Node.js 是單線程的。基於這點,同步代碼會堵塞整個應用。好比說,多數的文件系統 API 都有它們的同步版本。下面代碼演示了文件讀取的同步和異步兩種操做:redis

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

// Synchronous
var content = fs.readFileSync('file.txt').toString();

不過要是你執行那種長時間的阻塞操做,主線程就會被阻塞到這些操做完成爲止。這大大下降你應用的性能。因此,最好確保你的代碼裏用的都是異步版本 API,最起碼你應該在性能節點異步。並且,你在選用第三方模塊的時候也要很當心。由於當你千方百計把同步操做從你代碼中剔除以後,一個外部庫的同步調用會讓你前功盡棄,下降你的應用性能。mongodb

3. 緩存

若是你用到一些不常常變化的數據,你應該把它們緩存起來,改善性能。好比說,下面的代碼是獲取最新帖子並顯示的例子:數據庫

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 的客戶端來保存鍵/值對。下面的例子演示咱們怎麼緩存帖子:express

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 緩存,這樣就能夠更新內容了。

4. 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')));

5. 若是能夠,在用客戶端渲染

如今有超多功能強勁的客戶端 MVC/MVVM 框架,好比說 AngularJS, Ember, Meteor, 等等,構建一個單頁面應用變得很是簡單。基本上,你只要公開一個 API,返回 JSON 響應給客戶端就能夠了,而不須要在服務端渲染頁面。在客戶端,你能夠用框架來組織 JSON 而後把它們顯示在 UI 上。服務端只發送 JSON 響應能夠節省帶寬,改善性能,由於你不須要在每一個響應裏面都返回佈局標記了,對吧,你只須要返回純 JSON,而後在客戶端渲染它們。

看下個人這個教程,它是關於怎樣用 Express 4 公開一個 RESTful APIs的。我還寫了另外一篇教程,演示了怎樣把這些 APIs 和 AngularJS 結合起來。

6. 不要在 Sessions 存儲太多數據

典型的 Express 頁面應用, Session 數據默認是保存在內存中的。當你把太多數據保存在 Session 的時候,會致使服務器開銷顯著增大。因此,要麼你切換到別的儲存方式來保存 Session 數據,要麼儘可能減小存儲在 Session 中的數據量。

好比說,當用戶登陸到你的應用的時候,你能夠只在 Session 中保存他們的 ID 而不是整個用戶數據對象。還有,對於那些你可以從 id 拿到對象的查詢,你應該會喜歡用  MongoDB 或者 Redis 來存儲 session 數據。

7. 優化查詢

假設你有個博客,你要在主頁上顯示最新帖子。你可能會經過 Mongoose 這樣取數據:

Post.find().limit(10).exec(function(err, posts) {
  //send posts to client
});

不過問題是 Mongoose 的 find() 方法會把對象的全部字段都查詢出來,而許多字段在主頁上並不要求。好比說,commentsis 保存的是特定帖子的回覆。咱們不須要顯示文章回復,因此咱們能夠在查詢的時候把它給剔除掉。這無疑會提升速度。能夠像這樣優化上面那條查詢:

Post.find().limit(10).exclude('comments').exec(function(err, posts) {
  //send posts to client
});

8. 用標準的 V8 方法

集合上的一些操做,好比 map,reduce,和 forEach 不必定支持全部瀏覽器。咱們能夠經過前臺的庫解決部分瀏覽器兼容性問題。但對於 Node.js,你要確切知道 Google 的 V8 JavaScript 引擎支持哪些操做。這樣,你就能夠在服務端直接用這些內建方法來操做集合了。

9. 在 Node 前面用 Nginx

Nginx 是個微小型輕量 Web 服務器,用它能夠下降你的 Node.js 服務器的負載。你能夠把靜態資源配置到 nginx 上,而不是在 Node 上。你能夠在 nginx 上用 gzip 壓縮響應,讓全部的響應都變得更小。因此,若是你有個正在營運的產品,我以爲你應該會想用 nginx 來改善運行速度的。

10. 打包 JavaScript

最後,你還能夠大大提升頁面應用速度,經過把多個 JS 文件打包。當瀏覽器在頁面渲染中碰到 <script> 元素的時候會被堵塞,直到拿到這個腳本才繼續運行(除非設置了異步屬性)。好比,若是你的頁面有五個 JavaScript 文件,瀏覽器會發出五個獨立的 HTTP 請求來獲取他們。若是把這五個文件壓縮打包成一個,總體性能將能夠大幅提高。CSS 文件也是同樣。你能夠用諸如 Grunt/Gulp 這樣的編譯工具來打包你的資源文件。

結論

上面 10 條技巧確定能夠提升你的 Web 應用的速度的。不過,我知道還有改善和優化的空間。若是你有任何改善性能的技巧的話,在回覆裏告訴我。

英文原文:10 Tips to Make Your Node.js Web App Faster
出處:讓你的 Node.js 應用跑得更快的 10 個技巧

相關文章
相關標籤/搜索