文章原創於公眾號:程式猿周先森。本平臺不定時更新,喜歡我的文章,歡迎關註我的微信公眾號。 其實在JavaScript的發展中,它主要是在瀏覽器前端中被應用廣泛。因為在實際應用中, JavaScript的表現能力主要取決於宿主環境的API支持程度, 在最早期,只有對BOM, DOM的支持,隨著HTML ...
文章原創於公眾號:程式猿周先森。本平臺不定時更新,喜歡我的文章,歡迎關註我的微信公眾號。
其實在JavaScript的發展中,它主要是在瀏覽器前端中被應用廣泛。因為在實際應用中, JavaScript的表現能力主要取決於宿主環境的API支持程度, 在最早期,只有對BOM, DOM的支持,隨著HTML5的出現,在瀏覽器中出現了更多,更強大的API供JavaScript調用,但是這些都是發生在前端,後端JavaScript的規範卻遠遠落後。Java有class文件,Phthon有import機制,PHP有include和require,但是JavaScript通過script標簽引入代碼的方式顯得雜亂無章,為我們的後期維護增加了難度。對於JavaScript來說,還有四大主要缺點:
1.沒有模塊系統。
2.標準庫比較少。
3.沒有標準,統一的介面。
4.缺乏包管理系統。
Node.js實現了一套非常易用的模塊系統,而Node的包管理系統NPM對包規範的完好支持使得Node應用在開發過程事半功倍。這一篇文章,主要針對Node的模塊以及包的實現進行說明。
Node的模塊規範
其實模塊的定義非常簡單,主要分為模塊引用,模塊定義和模塊標識三個部分。
1)模塊引用
Node.js中存在require()方法,這個方法接受模塊標識,以此引入一個模塊的API到當前的上下文中。
2)模塊定義
既然我們可以用require()來引入模塊,那自然也可以引出模塊。Node.js提供了exports對象用於導出當前模塊的方法和變數,並且exports是唯一導出的出口。在每個模塊中,存在一個module對象,表示模塊本身,exports其實就是module的一個屬性。在Node.js中,一個文件其實就是一個模塊,將我們需要導出的方法和屬性綁定在exports對象上作為屬性就可以將該方法或屬性導出。
在另一個模塊,可以通過require()引入模塊,就可以使用導出的方法sum()。
3)模塊標識
模塊標識其實傳遞給require()方法的參數,模塊標識必須是符合駝峰命名的字元串或者以./,../開頭的路徑,引入模塊模塊標識可以省略.js尾碼。
模塊的好處是將特定的方法和變數限定在特定的作用域中,使得開發者完全不必去考慮變數污染的問題。
Node.js的模塊實現
在Node.js中,有三類模塊,其中一類是Node.js提供的核心模塊,就比如上一篇說過的fs文件模塊,database資料庫模塊,還有一類是開發者自行編寫的文件模塊,就比如剛纔示例的test.js模塊,第三類就是自定義模塊,這是一種特殊的文件模塊,一般是一個文件或包的形式,比如引入mysql所需的jar包。
在Node.js中引入模塊,需要經歷三步:
(1)路徑分析
對於文件模塊來說,引入時模塊標識指明瞭確切的文件位置,所以在路徑分析中可以省略大量時間,載入速度僅次於核心模塊。
自定義模塊則是會從項目根目錄逐個比較路徑,直到找到目標模塊為止。所以,自定義模塊的路徑越深,路徑分析的耗時越多,所以自定義模塊的載入速度是最慢的。
(2)文件定位
剛纔其實說過了,模塊標識可以不包含尾碼名,所以Node.js在文件定位時會依次補充.js,.json,.node尾碼名,然後去進行文件定位,因為Node.js是單線程,所以文件定位時會發生堵塞,所以如果引入的模塊尾碼是.json或者.node,可以在引入的時候加上尾碼,可以提高查找速度。
(3)編譯執行
定義到具體文件後,Node.js會創建一個模塊對象,然後將模塊引入並且編譯。每一個編譯成功的模塊其文件路徑都會作為索引緩存在緩存對象上,以提高二次引入模塊的性能。
核心模塊在Node.js源代碼的編譯過程中,直接被編譯成二進位文件,然後被直接載入到記憶體中,所以核心模塊引入時,文件定位和編譯執行這兩個步驟可以直接跳過,並且核心模塊在路徑分析中會被優先判斷,所以核心模塊的載入速度是最快的。
文件模塊則是在執行時動態載入,所以路徑分析,文件定位以及編譯執行這三個步驟都不可省略,所以載入速度比核心模塊慢。
Node.js對引入過的模塊會進行緩存,以減少二次引入模塊的性能開銷二次載入模塊一律採用緩存優先方式。核心模塊的緩存檢查優先於文件模塊。
包管理工具NPM
剛纔說到Node模塊,但是雖然我們可以引用模塊,但是模塊與模塊之間仍然是散列在各地的,相互之間並不能直接引用。而Node的包管理工具NPM則將模塊相互聯繫起來。包其實是在模塊的基礎上進一步組織JavaScript代碼。
其實NPM會有一個包描述文件package.json,一般位於包的根目錄, NPM的所有行為都與包描述文件息息相關。前面幾篇有講過NPM作為預設包管理工具,會作為Node環境被一起安裝。
NPM常用功能
NPM幫助Node完成了第三方模塊的發佈,安裝和依賴。因為有NPM的存在,Node和第三方模塊之間形成了很好的一個生態系統,而且逐漸越來越強大。接下來大致講解下幾個NPM常見命令
npm --version 查看當前NPM的版本
npm 查看幫助說明
npm help 查看具體命令說明
執行命令會在瀏覽器中打開對應命令的說明文檔
npm install 安裝依賴包,預設使用–-save參數,即預設添加到package.json中
執行該命令,NPM會在當前目錄創建node_modules目錄,然後再node_modules創建對應依賴包的目錄,然後將依賴包解壓到該目錄。
npm init 在此目錄初始化生成package.json文件
npm uninstall
卸載依賴包, 預設使用-–save參數,即從package.json中移除 npm ls查看當前目錄的依賴包
npm root -g 查看全局安裝地址
npm list
查看依賴的當前版本
NPM存在的問題
在NPM平臺,每個人都可以分享包,所以包質量沒有辦法保證,而且Node.js運行在服務端,所以需要考慮安全問題。所以一個優秀的模塊需要符合幾大模塊:
具備良好的測試
具備良好的文檔
具備良好的測試覆蓋率
具備良好的代碼規範
今天內容就到這裡了,其實這篇文章並沒有涉及到代碼的編寫,而是從模塊的角度去理解Node.js,Node.js通過模塊規範,彌補了JavaSCript沒有結構性的不足,而NPM通過對包的統一管理,使得項目開發中的依賴問題得到有效解決。
下一篇將從非同步編程的角度帶大家繼續瞭解Node.js,下一篇再見!
歡迎關註我個人公眾號:程式猿周先森