原文地址在個人博客,轉載請註明來源,謝謝!javascript
node是在前端領域常常看到的詞。node對於前端的重要性已經不言而喻,掌握node也是做爲合格的前端工程師一項基本功了。知道node、知道後端的一些東西,才能更好的與別人合做,發揮更大的價值。css
本文主要介紹了我對node的一些核心特性的理解,包括node架構、特色、機制、核心模塊與簡單應用。html
首先,node是一個平臺,使用javascript做爲編程語言,運行在服務端。服務端語言能作的,node通常都能作,並且有些狀況下作的更好,由於它具備本身的特點。前端
node是javascript運行環境(runtime),就像瀏覽器同樣,是一個平臺。在瀏覽器中,V8引擎負責解釋javascript,你在javascript調用的接口都是瀏覽器實現並提供的,瀏覽器會調用底層的、由其餘語言(C++)實現並封裝好的接口來完成任務;一樣,在node中,也是V8引擎負責解釋javascript,而你在javascript調用的瀏覽器提供的接口就不能用了,由於它脫離了瀏覽器的環境,可是由於你在node環境中,你就可使用node提供的由C++語言實現的、由javascript封裝好的各類接口來完成後端任務。瀏覽器提供的API用於處理前端任務,好比彈個窗,換個主題,處理用戶操做等,而node由於服務後端,所以提供的API則用來處理後端任務,好比響應請求,讀取文件等,這些API由不一樣的模塊提供。由於關注領域不同,所以所作的任務就不同,提供的API就不同,可是原理、相關實現大體與瀏覽器端相同。java
從瀏覽器到node這一塊若是想了解更多,推薦IBM的文章node.js究竟是什麼?node
node架構分爲三層(參考連接):git
圖片來源github
日常咱們用到的也就是第一層node各個模塊實現的接口。chrome
那他們之間時如何協做的呢數據庫
程序啓動,V8引擎會首先解析javascript代碼,經過Node bindings來調用C/C++庫。執行到當前事件時,會把事件放在調用堆棧(stack和heap)處理(能夠理解爲放進一個工做空間,如上圖),在堆棧中的任何I/O請求都會交給libuv來處理,libuv維持一個線程池,裏面是一些工做線程(以下圖),請求會調用這些線程來完成任務,這些線程則調用底層的C/C++庫。完成時,libuv再把結果返回事件隊列等待主線程執行。在此期間,主線程繼續執行其餘任務。
單線程的意思就是隻在一個線程上運行javascript。首先,javascript 在瀏覽器端是單線程的,這是爲了不多線程產生任務衝突的狀況;其次,java和PHP這類多線程後端語言,爲避免同步I/O阻塞,每處理一個鏈接都會產生一個新線程,這樣的話在遇到大量併發請求時就會受到物理內存的限制。node 延續了瀏覽器端單線程javascript,只用一個主線程執行javascript,不斷循環遍歷事件隊列,執行事件。事實上,主線程發出的I/O請求,都會交給其餘線程去完成,其餘線程完成後悔返回結果放到事件隊列。在此期間,主線程會繼續執行其餘任務,也就是在交給libuv後直接返回,繼續執行下面的任務,主線程只負責循環執行事件隊列,所以這種模式稱爲非阻塞型I/O,性能很好,適用於處理大量併發請求,還能簡化開發。
仍是跟瀏覽器的差很少。總的來講就是,瀏覽器端把鼠標點擊、鍵盤按鍵等定義爲事件,而node把網絡請求、I/O操做等也看做事件,嚴格來講,一切動做都是事件,這就是事件驅動的思想。在程序啓動時,便進入事件循環,不斷遍歷執行事件隊列中產生的事件,而在執行過程當中,又會產生新的事件,所以稱爲事件循環。主線程執行事件時,遇到麻煩的I/O請求會交給libuv來調度其餘工做線程來幫忙,忙完後就會造成事件返回結果到事件隊列等待主線程處理。在此期間,主線程會繼續執行其餘任務。
mbp 曾經作過一個巧妙的比喻,把 Node.js 當作一家餐廳。我在此借用下他的例子,稍做修改來闡述下 Node.js 的執行狀況:
把 Node.js 應用程序想象成一家星巴克,一個訓練有素的前臺服務生(惟一的主線程)在櫃檯前接受訂單。當不少顧客同時光臨的時候,他們排隊(進入事件隊列)等候接待;每當服務生接待一位顧客,服務生會把訂單告知給經理(libuv),經理安排相應的專職人員去烹製咖啡(工做線程或者系統特性)。這個專職人員會使用不一樣的原料和咖啡機(底層 C/C++ 組件)按訂單要求製做咖啡或甜點,一般會有四個這樣的專職人員保持在崗待命(線程池),高峯期的時候也能夠安排更多(不過須要在一早就安排人員來上班,而不能中午臨時通知)。服務生把訂單轉交給經理以後不須要等着咖啡製做完成,而是直接開始接待下一位顧客(事件循環放進調用堆棧的另外一個事件),你能夠把當前調用堆棧裏的事件當作是站在櫃檯前正在接受服務的顧客。
當咖啡完成時,會被髮送到顧客隊列的最後位置,等它移動到櫃檯前服務生會叫相應顧客的名字,顧客就來取走咖啡(最後這部分在真實生活中聽起來有點怪,不過你從程序執行的角度理解就比較合乎情理了)。
——By Amio
若是你想進一步瞭解javascript 事件驅動機制,推薦深刻理解 javascript 事件循環機制
node 模塊機制是CommonJs 的實現。起初,javascript 標準一片混沌,並無其餘成熟語言(例如C++)的模塊機制、標準庫、接口等,爲了讓javascript 具有開發大型應用的能力,爲了讓 javascript 能在後端運行,CommonJS 就制定了javascript 模塊規範。node 借鑑了這個規範,讓javascript 以模塊形式組織起來。模塊機制是一個成熟語言必備的,一個模塊表明一個功能的封裝,它就像搭積木同樣,不一樣模塊能夠銜接在一塊,使語言具備極強的可擴展型。node 模塊機制同時制定了模塊規範,能讓全球的開發者均可以在node官網上傳本身的包。此外,node 社區又實現了node 包管理器npm,使用npm能夠輕鬆管理各類包。
node 的模塊分爲核心模塊和用戶模塊,前者是底層的、自帶的,後者是第三方。
核心模塊有Global(全局對象)、Http、fs(文件系統)、Buffer、Stream、Events、URL、path等,這些模塊提供了後端服務的基本功能,都提供本身關注功能的API。
在使用模塊時,require 便可。但在require背後,node 有一套尋找模塊的機制:
從上圖能夠看到,node 優先從緩存區讀取,緩存區有直接讀取,沒有則加載並緩存,這樣作不用一遍一遍去找了,很是高效。node 在緩存區沒有發現模塊時,會分析require 的路徑和文件後綴,node 有個模塊路徑的查找策略,咱們能夠在名爲module_paths
的js文件裏console.log(module.paths)
而後node module_paths.js
運行來間接查看node 尋找文件模塊的具體文件的方式:
[ '/home/username/nodeProject/node_modules',
'/home/username/node_modules',
'/home/node_modules',
'/node_modules' ] //Linux下的數組輸出(/home/username因電腦不一樣而異)
[ 'c:\\nodeProject\\node_modules', 'c:\\node_modules' ] //Windows複製代碼
也就是按照下面的順序:
這些順序都是在查找緩存以後的。
在找到模塊後,node 將在引入以前對這個模塊進行編譯執行,編譯成功後會緩存,執行的結果會返回給調用者。
有了node 自帶核心模塊的基礎功能,就能夠進一步封裝更強大、容易操做的功能了,就像jQuery 對於javascript 基礎API 同樣,node 社區也誕生了像 Express、KOA等框架來構建node.js程序
這些框架的詳情移步2017 Node.js 開發框架比較
另外,node 還能夠鏈接MySQL,MangoDB進行數據庫操做。
下面是使用express 腳手架生成的基本 node應用結構:
.
├── app.js //程序入口
├── bin
│ └── www //二機制文件
├── package.json //項目配置文件
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js //路由文件入口
│ └── users.js
└── views
├── error.jade //界面模板
├── index.jade
└── layout.jade複製代碼
如今使用 node做爲後端語言一般都要配合類庫和框架使用。
node 的單線程、非阻塞型特色讓它很是適合高併發的應用,適合處理大量重複的、簡單的邏輯,適合構建Rest/JSON API服務;同時,也正是由於這些特性,node 不適合CPU使用率較重、IO使用率較輕的偏計算應用。缺點是由於單線程,一個進程掛就全掛了,可靠性低,但這是能夠避免的。node 更多的應用是在前端、中間件、先後端分離等。
因爲 node 的諸多優勢,如今愈來愈多大公司開始使用node、深度使用node。
node 的核心概念、思想遠不止這麼多,應用更是多了去了,無奈本人水平有限,只能說個淺層,還有不少像進程管理、異步編程、異常調試、部署、性能調優、與集羣、CDN協調等都值得深刻探索一下。不管如何,node 是讓javascript 邁向企業級開發語言重要的一步(也許已是了),前端工程師從未像如今這樣的powerful,能作的事情愈來愈多,所能涉及的領域也愈來愈多。前端這行愈來愈使人興奮了。