Javascript模塊全攬

以前寫的文章急速Js全棧教程獲得了不錯的閱讀量,霸屏掘金頭條3天,點贊過千,閱讀近萬,甚至還有人在評論區打廣告,可見也是一個小小的生態了;)。看來和JS全棧有關的內容,仍是有人很有興趣的。javascript

此次文章的內容,是JavaScript模塊。JavaScript Module 真是很討厭,可是不得不瞭解的話題。奇葩在於:css

  1. 它一個很是老的語言,而且使用很是普遍
  2. 但是它不少年來也不支持模塊。這得廠家當前是多大的心呢
  3. 再一個但是,它能夠直接用現有的語言機制,實現本身的模塊,這個就厲害了,由於它釋放了社區的力量。事實證實,社區果真不可小看,這個年代,螞蟻雄兵賽過大象的
  4. 再再一個可是,它的模塊還能夠有不少型的,這說的是分裂
  5. 這麼多型的模塊,還搞了各自獨立的標準出來,這說的是整合

最近的ES2017,終於在前端也有了媲美后端的模塊,可是你們並不許備把它用起來,不少人表示須要繼續Webpack玩轉ES6模塊html

把ES6模塊真用的起來,能夠不在意Webpack等打包工具帶來的加載優化,各類小文件沒必要打包這點來講,我看還得加上HTTP/2的配合就好不少了。這也是文章將要介紹的一個主旨吧。ES6模塊的引入,確實有可能對當前主流的打包模式有些影響,參考文章6內有所論述前端

文章天然也很多,可是寫做此文的理由仍是存在:java

  1. 我尚未看到一個完整的全覽,而且結合HTTP/2的更加沒有看到。
  2. 並且,在我看來,即便有了ES6模塊,也得了解和學習以前拼出來的各類模塊,由於社區內的代碼還大量的使用這樣的模塊,其中的一些設計模式,好比IIFE,也是值得一看的。
  3. 看到JS社區的熱情和推進力,相信JS發展的將來是美好的

目錄

  1. 最古老的模塊加載<script>標籤
  2. 此方法的若干問題
  • 全局變量。全局命名污染和命名衝突
  • 依賴管理。都須要HTML管理,而不是分層管理依賴,多文件加載次序很是關鍵
  • 效率。太多HTTP請求,和並行加載效率低下
  1. 有問題引起的解決方法
  • 命令空間,匿名閉包、依賴引入
  1. 當前主流的模塊技術
  • Nodejs的作法,Commonjs方案
  • Nodejs借鑑
  • Require.js實踐,AMD和CMD,依賴就近原則
  • 從手寫模塊,到自動編譯,Browerify,Webpack,Rollup
  1. 剛剛落地的模塊技術
  • ES6模塊,官方發力,對現有技術的影響
  • 彌補ES6問題,HTTP/2
  1. 最佳實踐

從腳本加載開始

一切從Javascript的加載開始,自有Javascript依賴,第一個加載模塊的方案就是使用HTML標籤,也就是<script>標籤。也就是說,Javascript自己根本就沒有模塊和加載的定義,它是利用HTML來完成本該本身作的工做。node

這是初學者遇到的第一個使人困惑的問題。這樣的語言,根本就是一個玩具!也許有些尷尬,可是現實就是如此。而且如此的加載方案,在稍微大點的工程中,會遇到幾個違反常識的問題:webpack

  1. 全局命名污染。就是說每個被加載的模塊都會引入新的全局變量,他們會污染全局空間,並且必須當心命名,避免名字的衝突
  2. 依賴關係單一。此種加載方式,必須按照依賴關係排序,依賴性最大的模塊必定要放到最後加載,當依賴關係很複雜的時候,代碼的編寫和維護都會變得困難。
  3. 加載和執行效率難以細顆粒度的調優。一個個的按依賴次序加載和執行。雖然加載每每是能夠並行的,可是執行時串行的。加載的時候,瀏覽器會中止網頁渲染,加載文件越多,網頁失去響應的時間就會越長

仍是從一個案例開始。這個案例,不會作任何有意義的工做,也不會作什麼功能演示,而只是驗證古典的Javascript加載的能力和限定,驗證這些問題的存在,進而找到解決問題的方法。git

假設咱們如今有一個主程序,它在index.html內,一個模塊dep1,一個模塊dep2,依賴關係是index.html依賴dep1,dep1依賴dep2。代碼都不復雜,就是直接列表以下:es6

文件index.htmlgithub

// index.html
<script src="dep2.js"></script>
<script src="dep1.js"></script>
<script type="text/javascript">
	console.log(dep1())
</script>
複製代碼

文件dep1.js

var v1 = "dep1"
function dep1(){
	return v1+"-"+dep2()
}
複製代碼

文件dep2.js

var v2 = "dep2"
function dep2(){
	return v2
}
複製代碼

當使用瀏覽器加載index.html文件時,如我所願,它會隨後加載dep2,dep1,並調用函數dep1,後者調用dep2,而後在控制檯輸出:

dep1+dep2
複製代碼

功能是有效的,依賴關係是是對的,輸出也是如指望的。可是它也帶來了額外的問題:

  1. 全局變量污染。在本案例中,能夠在console內驗證,發現變量v1,v2,函數dep1,dep2都是全局變量。可是因爲script的加載機制,以及當前採用的Javascript函數和變量的定義不是局部化的,致使了這樣的問題。
  2. 依賴關係並不嚴密。事實上,dep2內的引入變量和函數,只有dep1看獲得便可,無需導入到全局變量內。
  3. 加載和執行效率難以細顆粒度的調優。本例內,dep1依賴dep2,它們被並行轉入,可是執行必須是串行的,首先執行dep2,而後執行dep1,在此案例中,這樣作是合適的,可是有很多代碼模塊之間並不存在依賴關係,它們徹底可能併發裝入併發執行,可是使用script裝入是不能如此的,它會按照標籤的次序一個個的執行。若是有比較好的指定依賴關係的方法就行了。

討論到此,我感受我在重複先輩們的話,實際上1960年代,第一屆軟件工程會議,就提出了模塊化編程的概念,而且在以後多年一直努力的批評全局變量和Goto語句了。有時候,你會發現,這樣看起來很是不濟的語言,卻能夠在現實的項目中如魚得水,發展的很是的好。而軟件工程思想指導下的一些名流語言卻早早夭折。這是另一個有趣的話題了,或許之後有機會談到。

後端的借鑑

後端Nodejs乾淨利索的解決了此問題。作法就是對每個裝入的模塊都注入一個require函數和一個exports對象。其中require函數能夠被模塊用來引入其餘模塊,而exports對象則被用來引出當前模塊的功能接口。仍是之前文提到的做爲案例,作法就是:

文件index.js

// index.js
var d = require('./dep1')
console.log(d.dep1())
複製代碼

文件dep1.js

var d = require('./dep2')
var v1 = "dep1"
function dep1(){
	return v1+"-"+d.dep2()
}
exports.dep1 = dep1
複製代碼

文件dep2.js

var v2 = "dep2"
function dep2(){
	return v2
}
exports.dep2 = dep2
複製代碼

執行命令:

$ node index.js 
dep1-dep2
複製代碼

這裏有一點變化,就是在nodejs內使用index.js代替了index.html。能夠看到:

  1. Nodejs提供了很好的局部化定義變量和函數的能力,若是使用exports聲明引出,其餘模塊看不到本模塊的定義。好比v2變量沒有聲明引出,固然實際上在本案例內原本也沒必要引出,那麼在dep1內並不會看到v2變量。相似的v1也不會出如今index.js內。
  2. Nodejs提供了更加細粒度的依賴關係。index.js依賴dep1,可是並不依賴於dep2,那麼index.js就只要引入dep1,而沒必要同時引入dep2。這樣的依賴關係,更加符合實際工程代碼的需求,而不是一股腦的、不分層次的引入所有須要用到的代碼。

在傳統的服務器開發的諸多語言中,模塊都是最基礎也是最必備的,像是JavaScript連個內置模塊支持都沒有的是不常見的(或者說根本沒有?)。使用諸如的require和exports,就在後端乾淨利索的解決了困惱前端的模塊問題,這難免讓前端以爲應該效仿之。固然,Nodejs加載模塊是同步的,這個是不能在前端效仿的。由於後端從磁盤加載代碼,速度根本不是問題,而前端加載的都是從網絡上進行的, 若是同步的話,加上Javas自己的單線程限定,整個UI就會由於加載代碼而被卡死的。對比下二者的速度差別,你就明白了:

硬盤 I/O		
-----------------
HDD:	100 MB/s	
SSD:	600 MB/s	
SATA-III:	6000 Mb/s	
-----------------
網速 I/O
ADSL:	4 Mb/s
4G:	100 Mb/s
Fiber:	100 Mb/s
複製代碼

借鑑後的樣子,先看看Modules/Async規範

思路倒也簡單,只要本身編寫一個庫,有它來異步加載其餘模塊,並在加載時注入須要的require和exports便可。這方面的庫有幾個,好比requirejs,sea.js等。由於咱們只是爲了講清楚概念和思路,所以會那概念上最清晰,和Nodejs最爲一致的庫來講明問題,並不會由於那個更加主流而去選擇它。從這個標準看,sea.js是說明概念問題的最佳模塊裝入庫。

sea.js 是一個模塊加載器,模塊加載器須要實現兩個基本功能:

  1. 實現模塊定義規範
  2. 加載運行符合規範的模塊

核心落腳點,就在規範二字上。sea.js要求模塊編寫必須在真正的代碼以外套上一層規定的代碼包裝,樣子看起來是這樣的:

define(function(require, exports, module) {
    // 模塊代碼
});
複製代碼

經過傳遞一個簽名爲function(require, exports, module)的回調函數給define函數,就能夠把須要注入的變量和函數注入到模塊代碼內。以前的實例代碼,在這裏寫成:

文件index.js

// index.js
define(function(require, exports, module) {
	var d = require('./dep1')
	console.log(d.dep1())
});
複製代碼

文件dep1.js

define(function(require, exports, module) {
	var d = require('./dep2')
	var v1 = "dep1"
	function dep1(){
		return v1+"-"+d.dep2()
	}
	exports.dep1 = dep1
});
複製代碼

文件dep2.js

define(function(require, exports, module) {
	var v2 = "dep2"
	function dep2(){
		return v2
	}
	exports.dep2 = dep2
});
複製代碼

除了加上一層有點看起來莫名其妙的外套代碼,其餘的模塊代碼,你該怎麼寫就怎麼寫。假若不是那麼潔癖,這樣的代碼確實解決了以前使用script標籤加載代碼帶來的全局變量污染等問題,而且仍是能夠異步加載的,那些看起來不錯的依賴關係,也如Nodejs同樣。以上代碼,能夠直接把nodejs對應的代碼拷貝過來,加上外套便可運行。

咱們不妨加入seajs文件,來看看實際的使用效果:

//index.html
<script type="text/javascript" src="https://cdn.bootcss.com/seajs/3.0.2/sea.js"></script>
<script>
  seajs.use('./index.js');
</script>
複製代碼

這裏爲了偷懶,我使用了seajs的CDN文件。若是有遇到什麼問題,你不妨本身下載一個seajs文件,而後改爲你的URL便可。

加載此HTML文件,能夠在控制檯看到輸出:

dep1+dep2
複製代碼

說明seajs執行效果不錯!

  1. seajs經過use方法來加載入口模塊,可選接收一個回調函數,當模塊加載完成會調用此回調函數,並傳入對應的模塊做爲參數
  2. 來獲取到模塊後,等待模塊(包括模塊依賴的模塊)加載完成會調用回調函數。
  3. 分析模塊的依賴,按依賴關係遞歸執行document.createElement(‘script’),這些標籤的建立會致使瀏覽器加載對應的腳本

對模塊的價值,都是異步加載,瀏覽器不會失去響應,它指定的回調函數,只有前面的模塊都加載成功後,纔會運行,解決了依賴性的問題。

能夠在控制檯輸入:

seajs.data.fetchedList
複製代碼

查看文件加載清單。

由於不是語言自帶,而是社區經過現有的語言特性,硬造出來的一個模塊系統,由於看起來代碼難免累贅。可是在沒有原生模塊的狀況下,這樣作確實是管用的。要知道真正的原生模塊,在ES6標準以後纔出現,這都是2015年的事兒了。在一些有名的應用如Gmail、Google Map的推進下,Web從簡單的展現到App的變化,迫切須要這樣相似的模塊技術,你們等不了那麼久,先弄一個能用的是很重要的。

爲何要套這層外殼呢?就是爲了解決全局變量污染問題。在JavaScript語言內,惟一提供本地做用域的就是函數和閉包,經過閉包function(require, exports, module),模塊加載器給模塊注入了必要的函數和變量。看起來在模塊以內的任何地方均可以使用require和exports,可是他沒都不是全局變量,而是閉包內變量。這些變量都是局部化的,絕對不會污染全局空間。

使用require函數,能夠就近指定對其餘模塊的依賴,函數自己是由sea.js這樣的模塊加載器提供,它會內部構造依賴關係圖譜,並根據依賴關係,設置加入script標籤的次序。

更加詳細的理解這層外殼,能夠閱讀seajs源代碼,代碼量並不大,值得一讀。或者看看此問答

固然Seajs也引入了本身的規範,叫作CMD規範。它的前身是Modules/Wrappings規範。SeaJS更多地來自 Modules/2.0 的觀點,同時借鑑了 RequireJS 的很多東西,好比將Modules/Wrappings規範裏的 module.declare改成define等。 說是規範,卻不像是通常的規範那麼冗長,可能打印出來也就一兩頁的紙張而已,這也是JavaScript社區的一個特色吧。Modules/Wrappings

seajs的做者在一篇文章中提到了業界在開發前端模塊加載器時的場景:

大概 09 年 - 10 年期間,CommonJS 社區大牛雲集。CommonJS 原來叫 ServerJS,推出 Modules/1.0 規範後,在 Node.js 等環境下取得了很不錯的實踐。09年下半年這幫充滿幹勁的小夥子們想把 ServerJS 的成功經驗進一步推廣到瀏覽器端,因而將社區更名叫 CommonJS,同時激烈爭論 Modules 的下一版規範。分歧和衝突由此誕生,逐步造成了三大流派:

  1. Modules/1.x 流派。這個觀點以爲 1.x 規範已經夠用,只要移植到瀏覽器端就好。要作的是新增 Modules/Transport 規範,即在瀏覽器上運行前,先經過轉換工具將模塊轉換爲符合 Transport 規範的代碼。主流表明是服務端的開發人員。如今值得關注的有兩個實現:愈來愈火的 component 和走在前沿的 es6 module transpiler。
  2. Modules/Async 流派。這個觀點以爲瀏覽器有自身的特徵,不該該直接用 Modules/1.x 規範。這個觀點下的典型表明是 AMD 規範及其實現 RequireJS。
  3. Modules/2.0 流派。這個觀點以爲瀏覽器有自身的特徵,不該該直接用 Modules/1.x 規範,但應該儘量與 Modules/1.x 規範保持一致。這個觀點下的典型表明是 BravoJS 和 FlyScript 的做者。BravoJS 做者對 CommonJS 的社區的貢獻很大,這份 Modules/2.0-draft 規範花了不少心思。FlyScript 的做者提出了 Modules/Wrappings 規範,這規範是 CMD 規範的前身。惋惜的是 BravoJS 太學院派,FlyScript 後來作了自我閹割,將整個網站(flyscript.org)下線了。這個故事有點悲壯,下文細說。

也談談require.js

這個模塊加載器是更加主流的。之因此不是首先提到它,是由於概念上來講seajs更加簡明。和seajs相比,requirejs是更加主流的框架。它的差別主要是一些零零散散的不一樣,好比模塊代碼的外套是不太同樣的:

require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
複製代碼

    // some code here });

導出模塊變量和函數的方式,也是不一樣的。requirejs的引出方式是直接返回:

return {foo:foo}
複製代碼

同樣的案例,使用requirejs的話,代碼是這樣的:

index.html文件

<script data-main="index"
 src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.js" ></script>
複製代碼

index.js文件:

require(['./dep1'], function (d){
	console.log(d.dep1())		
});
複製代碼

dep1.js文件:

define(['./dep2'], function (d){
	var v1 = "dep1"
	function dep1(){
		return v1+"-"+d.dep2()
	}
	return {dep1:dep1}
});
複製代碼

dep2.js文件:

define(function() {
	var v2 = "dep2"
	function dep2(){
		return v2
	}
	return {dep2:dep2}
});
複製代碼

瀏覽器打開文件index.html,能夠看到控制檯輸出同樣的結果。

稍加對比require.js和sea.js。使用Require.js,默認推薦的模塊格式是:

define(['a','b'], function(a, b) {
  // do sth
})
複製代碼

使用seajs的時候,相似的功能,代碼這樣寫:

define(function(require, exports, module) {
  var a = require('a')
  var b = require('b')
  // do sth
  ...
})
複製代碼

Seajs的作法是更加現代的。我須要用的時候,我纔去引用它,而不是實現什麼都引用好,而後用的時候直接用就好。

Modules/1.x規範

以require.js爲表明的Modules/Async流派,尊重了瀏覽器的特殊性,代價是無論寫什麼模塊,都得本身給本身穿上一層外套,對於有代碼潔癖的人來講,這樣的狀況是看不下去的。最好是開發人員編寫乾乾淨淨的模塊代碼,框架開發者作一個工具,這個工具自動的把這些代碼轉義成客戶端承認的異步代碼。即在瀏覽器上運行前,先經過轉換工具將模塊轉換爲符合規範的代碼。這就是Modules/1.x 流派的作法。須要注意的是1.x和2.0還有Async流派不能簡單的認爲版本號大的就更好。卻是理解成各自不一樣的解決方案爲好。

以咱們本身的案例來講,就是能夠直接把nodejs代碼那裏,使用一個工具作一個轉換,便可獲得符合前端須要的代碼,這些代碼是異步加載的、是能夠保證模塊變量局部化的、是能夠由良好的依賴關係定義的。工具browerfy就是作這個的。咱們來試試具體是怎麼玩的。

首先安裝此工具:

npm install --global browserify
複製代碼

到你的nodejs代碼內,而後轉換此代碼,生成一個新的js文件,通常命名爲bundle.js:

browserify index.js -o bundle.js
複製代碼

而後建立index.html並引入bundle.js:

<script type="text/javascript" src="./bundle.js"></script>
複製代碼

使用瀏覽器打開此HTML文件,能夠在控制檯看到熟悉的輸出,這說明轉換是有效的:

dep1+dep2
複製代碼

自己nodejs的代碼,是不能在瀏覽器執行的,瀏覽器內也沒有什麼require函數,可是轉換後就能夠執行了。那麼,轉換的過程,到底玩了什麼魔術?

像是browserify這樣的工具,就是找到全面被引入的代碼,解析它的依賴關係,而且自動的加入咱們在requirejs裏面須要的外套代碼。儘管bundle.js文件並非爲了閱讀優化的,可是能夠取出其中的代碼片斷來證明咱們的觀點:

{"./dep2":2}],2:[function(require,module,exports){
		var v2 = "dep2"
		function dep2(){
			return v2
		}
		exports.dep2 = dep2
},{}],3:[function(require,module,exports){
		var d = require('./dep1')
		console.log(d.dep1())
},{"./dep1":1}]},{},[3]);
複製代碼

咱們能夠看到原本的nodejs代碼,以及它們對應的外套。仍是比較簡單,就不進一步解釋了。browserify不但完成了加外套代碼的工做,還同時把若干小文件打成一個大的文件,對於當前使用的HTTP主流版本1.1來講,這樣作會讓加載效率更高。可是對於HTTP/2.0來講,它已經支持了多個文件在一個鏈接內交錯傳遞,所以再作打包的意義就不大了。只是...HTTP/2.0的普及還須要時日。

browerify完成的工做簡明而單一。另一個主流的同類工具叫作webpack,不但能夠轉換js代碼,還能夠打包css文件、圖片文件,而且能夠作一些工程化的管理,代價就是webpack學起來也困難的多。實際上像是Vuejs這樣的UI開發框架,內部就是使用了webpack作工程化管理和代碼轉譯的。可是在模塊化方面,二者是差很少的。就不另外介紹了。

ES6 Module

時間到了May 9, 2018,我看到了阮一峯發佈了這樣的微博:

今天 Firefox 60發佈,默認打開了ES6 模塊支持,至此全部瀏覽器都默認支持ES6模塊。前端開發模式可能所以大變。如今的方案是全部模塊發到npm,本地寫好入口文件,再用webpack打包成一個腳本。可是若是瀏覽器原生支持,爲何還要打包呢?至少簡單的應用能夠直接加載入口文件,瀏覽器本身去抓取依賴。 ​​​​
複製代碼

這裏全部瀏覽器指的是Edge、Firefox、Chrome、Safari。固然,再一次沒有IE。若是想要支持IE或者比較老的版本的話,仍是須要使用打包器來完成代碼的轉譯。另外不少人表示會繼續使用Webpack,緣由很簡單,Webpack不只僅是完成模塊打包工做,還有壓縮、混淆等,而且不少框架還須要依賴它。因此遷移並不是一朝一夕之功。而無需考慮老版本瀏覽器的兼容的代碼,是徹底能夠大量的使用它了。了不得在把Webpack加起來轉換ES Module到加外套的代碼就是了。

ES6 Module不是requirejs那樣加外套的樣子,也不是Nodejs使用require函數的樣子,而是另一套有官方提出的模塊模式。它使用的是import、export關鍵字。官方的就是不同,社區是加不了關鍵字的。一樣的案例,使用ES6 Module就是這樣的了。

index.html文件:

<script type="module">
		import {dep1 } from './dep1.js'
		console.log(dep1())
</script>
複製代碼

dep1.js文件

import {dep2} from './dep2.js'
	var v1 = "dep1"
	export function dep1(){
		return v1+"-"+dep2()
	}
複製代碼

dep2.js文件:

var v2 = "dep2"
	export function dep2(){
		return v2
	}
複製代碼

ES6 Module要求必須有後臺的HTTP服務器,而不能直接在文件系統上完成Demo的測試。所幸使用Nodejs搭建一個服務器也很是簡單直接:

npm i http-server -g
http-server
複製代碼

在瀏覽器內訪問此HTML文件的URL,能夠看到控制檯輸出:dep1+dep2。這個輸出,已是你的老朋友了。

Nodejs在10.9才支持實驗版本的ES6 Module,是落後了點,可是對於Nodejs來講,新的模塊技術原本也就並不迫切。

最佳實踐建議

綜合以上的內容,我認爲,在沒必要考慮古老的瀏覽器兼容的狀況下,最好的實踐是這樣的:

  1. 直接使用ES6 Module編寫模塊代碼
  2. 使用Rollup清除沒有調用的代碼,下降代碼的大小
  3. 使用Ugly工具壓縮和混淆代碼
  4. 使用HTTP/2作網絡傳遞協議

這樣的實踐,會隨着HTTP/2的逐步普及和ES6被更多的開發者採用,而成爲更好的選擇。

使用ES6 Module的壞處是沒法像require那樣動態的加載。可是好處是能夠精確指明對於一個庫,咱們使用的是那些,這就給工具提供了優化的可能,就是說若是我引入了一個庫,可是這個庫內有些我不會用的,那麼這些不會被用到的代碼也不會加載到前端了。這個功能對於後端來講意義不大,可是對於前端來講,就是很是使人喜歡的功能了。實際上,這樣的工具已經有了,比較知名的就是rollup,它屬於了一種被稱爲tree-shaking的技術優化使用代碼。

而以往作模塊打包,不少的緣由是HTTP/1.1傳遞大量小文件的時候開銷比較大,而打包成單一的問題,就能夠更好的利用HTTP/1.1的傳輸特性。可是HTTP/2.0的一個大的特點就是能夠在單一的鏈接內,併發和交錯的傳遞多個流,由於在一個鏈接內交錯的傳遞多個文件,就能夠再也不有HTTP/1.1的鏈接開銷了。所以,在HTTP/2.0被採納的網絡裏面,打包單一文件的價值幾乎沒有了。直接使用小文件默認狀況下就能夠獲得比較好的優化傳輸。

按照如今的技術發展的勢頭,要不了幾年,打包器將再也不那麼必要,使用原生代碼編寫模塊將會成爲主流的。

參考

參考文章很多,其中模塊歷史和選型以下:

  1. 前端模塊化開發那點歷史
  2. 梳理的仍是比較清晰
  3. 有點黑客精神的小夥伴,玩的很廣譜
  4. 介紹Bower
  5. npm for Beginners: A Guide for Front-end Developers
  6. Es6module 出來了,是否應該從新考慮打包的方案?

將來

這篇文章預計想要編寫的YUI方法,YUI Combo方法,想了想仍是算了,由於這樣的恐龍代碼,已經在平常的代碼實踐中逐步消失,做爲一個曾經比較重要,如今則退居二線的代碼庫,對它最好的讚許就是讓它退休,也沒必要給讀者增長額外的閱讀負擔了。畢竟require.js、browerify、webpack都工做的不錯,在此基礎上發展的Vuejs、React.js也的獲得了更多的承認。

本文講到的模塊規範和實踐工具,爲編寫一個廣爲社區承認的模塊起到了最基礎的規範做用。可是,JavaScript社區最爲使人稱道的就是代碼庫倉庫。包括NPM倉庫,Bower倉庫。在這些倉庫內,有模塊依賴管理工具,還有工程化工具。這些內容,它們固然是重要的,不在本文的範圍內。

做爲前端開發者,有人採用Bower管理組件依賴,也有人使用Npm作相似的工做。有不少時候,這樣的實踐是使人困惑的。還有這裏npm and the front end,NPM官方也對npm在前端的使用,提出了[本身的見解][blog.npmjs.org/post/101775…]。

這些未盡的內容,或許在將來的文章中表達之。

相關文章
相關標籤/搜索