痛點
- 有時候執行npm install命令安裝某些模組的時候,特別慢,經常安裝失敗
- 公司內部的模組如何維護?
我們需要一個能夠讓公司內部模組穩定維護的私有倉儲,而且這個倉儲還能夠穩定的提供通過npm install獲取的安裝包,那麼cnpm來了~
CNPM是什麼
CNPM是一個私有的Nodejs庫,使用CNPM 有如下理由:
-
確保npm服務快速、穩定:對於企業來說,上線生產系統的時候,需要花半小時甚至更久等待npm模組依賴安裝完畢,是不可接受的。部署映象後,可以確保高速、穩定的npm服務。
-
釋出私有模組:官方的npm上的模組全部是開源的。一些與企業業務邏輯相關的模組可能不適合開源。這部分私有的模組放在私有NPM倉庫中,使用起來各種方便。
-
控制npm模組質量和安全:npm上的模組質量參差不齊,搭建私有倉庫,可以更嚴格地控制模組的質量和安全,只有經過稽核的模組才允許被加入私有倉庫。
-
使用MySQL替換了CouchDB,更容易部署。同時由於大部分開發者更熟悉MySQL,因此架設起來更方便。
-
部署簡單:只需要五分鐘
從CNPM的架構圖中,我們可以看出CNPM是對NPM做的映象服務,CNPM會定期同步NPM的資源庫,同時CNPM支援釋出私有的庫,這樣就非常方便地整合了公有庫和私有庫,對於公司內部的開發者來說,基本感覺不到兩種庫的區別。
搭建CNPM服務
從官方文件中,我們看到CNPM伺服器環境,只需要Node(0.11.12) + MySQL(>= 0.5.0),另外我們還需要Linux的環境,接下來就讓我們動手自己搭建一個私有NPM的伺服器
-
準備:
Linux 作業系統,如 Ubuntu 12.04.5 LTS Node: v6.0.0 Npm: 3.8.6 資料庫 ,如 MySQL: 5.5.40 Git客戶端 複製程式碼
-
從github下載專案原始碼,安裝專案依賴
git clone https://github.com/cnpm/cnpmjs.org.git cd cnpmjs.org npm install 複製程式碼
-
在config目錄下新建一個config.js 檔案,可以參考官方推薦的一些配置
下面列出一些常用的配置說明
- enableCluster:是否啟用 cluster-worker 模式啟動服務,預設 false,生產環節推薦為 true;
- registryPort:API 專用的 registry 服務埠,預設 7001;
- webPort:Web 服務埠,預設 7002;
- bindingHost:監聽繫結的 Host,預設為 127.0.0.1,如果外面架了一層本地的 Nginx 反向代理或者 Apache 反向代理的話推薦不用改;
- sessionSecret:session 用的鹽;
- logdir:日誌目錄;
- uploadDir:臨時上傳檔案目錄;
- viewCache:檢視模板快取是否開啟,預設為 false;
- enableCompress:是否開啟 gzip 壓縮,預設為 false;
- admins:管理員們,這是一個 JSON Object,對應各鍵名為各管理員的使用者名稱,鍵值為其郵箱,預設為 { fengmk2: 'fengmk2@gmail.com', admin: 'admin@cnpmjs.org', dead_horse: 'dead_horse@qq.com' };
- logoURL:Logo 地址,不過對於我這個已經把 CNPM 前端改得面目全非的人來說已經忽略了這個配置了;
- adBanner:廣告 Banner 的地址;
- customReadmeFile:實際上我們看到的 cnpmjs.org 首頁中間一大堆冗長的介紹是一個 Markdown 檔案轉化而成的,你可以設定該項來自行替換這個檔案;
- customFooter:自定義頁尾模板;
- npmClientName:預設為 cnpm,如果你有自己開發或者 fork 的 npm 客戶端的話請改成自己的 CLI 命令,這個應該會在一些頁面的說明處替換成你所寫的;
- backupFilePrefix:備份目錄;
- database:資料庫相關配置,為一個物件,預設如果不配置將會是一個 ~/.cnpmjs.org/data.sqlite 的 SQLite;
- db:資料的庫名;
- username:資料庫使用者名稱;
- password:資料庫密碼;
- dialect:資料庫介面卡,可選 "mysql"、"sqlite"、"postgres"、"mariadb",預設為 "sqlite";
- hsot:資料庫地址;
- port:資料庫埠;
- pool:資料庫連線池相關配置,為一個物件;
- maxConnections:最大連線數,預設為 10;
- minConnections:最小連線數,預設為 0;
- maxIdleTime:單條連結最大空閒時間,預設為 30000 毫秒;
- storege:僅對 SQLite 配置有效,資料庫地址,預設為 ~/.cnpmjs/data.sqlite;
- nfs:包檔案系統處理物件,為一個 Node.js 物件,預設是 fs-cnpm 這個包,並且配置在 ~/.cnpmjs/nfs 目錄下,也就是說預設所有同步的包都會被放在這個目錄下;開發者可以使用別的一些檔案系統外掛(如上傳到又拍雲等),又或者自己去按介面開發一個邏輯層,這些都是後話了;
- registryHost:暫時還未試過,我猜是用於 Web 頁面顯示用的,預設為 r.cnpmjs.org;
- enablePrivate:是否開啟私有模式,預設為 false; 如果是私有模式則只有管理員能釋出包,其它人只能從源站同步包; 如果是非私有模式則所有登入使用者都能釋出包;
- scopes:非管理員釋出包的時候只能用以 scopes 裡面列舉的名稱空間為字首來發布,如果沒設定則無法釋出,也就是說這是一個必填項,預設為 [ '@cnpm', '@cnpmtest', '@cnpm-test' ],據蘇千大大解釋是為了便於管理以及讓公司的員工自覺按需釋出;更多關於 NPM scope 的說明請參見 npm-scope;
- privatePackages:就如該配置項的註釋所述,出於歷史包袱的原因,有些已經存在的私有包(可能之前是用 Git 的方式安裝的)並沒有以名稱空間的形式來命名,而這種包本來是無法上傳到 CNPM 的,這個配置項陣列就是用來加這些例外白名單的,預設為一個空陣列;
- sourceNpmRegistry:更新源 NPM 的 registry 地址,預設為 https://registry.npm.taobao.org;
- sourceNpmRegistryIsCNpm:源 registry 是否為 CNPM,預設為 true,如果你使用的源是官方 NPM 源,請將其設為 false;
- syncByInstall:如果安裝包的時候發現包不存在,則嘗試從更新源同步,預設為 true;
- syncModel:更新模式(不過我覺得是個 typo),有下面幾種模式可以選擇,預設為 "none";
- "none":永不同步,只管理私有使用者上傳的包,其它源包會直接從源站獲取;
- "exist":定時同步已經存在於資料庫的包;
- "all":定時同步所有源站的包;
- syncInterval:同步間隔,預設為 "10m" 即十分鐘;
- syncDevDependencies:是否同步每個包裡面的 devDependencies 包們,預設為 false;
- badgeSubject:包的 badge 顯示的名字,預設為 cnpm;
- userService:使用者驗證介面,預設為 null,即無使用者相關功能也就是無法有使用者去上傳包,該部分需要自己實現介面功能並配置,如與公司的 Gitlab 相對接,這也是後話了;
- alwaysAuth:是否始終需要使用者驗證,即便是 $ cnpm install 等命令;
- httpProxy:代理地址設定,用於你在牆內源站在牆外的情況。
閱讀了上面的配置,你可能會編寫一份如下的配置檔案
module.exports = { debug: false, enableCluster: true, // enable cluster mode mysqlServers: [ { host: 'localhost', port: 3306, user: 'root', password: 'xxxxxx', } ], mysqlDatabase: 'cnpmjs', enablePrivate: true, // enable private mode, only admin can publish, other use just can sync package from source npm admins: { admin: 'example@example.com', }, scopes:['@IModules'], syncModel: 'exist'// 'none', 'all', 'exist' }; 複製程式碼
-
建立並初始化MySQL資料庫
$ mysql -u yourname -p mysql> use cnpmjs; mysql> source docs/db.sql 複製程式碼
-
啟動CNPM伺服器,預設會開啟兩個埠,7001用於NPM的註冊服務,7002用於Web訪問。
node --harmony_generators dispatch.js 複製程式碼
或者 npm run start npm run dev:除錯模式啟動; npm run test:跑測試; npm run start:啟動 CNPM; npm run status:檢視 CNPM 啟動狀態; npm run stop:停止 CNPM。
-
瀏覽器訪問CNPM私有倉庫
127.0.0.1:7002 複製程式碼
終於正常了,這樣就成功搭建了私有的NPM註冊服務。
配置npm源為公司內部倉庫
-
配置npm 源為公司私有倉庫
npm config set registry http://cnpm.xxx.cn/ #這個是將上文IP對映的域名 複製程式碼
-
檢視是否操作成功
npm config ls 複製程式碼
執行命令,來安裝一個私有庫(後面的文章會建立)
npm install --save @IModules/IUtils@0.2.0-snapshot
複製程式碼
載的時候指定我們自己的私有庫,這樣就會從我們自己的私有庫中下載。如果私有庫沒有對應的庫,CNPM會自動同步到NPM 找到我們要下載的庫和版本,先在CNPM中存一份,然後再傳給客戶端一份,執行原理和Maven的原理一樣。 或者使用如下命令,臨時安裝 npm install winston --registry=http://127.0.0.1:7002
工具庫
私有倉儲建立起來了,後面就開始動手建立上文中提到的IUtils庫併發布到私有倉儲
這裡我提供一份支援釋出的私有庫檔案,具體的請參考這裡