前端十萬個為什麽(之一):我們為什麽需要npm?
如果我能比別人看得更遠,那是因為我站在巨人的肩上。
——艾薩克·牛頓
現代前端開發已經離不開Node了。大家都知道在安裝Node時會附贈一個命令行工具Node Package Manager,即npm。或許你已經照著教程輸入過好多遍”npm install xxx”,並且你發現npm的命令林林總總幾十條,package.json的配置項令人眼花繚亂,但不知你有沒有認真想過,我們為什麽需要npm?如果沒有它,世界會怎樣?
我的理解,npm所做的一切都是為了解決軟件工程界一個一直以來的追求:代碼復用。抓住這個核心,也就抓住了正確理解和使用npm的鑰匙。
為什麽要復用代碼呢?因為基於已有的成熟代碼快速開發新的應用,可以極大地提高開發效率,正所謂“站在巨人肩膀上”“不要重復造輪子”。
So,在Node環境下要復用JS代碼,我們有哪些方案呢?
1. 刀耕火種——copy&paste
復制粘貼代碼的思路很直接,但如今還在的這樣搞的同學應該是從原始社會穿越來的吧。。這個方案最大的缺點倒還不是代碼冗余,而是一旦所復制的原始代碼發生了變化,那就必須手動修改每一處復本,在稍有規模的項目裏根本不可行。
2. 耕牛犁地——CommonJS
Node實現了一個模塊系統CommonJS,實在是JSer的一大福音。借助它,我們不必再復制粘貼代碼了:假如一個作者開發了一個名為lib1的庫,他只需代碼寫在一個名叫lib1.js的文件裏,用module.export語句導出;而使用者只需把lib1.js下載到自己工程目錄,require一下便可直接用啦!(此時lib1也被稱為一個“依賴”)
但這裏仍然存在兩個大問題:
一,如果lib1.js本身也復用了別的代碼,比如lib2.js、lib3.js...那你在下載lib1.js的時候,必須手動把它所依賴的這些模塊文件也一並下載;可要是lib2.js還依賴lib5.js、lib6.js....呢?一棵龐大的、深不見底的依賴樹很難手工管理。
二、lib1.js的作者修復了幾個bug,但沒有一個機制能讓他通知你升級舊的模塊文件。
作為一名職業素養良好的程序員,看到這些問題的第一反應是不是“寫個腳本”?哈哈,不用麻煩了,因為已經有人替我們寫好了,這個腳本工具就是npm。
3. 機械化耕作——npm
有了上面“自力更生”的原始體驗,再看看npm提供的依賴安裝、卸載、升級、發布等一條龍服務,是不是很爽?
Npm制定了一個包規範,所謂規範就是一些格式和約定,比如約定從package.json文件裏讀取這個包的所有信息,包括它的名字、版本號、它依賴於哪些別的包等;又比如約定node_modules目錄專門用來存放第三方依賴,Node為此提供的支持是內置的require方法默認會到這個目錄下去檢索模塊,而無需手動指定路徑。有了這些規範,一個包的開發、依賴安裝、發布等都步驟都標準化了,省心省力。
可以說,JavaScript從一門“玩具”語言,到如今可以勝任大型項目開發,模塊化和npm是其進化路上的重要一步。
後記
大家都知道前端有“三板斧”,但剛才我一直在談JS,完全沒提到另外兩板斧。這是因為npm只是“Node模塊管理器”,Node上又沒有HTML和CSS,npm自然管不到。那麽除了可以直接支持Node端的開發以外,npm又如何為瀏覽器端開發提供支持呢?
答案是:npm生態圈提供了很多強大的前端開發工具,比如Webpack、Babel、ESLint等。特別是Webpack、Browserify、rollup這類構建工具,可以接手瀏覽器端的依賴管理重任,以及很多其他的附加功能。這些內容,且待下回分解。。
前端十萬個為什麽(之一):我們為什麽需要npm?