再寫Node基礎(讀《Node.js 來一打C++擴展》)

NPM的做用: Node.js程序依賴包的發佈、管理和安裝。javascript

CommonJS規範

require

require是一個函數,參數是模塊標識符,返回值是所引用模塊暴露給外部使用者的內容。前端

直白一點講:java

一個模塊定義文件module1.jsnode

module.exports={
    a:1,
    f: function(){
        console.log('f');
    }
}

一個引用模塊module1.js的文件python

let m1 = require('module1.js');
console.log(m1);
// {a: 1, f: ƒ}

模塊的上下文

在每一個模塊中,都有以下一些事物:git

  1. require函數
  2. exports對象,這個對象上掛載的東西會被暴露給外部。
  3. module對象,裏面包含模塊自身的一些信息,例如ID

![module對象實例]()數據庫

Note: exports 對象實際上指向 module.exports的引用,若是隨意替換module.exports的引用,則會致使兩者的實際引用不相同。不瞭解這個問題的話,在世紀城使用中,可能會遇到一些難以預料的問題。npm

模塊標識

模塊標識是一個字符串,理論上應該是小駝峯式的命名方式,或者以「.」 , 「..」及「/」開頭的路徑。
若是模塊標識是文件路徑,理論上不須要在文件名後面加後綴「.js」。json

未指定的約定

在符合CommonJS規範的狀況下,有一些機制能夠隨意實現。之因此這麼說,是由於實際上這些東西也是構建完整模塊所必須的,但CommonJS並未嚴格定義這些東西,理論上只要可以完成既定目標就能夠。後端

  1. 模塊的存儲方案,模塊但內容能夠存儲在數據庫、文件系統、工廠函數甚至一個連接庫中;
  2. 模塊加載器能夠支持PATH環境變量用於加載時但尋址,也能夠不支持,不做強制限制

Node.js的模塊

Node程序一般就是由一個個的模塊拼裝起來的。這些模塊可能的形式: js文件、json文件、C++模塊的二進制文件.node

這些模塊都是經過 require函數 引入。

Node中的模塊查找

Node中的模塊分爲兩類: 核心模塊 和 文件模塊。

核心模塊存在於Node源碼,屬於Node自帶模塊。主要是一些基礎性的模塊,例如:fs, http等。它們查找很是簡單,若是require中的模塊標誌符與這些核心模塊的名字吻合,則直接返回這些核心模塊export出的內容。

文件模塊是須要經過查找文件來得到的模塊。這些模塊都是第三方開發者編寫的程序,並不屬於Node自己的一部分。它們是你在編寫Node程序(基於Node.js運行的程序, Not Node.js self)時,引入的文件。

文件模塊又能夠分紅 第三方模塊項目模塊

若是傳入require函數是一個文件路徑,通常能夠看做是項目模塊。對於項目模塊,若是路徑中指定了具體文件,則直接引入。若是路徑是一個目錄,則首先查找是否存在package.json文件,若是存在且在package.json中定義了main屬性,則根據main屬性的值查找模塊的入口文件,若是沒有,則依次查找目錄下的index.js, index.json以及index.node

若是傳入require函數的是一個非路徑的值,則能夠看做 第三方模塊。Node查找第三方模塊也有一套規則存在。

  1. 當前文件(require函數所在的文件)的 node_modules目錄;
  2. 當前文件父級目錄下的 node_modules下,若是沒有,則繼續向上級目錄,直至根目錄下的node_modules;

找到對應的模塊後,實際上也就等於獲取到了模塊的文件PATH,而後就會查找模塊的入口文件(查找規則跟項目模塊同樣),獲取模塊export的內容。

模塊緩存

Node會緩存require的模塊,也就是說若是某個模塊被加載過,當在有其餘模塊引用該模塊的時候,Node會直接讀取緩存中的內容返回。

Node的包機制

包描述文件package.json

主要內容以前有寫過。

包目錄結構

  • package.json在根目錄下
  • 二進制文件放在bin目錄下
  • JavaScript源碼放在禮拜目錄下
  • 文檔放在doc目錄下
  • 單元測試文件放在test目錄下

Node.js/ NPM下的包

NPM(Node.js Package Manager)。

在NPM中存在一個包信息描述文件————package.json。這個文件會記錄這個包的其它依賴。並且它的第三方模塊會被放到node_modules目錄中,這就致使有些開發者會把這個目錄也做爲項目的一部分提交到git倉庫,但咱們實際並不推崇這麼作。由於node_modules提供的文件是項目運行時所需,且一般狀況下,它的內容會比較多。咱們能夠根據pacakge.json文件的描述,在運行項目以前安裝這些依賴(通常經過npm命令npm install)。

若是你對第三方模塊的源碼有所改動,推薦的作法是在項目初始化時或者其餘比較合適的時機進行hack。

NPM下的package.json文件是基於CommonJS定義的包描述文件來實現的。但它有一些地方是與其不一樣的。這一點須要咱們明確。

NPM

在NPM中,NPM2與NPM3是有區別的,NPM2的依賴安裝路徑是嵌套式的,適合Node.js進行工具、後端的開發。在NPM2中,不一樣的的包若是使用名稱相同但版本不一樣的的第三方模塊,那麼這個模塊的兩個版本分別被放在各自引用者的node_modules目錄中,互不干擾。

node_modules
    ---- bar
        ---- node_modules
            ---- foo@1.0.0
    ---- baz 
        ---- node_modules
            ---- foo@2.0.0

而在NPM3中,依賴的安裝路徑變成了扁平式的。全部的第三方依賴包都被放倒根目錄下的node_modules中。這種方式適合前端項目:須要優化到很小代碼空間佔用量、以及打包分析等,同時順帶解決了Windows中文件路徑不容許過長的問題。

只有在遇到存在衝突的狀況下,纔會出現嵌套。

NPM3的思想:儘量的扁平化你的依賴。

CNPM

CNPM是阿里巴巴集團的Node.js團隊研發的一套更快的NPM工具。它比NPM快不只僅是依靠使用國內的鏡像,還有就是在安裝過程當中,將一些包緩存到node_modules/.npminstall 目錄下,再以符號連接(Symbol Link)的形式將依賴目錄鏈接到對應的路徑。也就是說,在實際安裝過程當中,相同版本的包只有一份實體,相似於NPM3。

Chrome V8

Node.js使用Chrome V8做爲Javascript的解釋器。

V8是一個高效的JavaScript引擎,不一樣於其餘JS引擎的地方:

  1. JIT編譯
  2. 垃圾回收
  3. 內斂緩存
  4. 隱藏類

JIT編譯

JIT編譯,Just-In-Time編譯,即時編譯。編譯輸出結果是機器語言,而不是字節碼。

垃圾回收

V8的垃圾回收器借鑑了Java VM的精確垃圾回收管理,其垃圾回收機制的效率是至關高的。

內聯緩存(Inline Cache)

若是訪問過a.b,那麼當再次訪問a.b時,不會再對哈希表進行一次尋址,由於V8已經緩存過這個屬性的偏移量,不用再次計算尋址的偏移量。

隱藏類

TODO: 隱藏類的具體機制還有待進一步查詢資料。

V8引擎比較高效的機制主要是 內聯緩存隱藏類

V8引擎遵循ECMA Script標準。Node.js會隨着V8的更新升級本身的代碼。

libuv

libuv 是一個專一於異步I/O的跨平臺類庫。最初是由Node的創始人Ryan Dahl爲Node寫的。只要是爲Node開發,可是也能夠支持其餘項目。

libuv中一個重要的概念是 事件循環

libuv的一些特性

  • 基於epoll/kqueue/IOCP/event ports實現的全能事件循環;
  • 異步TCP 和 UDP套接字
  • 異步DNS解析
  • 異步文件、文件系統操做
  • 文件系統事件
  • ANSI轉義碼控制的TTY
  • 使用UNIX domain套接字或者命名管道實現的套接字共享IPC
  • 子進程
  • 線程池
  • 信號(Signal)處理
  • 高精度時鐘
  • 線程和同步元
PS:不一樣的平臺有不一樣的異步機制(如epoll、IOCP等),libuv 基於此實現來跨平臺的事件循環。

另外libuv接口簡潔明瞭,靈活性好,便於使用。Node中事件循環直接使用libuv的事件循環。

Node中其餘一些依賴

http-parser

一個C實現的HTTP消息解析器,能解析HTTP協議的請求數據和返回數據。

OpenSSL

安全套接字層協議庫。
SSL(Secure Socket Layer),能夠在網絡上提供祕密性的傳輸。用於對HTTP協議進行加密。

zlib

zlib是一個提供數據壓縮功能的庫。

IDE

神的編輯器和編輯器之神

  • VIM/NeoVIM
  • Emacs
  • Sublime Text
  • Visual Studio Code
  • Atom
  • Visual Studio

node-gyp

node-gyp 是 Node.js下的C++擴展構建工具。基於GYP(General Your Projects)進行工做,GYP時Google的一套構建工具。

node-gyp進行工做須要一些依賴。

在UNIX系列平臺下:

  • python
  • make
  • C++編譯工具包(GCC)

在macOS下:

  • xcode

在 Windows中

  • Visual Studio

也或者使用Visual C++ Build Tools(比較輕量級)。

相關文章
相關標籤/搜索