Node.js 受益於它的事件驅動和異步的特徵,已經很快了。可是,在現代網絡中只是快是不行的。若是你打算用 Node.js 開發你的下一個Web 應用的話,那麼你就應該無所不用其極,讓你的應用更快,異常的快。本文將介紹 10 條,通過檢驗得知可大大提升 Node 應用的技巧。廢話很少說,讓咱們逐條來看看。node
建立 Web 應用的時候,你可能要屢次調用內部 API 來獲取各類數據。好比說,假設在 Dashboard 頁面上,你要執行下面這幾個調用:nginx
爲了拿到這些信息,你應該會爲每一個方法建立獨立的中間件,而後將它們連接到 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
根據設計 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
若是你用到一些不常常變化的數據,你應該把它們緩存起來,改善性能。好比說,下面的代碼是獲取最新帖子並顯示的例子:數據庫
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 緩存,這樣就能夠更新內容了。
開啓 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')));
如今有超多功能強勁的客戶端 MVC/MVVM 框架,好比說 AngularJS, Ember, Meteor, 等等,構建一個單頁面應用變得很是簡單。基本上,你只要公開一個 API,返回 JSON 響應給客戶端就能夠了,而不須要在服務端渲染頁面。在客戶端,你能夠用框架來組織 JSON 而後把它們顯示在 UI 上。服務端只發送 JSON 響應能夠節省帶寬,改善性能,由於你不須要在每一個響應裏面都返回佈局標記了,對吧,你只須要返回純 JSON,而後在客戶端渲染它們。
看下個人這個教程,它是關於怎樣用 Express 4 公開一個 RESTful APIs的。我還寫了另外一篇教程,演示了怎樣把這些 APIs 和 AngularJS 結合起來。
典型的 Express 頁面應用, Session 數據默認是保存在內存中的。當你把太多數據保存在 Session 的時候,會致使服務器開銷顯著增大。因此,要麼你切換到別的儲存方式來保存 Session 數據,要麼儘可能減小存儲在 Session 中的數據量。
好比說,當用戶登陸到你的應用的時候,你能夠只在 Session 中保存他們的 ID 而不是整個用戶數據對象。還有,對於那些你可以從 id 拿到對象的查詢,你應該會喜歡用 MongoDB 或者 Redis 來存儲 session 數據。
假設你有個博客,你要在主頁上顯示最新帖子。你可能會經過 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 });
集合上的一些操做,好比 map,reduce,和 forEach 不必定支持全部瀏覽器。咱們能夠經過前臺的庫解決部分瀏覽器兼容性問題。但對於 Node.js,你要確切知道 Google 的 V8 JavaScript 引擎支持哪些操做。這樣,你就能夠在服務端直接用這些內建方法來操做集合了。
Nginx 是個微小型輕量 Web 服務器,用它能夠下降你的 Node.js 服務器的負載。你能夠把靜態資源配置到 nginx 上,而不是在 Node 上。你能夠在 nginx 上用 gzip 壓縮響應,讓全部的響應都變得更小。因此,若是你有個正在營運的產品,我以爲你應該會想用 nginx 來改善運行速度的。
最後,你還能夠大大提升頁面應用速度,經過把多個 JS 文件打包。當瀏覽器在頁面渲染中碰到 <script> 元素的時候會被堵塞,直到拿到這個腳本才繼續運行(除非設置了異步屬性)。好比,若是你的頁面有五個 JavaScript 文件,瀏覽器會發出五個獨立的 HTTP 請求來獲取他們。若是把這五個文件壓縮打包成一個,總體性能將能夠大幅提高。CSS 文件也是同樣。你能夠用諸如 Grunt/Gulp 這樣的編譯工具來打包你的資源文件。
上面 10 條技巧確定能夠提升你的 Web 應用的速度的。不過,我知道還有改善和優化的空間。若是你有任何改善性能的技巧的話,在回覆裏告訴我。
英文原文:10 Tips to Make Your Node.js Web App Faster
出處:讓你的 Node.js 應用跑得更快的 10 個技巧