隨著前端隊伍越來越壯大,專案間共享程式碼就變得尤為重要。常用的框架/類庫沒必要在每個專案都放一份,團隊內部產出的公共模組也需要有合理的共享機制。現在,用npm管理前端程式碼已經是業界趨勢。樓主嘗試用私有npm+資源管理系統的方式搭建起一套前端資源倉庫,用以在公司內部託管公共程式碼,併為開發環境提供程式碼源。本文記錄一下搭建過程,或許可以給大家做個參考。
整體架構
搭建私有npm的話其實是非常簡單的,github上有一個叫做sinopia(https://github.com/rlidwka/sinopia)的專案,使用相當簡單,無需配置資料庫。用阿里的cnpm也是可以搭建私有npm的,不過配置稍微麻煩些。鑑於只是beta階段,所以我就先採用簡單的sinopia了。npm有兩個作用:1.託管公共程式碼;2.為開發環境提供程式碼源。也就是說在開發環境,只需npm install,相應的程式碼就被下載到專案中。當然我們應該配置ignore,使得node_modules資料夾不被提交到程式碼庫。線上的資源都是走cdn的。
光是私有npm還是不夠的,考慮到公司不斷有新的前端入職,有些還是新手,所以有必要為每個模組提供詳細的說明。包括不限於基本資訊、使用方法、線上demo、cdn地址等等。使用README.md檔案雖然也能描述很多資訊,但它只是一個靜態檔案,我們的系統還需要具備釋出到npm、同步到cdn的功能。以後也可能進行功能擴充,比如為前端工程化提供支援。所以還需要一個資源管理系統,這個系統用於維護公共資源的各種資訊。
所以,這麼考慮下來,我們的前端資源倉庫應該包含兩部分:資源管理系統、私有npm。各自的功能如下:
資源倉庫的維護
所謂維護就是把原始碼錄入到資源管理系統、釋出到npm、同步到cdn這一過程。按照npm的規格來組織模組的目錄結構,但也不完全一致,因為有些是不需要的。模組都用UMD格式包裝,這樣無論用載入器還是直接寫標籤都是可用的。具體格式如下:
- 用模組的名稱命名根目錄
- 模組的不同版本,新建不同的目錄,如jquery/1.8.3/src/jquery.js,jquery/2.1.0/src/jquery.js
- src目錄,用於放置未壓縮的原始碼
- dist目錄,用於放置壓縮後的程式碼
- 使用package.json檔案的規格來描述本模組
這樣就夠了,系統提供釋出功能,上傳的檔案會自動釋出到我們的npm,並且同步到cdn。至於模組的使用方法等其他資訊,則需要模組維護者手動錄入到系統中。這樣,私有npm與這個資源管理系統就沒有任何耦合,將來也好做擴充套件。流程如下:
關於cdn的同步,我們只同步dist目錄下的檔案,因為線上只需要壓縮版。至於模組的打包,不在本系統的職責範圍內,由專案內的構建程式去完成。
如何使用
對於使用者,也就是前端同事們,需要做這麼幾件事:
- 專案中配置好package.json,npm install安裝好所需的模組
- 從資源管理系統中獲取到各模組的cdn地址
- 配置專案中的各模組地址,開發環境請求本地node_modules下的檔案,線上環境請求cdn。
- 使用gulp進行相關的構建,釋出到測試環境/線上環境
在npm install前,需要把倉庫地址指向我們搭的私有npm,而不再是npm官方的地址。使用npm set resigtry命令。如果你覺得麻煩,或者需要經常改動地址,github上有一個很方便的registry管理工具,nrm(https://github.com/Pana/nrm),推薦使用。
第3步需要做一個說明,因為我們現在專案很多,各專案的目錄結構也不一致,有的前後端還未分離,所以無法做到用同一套構建程式搞定所有的專案。配置的方法視專案的情況而定,可以依靠後端來動態給require.config賦值,也可以用gulp來進行編譯,總之能達到在不同環境請求不同路徑就行。
技術細節
sinopia的話照著文件去安裝就行。因為我們是安裝在伺服器上,所以有兩點配置需要注意:
- node_modules/sinopia/conf下的default.yaml中,listen: – 0.0.0.0:4873,使得其他機器可以訪問到該埠
- 在sinopia的儲存目錄下,有一個config.yaml,把proxy: npmjs注掉。我們公司內部可能只維護幾個特定版本,所以沒必要和官方倉庫同步。
sinopia有一個機制,當你從私有npm安裝一個模組時,如果不存在,會從npm官方倉庫拉取,也就是這個proxy配置的地址。我們注掉後,也就無法去官方倉庫去拉了,而這正是我需要的。一方面通過一個代理去訪問npm有不穩定的風險,另一方面,我需要使用者時刻清楚,自己安裝的模組是哪個倉庫的。
至於資源管理系統的開發,後端使用nodejs、express,mongodb資料庫,前端使用mvvm框架,還用了一個叫semantic的UI框架。基本就是對資源的增刪改查操作,基本也沒什麼難度 。資源包含的欄位如下:
其中,類別暫時分為三類:
- 框架/類庫。已經成熟的框架/類庫,基本不會修改其程式碼,如jquery、requirejs
- 第三方元件。UI元件及功能元件,來自於第三方,不像框架那樣穩定且有長期維護,例如:datepicker、彈框外掛
- 自研模組。公司內部自己寫的模組,通用的業務模組、功能模組
關於釋出npm。在系統中上傳原始碼的zip檔案,先進行解壓,然後使用了nodejs的child_process模組用來執行npm install命令,程式碼片段如下:
1 2 3 4 5 6 7 8 |
var exec = require('child_process').exec; exec('npm publish '+targetPath, function (error, stdout, stderr) { if (error !== null) { console.log('exec error: ' + error); res.json({success: false, message: error}); } res.json({success: true, message: {name: filePath} }); }); |
至於cdn的同步,請到了我們運維同學的幫忙,我只要把檔案上傳至相關目錄即可,後面的操作由他來搞~。
至此,我們的前端資源倉庫就搭建起來了,伺服器上使用pm2來管理,把sinopia和資源管理系統的server.js起來就可以了。
總結
搭建這個專案其實難度並不大,但由於是抽空閒時間來搞,前前後後花了兩個月時間。主要是花在系統的設計上。目前還是beta版,陸續會更新內容,先執行起來讓同事們嚐嚐,估計會有大量的建議和問題,後面再做升級吧。各位朋友有任何建議,也可以給我留言,不甚感激。最後,截圖來曬一下吧: