1.模塊(Model)編程
一般所指「模塊」是指編程語言所提供的代碼組織機制,利用此機制可將程序拆解爲獨立且通用的代碼單元。app
根據不一樣的關注點,將一個項目的能夠共享的部分抽取出來,造成獨立的Module,就是模塊化。框架
對於JavaScript來講,在ES6以前,並無語言內置的模塊機制,但咱們用一些方式自制了某種模塊機制,像CommonJS / AMD甚至創建了廣泛接受的社區標準。雖然它們都是模塊機制,但會有一些重大或微妙的差別。故當咱們提到JS模塊時,若是沒有足夠的上下文,有時須要明確是CommonJS module或AMD module或ES6 module。編程語言
對於CSS來講,並無廣泛接受的「CSS模塊」概念。一個CSS樣式表裏能夠經過@import
來引入其餘樣式表,但咱們一般並不稱之爲「模塊」。多份樣式表以cascade機制結合,這和咱們通常編程語言中模塊互相調用的方式至關不一樣。且CSS的@import
語義基本上就是最簡單的include,也就是將@import
語句替換爲導入樣式表的內容。而編程語言中的導入模塊會在當前做用域導入命名空間、符號等,比簡單的include要複雜許多。模塊化
有關「CSS模塊」的問題,咱們後面還會討論。spa
注:在Web標準中,「CSS module」其實指CSS spec自己的模塊化。這也是咱們應該避免採用「CSS模塊」來指代CSS代碼的組織結構的重要緣由。prototype
其實我公司裏對「模塊」的用法也比較隨便。好比咱們有/static/js/modules/
目錄,其實下面就是一些腳本,並無採用任何一種module規範。再如咱們有/src/modules/
目錄,下面每一個子目錄是業務模塊,裏面包含了view、controller和相關的各類類。設計
這裏一個是歷史因素——目錄結構不是我創建的,你們習慣如此,都知道咱們講的「module」是指業務模塊,跟具體編程語言裏的module沒有直接的關係,只要溝通沒有什麼障礙,那也沒必要改了。不過當咱們完成引入JS module loader和相關設施以後,極可能仍是須要從新調整文檔和目錄命名,以免可能的理解錯位。code
回到關於「模塊」的定義討論上,我建議運用此術語時儘可能避免擴張性解釋——即避免在脫離特定機制的general的「模塊化」的意義上使用「模塊」這個詞。component
好比,傳統的JS代碼組織方法之一,是掛在global上的層級命名空間。此嚴格上很差稱之爲「模塊」。緣由是namespace只提供邏輯劃分,不解決代碼自己的劃分。若是沒有其餘機制,代碼劃分仍然是文件爲單位,並由開發者本身指定script加載。同理,咱們一般認爲C++裏沒有模塊(儘管有namespace和include),可是PHP咱們認爲有模塊(由於它有autoloader能夠根據namespace映射到目錄去加載文件)。
固然,即使編程語言沒有模塊,咱們仍然能夠經過一些方式進行「模塊化」編程,但這種模糊的用法有可能形成誤解。在JS這邊由於咱們已經有很成熟的CommonJS / AMD / ES6 module了,更應避免模糊用法。
2.組建(component)
另外一個概念是「組件」。大致上「組件」和「模塊」的概念是相似的,只是「組件」一般指更high-level的東西。
我我的體會,「模塊」指代碼單元,其意義偏向靜態的代碼結構。而「組件」指功能單元,其意義偏向運行時的結構,並有更復雜的控制(如組件實例的生命週期管理)。
舉例來講,在組件系統中,你應該能夠比較容易的作到在運行時查找某種組件並替換爲另外一種組件(熱插拔)。而這一般並不做爲模塊系統的需求——即便模塊系統支持動態加載,一般也不支持註銷舊模塊;即便支持註銷舊模塊,一般也不支持替換全部舊模塊的引用(意味着須要從新 實例化/初始化 模塊依賴樹上全部直接或間接引用此模塊的模塊)。
注:的確有某Node.js平臺下的遊戲框架設計以class做爲模塊單元,經過替換prototype來作到模塊的熱插拔。不過這其實要求很是多的編程方式約定,實際上可被視爲使用的是JS的一個裁剪的特性子集,於是不具備廣泛性。