Sinopia | 從零開始搭建npm倉庫
使用 Node.js 開發商業項目,其中除了技術選型,最令人糾結的一個問題就是私有NPM怎麼託管,有的人說:
我用 git+ssh 這種方式直接引用到 GitHub 項目地址
嗯,這種方式可行,也最簡單,但真真的太爛了,姑且不說不能使用 semver,關鍵還是 url 太丑,如果是強迫症真的沒法忍~
我用 cnpm 代理
暫且不論 cnpm 只是作為鏡像使用,其實這個方案缺點就挺多的,用的人多,速度不一定快,緩存,關鍵是不支持發布包以及登陸、註冊,再加上配置過於複雜。
那好,我是土豪,我要買 npm on-site
說實在的,我就是從這個方案跳出來的,因為 npm 的服務對於國內團隊真的是挺貴,而且還死慢,得不償失,性價比太低。
好,下面進入正題了,我今天就是要給你們安利新get的神器:Sinopia,首先,要介紹一下這個項目的作者:
是的,看上去是一個大神,也是一隻貓~ 往社區內貢獻過很多代碼,包括 jshttp, markdown-it 等等,也是 Node.js 核心代碼庫的活躍貢獻者。
是的,我今天要安利的項目大家都看到了,就是1779顆星星(?)的那個項目,不過這裡插句題外話,看到項目裡面基本都不怎麼更新了,不過好在我在使用的過程沒怎麼遇到 Bug。
首先,我先大概講講 Sinopia 的思路,我大概掃過一眼代碼,大致有以下三點:
通過兼容官方的 Registry 的介面來對終端中 NPM 命令的兼容,從而不需要使用像 cnpm 這樣的命令
正是由於 npm 支持諸如 --registry 以及 .npmrc 這樣的配置文件,所以才使得上一條可以正常使用,而不需要任何 hacky 的代價
官方的 npm 使用 CouchDB 作為倉庫資料庫(大致聽說),不過 Sinopia 將直接使用文件系統來作為存儲結構,這樣可以非常方便我們對緩存以及發布的倉庫進行查看
上圖就是一個 Sinopia Registry 的倉庫截圖。
下面就開始搭建 Registry 伺服器,其實作者已經將步驟簡化到不能再簡單了,如果本地搭建,直接通過:
$ npm install sinopia -g
然後再通過:
npm set registry http://localhost:4873/
來設置客戶端使用的npm代理,然後就能正常使用了,接下來,為了可以發布你的私有庫,你需要一個用戶名:
npm adduser --registry http://localhost:4873
按照 npm 所給的提示輸入完畢後,需要再登陸一次(之前的 adduser 相當於註冊用戶):
npm login
同樣根據提示完成登陸,這個時候,打開 ~/.npmrc 你就應該能看到更新後的配置文件,接著你就可以使用 npm publish 來發布代碼庫到你的這個私有倉庫給你的團隊小夥伴使用了。
事情還沒完,眼睛尖的小夥伴可能已經發現:
誒?npm adduser 貌似不需要任何驗證就能添加,那豈不是所有人都能訪問到我的私有倉庫代碼了嗎?
答案是 YES,不過不用著急,奴家這就說說怎麼來配置驗證與角色許可權。
首先你在啟動 sinopia 的時候,可以指定一個配置文件,在裡面可以設置一些像:
storage: 倉庫保存的路徑
web: 是否支持WEB介面
auth: 驗證相關
uplinks: 配置上游的npm伺服器,主要是用於請求的倉庫不存在時去上游伺服器拉取
packages: 配置模塊/包的發布(publish)、下載(access)的許可權等
listen: 配置監聽埠與主機名
這裡著重講一講 auth 和 packages 的用法。
auth:
htpasswd:
file: ./htpasswd
# Maximum amount of users allowed to register, defaults to "+inf".
# You can set this to -1 to disable registration.
max_users: -1
最後一行特別重要,這裡我們將最大用戶數設置為-1,表示禁用 npm adduser 命令來創建用戶,不過我們仍然可以通過當前目錄下的 htpasswd 文件來初始化用戶,這裡我們可以將團隊小夥伴的用戶名密碼都添加了進來,下面就是一個示例:
yorkie:{SHA}?????????????????=:autocreated 2016-02-05T15:33:46.238Z
weflex:{SHA}????????????????=:autocreated 2016-02-05T15:39:19.960Z
james:{SHA}????????????????=:autocreated 2016-02-05T17:59:05.041Z
scott:{SHA}????????????????=:autocreated 2016-02-05T17:59:05.041Z
naruto:{SHA}??????????????=:autocreated 2016-02-05T17:59:05.041Z
上面的加密演算法也很簡單,就是簡單的SHA1哈稀之後再轉換成 Base64 輸出就好,後面跟著的只是表示時間。
好,接下來說一下 packages:
packages:
@weflex/*:
access: $authenticated
publish:
- admin
- yorkie
*:
access: $all
publish: $authenticated
proxy: npmjs
可以看到上面的配置大致分為兩個部分,一個是以 @weflex/* 為開頭的,另一個則是通配符 *。
這個當然就是對 package.json 中的 name 欄位進行匹配,比如 @weflex/app 將匹配第一個配置,而 express 則匹配第二個。
這裡這麼配置的意義在於:一般團隊或者公司的私有項目,會採用不同的許可權控制,於是這裡借用了 NPM 的 scoped name 即 @company 的形式,例如 @weflex/app 即表示 WeFlex 下屬的 app 項目了。
接下來,每一個命名過濾器(filter)下都有三項基本設置:
access: 表示哪一類用戶可以對匹配的項目進行安裝(install)
publish: 表示哪一類用戶可以對匹配的項目進行發布(publish)
proxy: 如其名,這裡的值是對應於 uplinks 的
對於1和2的值,我們通常有以下一些可選的配置:
$all 表示所有人都可以執行對應的操作
$authenticated 表示只有通過驗證的人可以執行對應操作
$anonymous 表示只有匿名者可以進行對應操作(通常無用)
或者也可以指定對應於之前我們配置的用戶表 htpasswd 中的一個或多個用戶,這樣就明確地指定哪些用戶可以執行匹配的操作
所以,上面 packages 的配置文件可以解讀為:
驗證過的用戶可以安裝 @weflex 下的包
名為 admin 或 yorkie 的用戶可以發布 @weflex 下的包
所有人都可以獲取到非 @weflex 下的包
驗證過的用戶可以發布非 @weflex 下的包
配置完成後,再運行:
$ sinopia -c config.yml
就能放心、安全地使用你的 NPM 包了。配置完成後,如果你設置了 web.enable 為 true 的話,還可以通過網頁的方式來瀏覽你的 Registry 情況。
另外,關於如何託管你的進程,你可以使用 docker, pm2 或者 forever 都可以。不過記住,千萬要保存好你的 htpasswd 文件,不要泄漏到任何公有倉庫中去。
至此,一個可以完整使用的 NPM Registry 伺服器就搭建完成,雖然文章很長,但是整個搭建過程真的很短,很簡單,希望可以給各位一個比較好的商業NPM以及NPM翻牆的解決方案。
不過,以上的情況並沒有考慮在遇到一些黑客攻擊的情況下,所以為了盡量保證代碼的安全,可以在前端加一層 Nginx 然後配置 SSH 公鑰來作為雙層驗證。
該文從我的微信公眾號拷貝:Sinopia | 從零開始搭建npm倉庫
推薦閱讀:
※npm的應用場景,剛需在何處?簡單的寫寫頁面是否需要npm包管理工具?
※Node快閃:npm模塊版本策略
※IoT開發的利器,pi-sync
※Node.js中的哪些庫讓你相見恨晚?
※semver:語義化版本規範在 Node.js 中的實現