1. NodeJS會是曇花一現嗎
在用了一年以後,我感覺node.js有一點不對勁。它很有意思,但是我覺得我應該用另外一個視角去審視它。
網路編程真的可以更容易嗎?
node.js無疑有一些設計非常好的地方。前段時間我寫了一個性能非常高的Syslog Collector系統,它可以每秒處理25萬個日誌,可以同時處理數千個TCP並發連接。它還支持UDP,HTTP和SSL.它是C++寫的,使用了
Boost.Asio 架構。它幾乎從來不會崩潰。 很少會內存泄露。但是它花了我5個月的時間去編輯(然後重寫),測試還有布署。所以,你要知道,寫相似的node程序真的不會讓你加快開發進度。
需要一個HTTP伺服器?require(導入)
http 模塊,如果你想要一台socket伺服器的話,還需要net模塊。node是一個事件驅動的框架。相對於為每個鏈接創始一個線程模型相比有極大的性能優勢,node.js取得了
twisted無法能取得的成功。 (注* twisted 基於python的非同步驅動框架)
node.js的問題是什麼?
JavaScript
讓我們先說JavaScript -
我喜歡用它的閉包,但是這個語言太扯蛋了。甚至是JavaScriptr的鐵桿粉絲都知道它有多可笑。JavaScript the Good
Parts (JavaScript好的方面) 真的是一本很簿的書,對比一下你會覺得很有趣。
你會發現下面的代碼根本不會報錯:
undefined=42
然後你輸入這個看看?
> [] + []
''
為什麼1個空數組加上另外一個空數組會等於空字元串?
然後這個呢?
> [] + [] * 5
'0'
解釋JavaScript為什麼會這樣其實挺困難的。就像為
無數個猴子設計的語言。 所以在線編程是非常重要,你得經常列印一下看看到底會輸出什麼。
調試
我看到的大多數node.js程序員都在用一種非常原始的方式在調試,並不斷地對他們用的工具表示失望。跟蹤回調里不該招聘的異常,在類似Mocha和
Chai的測試框架中,經常會像惡夢一樣。時間不斷地花在尋找為什麼會出錯上面。console.log也許是開發者最常使用的調試工具。
回調地獄
大多數程序員,只要在node上面寫了36個小時的代碼,就會發現callback hell。有些
文章 介紹了一些避免的方法。具有諷刺意味的是,這是node的非同步和事件驅動所天生的。它帶來了很多性能上的優勢,但導致了這種難看和不可靠代碼的產生。
但是我們有
Promises。
是的,我同意。不過如果不是用Bluebird這樣的模塊,我估計大多數node程序員馬上就會放棄。我非常喜歡用Promise模式,它寫出的代碼非常
優美。Promise的鏈式寫法是非常好的實踐。但是它讓你放棄了徹底修復回調地獄的想法。我嚴重懷疑這一點會破壞NodeJS在生產環境應用的可能性。
我只會佔用一個核,但只能用一個核。
node.js總是運行在一個進程里。這讓他進行跨函數和跨模塊的調用更加的簡單。但這並不意味著是沒有代價的,你必須確保你在做出更改的時侯進程不被打斷。但是當你使用多核CPU時,你就無法發揮出其它處理器的性能。你就開始罵娘了。當然node裡面有集群
Cluster 模塊,但是它還處在實驗階段,而且用它你還得重寫你程序的邏輯。你最初的設計可能很少考慮到需要分布式處理的情況。
那麼該怎麼辦?
寫高性能的網路和分布式程序是當代程序員應有的基本素質。框架應該降低內容的切換——像node一樣,允許我們創建高性能的伺服器。但是還有比node.js更好的框架。
Go 是一個很好的侯選對象。它基於一個健壯的庫,為網路編程而設計。而且編寫伺服器像node一樣容易。
Goroutines 允許程序員不必擔心回調式的書寫方式,讓程序員以更自然的,線性的思維去思考。而且Goroutines真的非常輕量級而且內容切換比操作系統的線程間切換更輕量,這種系統級的線程操作正是node.js想要避免的。
Go可以最大可能地發揮多核的優勢。這是它的基因。我寫了很多Go的代碼,而且它的體驗要比node要好很多。
不要把我的話當回事
我的node和JavaScript經驗並不像C/C++或Python那樣豐富。但是我的直覺告訴我node.js只是我們朝著向更好的網路編程邁進的一步。它已經解決很多問題了,但是應該還有更好的方法。
轉載
2. Nodejs Commonjs和ECMAScript(ESM)模塊系統導出與導入
深入理解Node.js的模塊系統,我們主要關注Commonjs和ECMAScript (ESM)兩種模塊系統。雖然目前兩種系統仍在共存,但了解它們的差異與應用是程序員的必備技能。
Commonjs模塊系統中,導出方式多樣,包括命名導出、函數導出、類導出以及類實例導出等。在導出時,我們通常使用`exports`或`mole.exports`關鍵字。
相比之下,ECMAScript模塊系統在較新的Node.js版本中得到支持。默認情況下,Node.js採用Commonjs語法導入和導出模塊,嘗試使用ECMAScript模塊會導致錯誤。要啟用ECMAScript模塊,我們需在`package.json`文件中添加`"type": "mole"`欄位。一旦確定了`type`欄位,就不能再使用Commonjs語法,需要進行相應的調整。
Node.js支持模塊的非同步導入與導出,具體實現方式包括根據命令行參數選擇模塊導入。通過創建如`el.js`、`en.js`等文件來展示非同步導入的實現。
ECMAScript模塊系統在運行時遵循嚴格模式,且不支持Commonjs提供的某些引用,如`require`、`exports`、`__filename`、`__dirname`。若需使用這些內容,我們需要尋找替代方案。
TypeScript,微軟主導的JavaScript衍生語言,提供了更嚴謹的代碼編寫方式。在TypeScript中,我們使用`export`關鍵字導出模塊,並通過`import`導入。對於使用`export=`導出的模塊,需要通過`import Mole = require('mole')`來進行導入。TypeScript官方文檔提供了關於導入與導出的詳細示例。
為了幫助理解模塊系統之間的差異,我們准備了示例代碼。這些代碼分別在`COMMON`、`ECMA`、`async`和`TS`文件夾中,展示了不同模塊系統下的導入與導出方法。每個文件夾下的`main`文件用於模塊導入與測試,而其他文件則展示了各種導出方式的示例。這些示例代碼的下載鏈接可供參考。