使用 Gitlab package registry 發布與下載私人 npm 套件全記錄
前情提要:
近期在幫公司開發一個提供內部前端成員使用的 npm package。在開發的過程中有一個比較麻煩的點是,我過去從來沒有開發過 npm package 的經驗,對於如何設置開發環境、打包、發布、維護可說是完全從零開始研究。再加上公司不希望這個 package 開源給外部使用,也沒有計劃要付費使用 npm Orgs 的私人 npm 功能。因此,除了研究如何開發 npm package 之外,同時還得研究是否有免費且適合我們公司的私人 npm library 的解決方案。
問題
我研究了公司至今為止發布 npm library 的作法,發現公司至今為止所有共用函式庫的開發與發布流程大致如下:
- 開發端:
修改原始碼 → 在本機打包 → 將原始碼與打包後的檔案一併推到 gitlab 上 → 根據改動程度決定是否需要上 tag。
- 用戶端:
在本地專案中手動指定 package.json 中套件的專案路徑與版本 -> 把整個函式庫專案從 gitlab 上 clone 到本地端的 node_module
我覺得目前這樣的開發與發布流程隱藏了一些問題:
- 使用端下載套件時,會將原始碼以及其他靜態檔案 一同下載下來,造成 node_module 體積過大。
- 供使用端下載的打包檔案沒有錨定於套件版號。
- 發布流程(打包、更新版號、撰寫 CHANGELOG)全手動,不易維護且容易產生疏漏,比如更新版號時忘記打包最新版本的程式碼
總結上述問題中,我認為核心癥結在於:供使用端下載的打包文件應該與原始碼分開託管。
一般來說,我們使用 npm install 指令下載的套件都是託管在公開的 npm registry 中。然而,免費方案下的 npm registry 只能託管開源的套件,這無法滿足公司想要的私人 npm 需求。
經過一番搜尋後,我發現 Gitlab 提供了一個非常方便的解決方案: Gitlab Package Registry
,它可以像 npm registry 一樣運作,但同時保留了私人託管的特性。經過嘗試,我發現這個工具非常強大且易於使用。本篇文章將記錄如何將私人用的 npm library 發布到 Gitlab,以及如何從 Gitlab 下載 npm library。
Gitlab package registry 簡介
Package Registry 是什麼?
首先,我們來談談 package registry 到底是什麼。簡單來說,package registry 是一個可以儲存和管理軟體套件的地方。我們可以把它想像成一個專門放軟體套件的倉庫,讓開發者們可以方便地分享和重複使用這些程式碼與模組。
Gitlab Package Registry
是 Gitlab 提供的一個功能,讓我們可以在 Gitlab 的平台上管理自己的 npm packages。如此不僅可以把程式碼放在 Gitlab 上,還可以把 npm 套件一同託管於 Gitlab,這對於在使用 Gitlab 的公司或私人開發團隊來說非常方便。
Gitlab 如何作為 npm package 的容器?
在介紹如何發布 library 到 Gitlab 之前,讓我們來看看 Gitlab 如何作為 npm package 的容器。
首先,每個 Gitlab 專案(project)都有自己的 Package Registry,也就是說,每個 Gitlab 專案都擁有自己獨立的 npm packages 存儲空間用來存儲和管理多個 npm packages。而每個專案的 Package Registry 都有一個類似地址的唯一 URL,這個 URL 通常是以專案 ID 為基礎構建的。比如說,我在範例中建立的專案 ID 是 123,那麼 Package Registry URL 可能看起來像這樣:
https://<your_domain_name>/api/v4/projects/123/packages/npm/
這個 URL 主要是用來告訴 npm 使用者從哪裡下載或上傳套件。
Scope 與 Gitlab 的套件命名規則
接著,我們來談談 npm 如何知道哪些套件要從上述的 URL 上下載下來。
在 npm 中,Scope(命名空間) 是用來組織套件的一種方式,它允許開發者將套件歸類到特定的組織或團隊之下,從而避免命名衝突。例如,@my-org/my-package
表示這個套件屬於 @my-org
組織。
若我們將 GitLab 作為託管 npm 套件的 package registry,package.json 的套件名稱就需要遵循 Gitlab 的命名規則來命名:
"name": "@scope/package-name"
@scope 的值應該是託管套件的專案根目錄,而非套件原始碼的專案根目錄,且應使用小寫字母。
舉例來說,如果將 npm 套件託管於:
- http://<your_domain_name>/<instance_name>/<group_name>/<project_name>
- @scope 的值應為
@<instance_name>
- @scope 的值應為
- http://<your_domain_name>/<group_name>/<project_name>
- @scope 的值應為
@<group_name>
- @scope 的值應為
- http://<your_domain_name>/<user_name>/<project_name>
- @scope 的值應為
@<user_name>
- @scope 的值應為
package-name 則可以任意命名
當使用端在專 案底下新增新增一個 .npmrc
檔案,並加入以下內容後:
# Set URL for your scoped packages.
# For example package with name `@foo/bar` will use this URL for download
@<scope>:registry <your domain name>/api/v4/projects/<project id>/packages/npm/
當我們下載名稱以 @<scrop>
開頭的套件時,npm 就會知道要去指定的 registry URL 下載
Npm registry 身份驗證
在使用 Gitlab Package Registry 發布或下載 npm 套件的時候,Npm 會先進行身份驗證,確認對於某個 registry 來說是否有發布或下載的權限。
- 發布套件時: npm 會透過 npm config / .npmrc 與 package.json 的資訊進行身分驗證;
- 下載私人套件時:npm 也會透過 npm config / .npmrc 進行身分驗證。
Gitlab 提供了以下幾種驗證方法:
- Personal access token: 以使用者權限進行身份驗證,適用於個人
- Project deploy token: 為特定 project 創建的 token,適用於多個使用者,提供專案範圍內所有 packages 的訪問權限。
- Group deploy token: 為特定群組創建的 token,適用於多個使用者,可以用來存取該群組下的所有 packages。
- Job token: 適用於在 CI/CD pipeline 中發佈 package,如果要通過 CI/CD pipelines 發佈 npm 套件,這是唯一可以使用的選擇。
如果在專案設置中關閉了 “Package registry” 功能,無論使用哪種驗證方式都會收到 403 Forbidden
Gitlab package registry 權限
在 Gitlab 中,不同的專案角色對 Package Registry 的權限也有所不同,以下表格列出不同權限的最低角色要求:
Project visibility | 操作 | 最低角色要求 |
---|---|---|
公開 (Public) | 檢視 package registry | 無 |
發佈 package | Developer | |
拉取 package | 無 | |
內部 (Internal) | 檢視 package registry | Guest |
發佈 package | Developer | |
拉取 package | Guest | |
私有 (Private) | 檢視 package registry | Reporter |
發佈 package | Developer | |
拉取 package | Reporter |
Gitlab 也允許設定不論 Project visibility 與最低角色要求,使所有人都具有 pull package 的權限:
- Settings > General.
- > Visibility, project features, permissions.
- → Allow anyone to pull from Package Registry
- → Save changes.
準備 GitLab Package Registry
具備 Gitlab package registry 的基本知識後,我們就可以開始嘗試來發布一個 npm library 到 Gitlab 上。首先我們先來處理 Gitlab 的部分。
建立 Gitlab Project
在這篇範例中,我在我個人的專案目錄下建立了一個新的 Gitlab 專案,專案 ID 為 691
設定 Deploy token
接著前往 Setting > Repository > Deploy tokens 設定 Project deploy token。點擊 Create deploy 後會得到一組 Token,記得要把它記下來。
發布本地端的 npm 專案
準備好 Gitlab 後,接著就可以準備將本地端的 npm library 發布到 Gitlab 上了。在這篇教學範例中,我在根目錄的 index.js
下創建一個簡單的 function 並且匯出它,用來簡單模擬要發布的 library:
function sum(a, b) {
return a + b;
}
module.exports = sum;
準備 .npmrc
.npmrc
在發布套件時的作用有兩個:
- 指定以 @<scope> 為套件命名開頭的套件要發布到的 package registry 位置
- 發布套件到指定 package registry url 時,提供 authToken 進行身份驗證
在套件 專案底下新增一個 . npmrc 檔,並加入以下內容:
# Set URL for your scoped packages.
# For example package with name `@foo/bar` will use this URL for download
@<scope>:registry <your domain name>/api/v4/projects/<project id>/packages/npm/
# Add the token for the scoped packages URL. Replace <your_project_id>
# with the project where your package is located.
//<your domain name>/api/v4/projects/<project id>/packages/npm/:_authToken=<your token>
- @<scope>: 由於這個 Gitlab 專案建立於我的個人目錄專案底下,因此在此處為我的 gitlab user-name: @bosh.kuo
- <your domain name>: 為公司的 gitlab domain
- <project id>: 691
- <your token>: 即剛剛創建的 project deploy token
準備 package.json
在發布套件前,,需要先確保以下幾個選項是否正確設定,這些選項將直接影響套件的發布和使用。
- name: 套件名稱,須遵循上述的 Gitlab 命名規則
- version: 套件的版本號,每次發布新版本時,記得更新這個版本號。
- publishConfig: 這個選項用來配置發布時的一些參數,特別是 registry 的 URL。我們需要將這個設定為 Gitlab 的 Package Registry URL。
- files: 這個選項用來指定哪些文件應該包含在發布的套件中。通常我們會包括
lib
或dist
目錄(打包後檔案的目標目錄),這取決於我們的專案結構。 - main: 這個選項指定了套件的主入口文件。當其他人安裝並使用你的套件時,這個文件將作為入口。
- module: 如果套件是用 ES module 編寫的,可以使用這個選項來指定 ES module 的入口文件。
- types: 如果專案使用 TypeScript,這個選項用來指定 TypeScript 的定義文件。這樣用戶在使用套件時,可以獲得完整的 型別支援。
本篇範例中的 package.json 如下:
{
"name": "@bosh.kuo/published-package",
"version": "0.0.0",
"publishConfig": {
"registry": "https://gitlab.xxx.com/api/v4/projects/691/packages/npm/"
},
"main": "index.js",
"files": [
"index.js"
],
...
}
發布
一切準備就緒後就可以透過以下指令發布 npm 套件
# for npm user
npm publish
# for yarn user
yarn publish
發布完成後就可以在 Gitlab Package Registry 中看到剛剛發佈的套件了
圖上顯示 @bosh.kuo/published-package1 與 @bosh.kuo/published-package2 為後來嘗試用 monorepo 管理多個 npm library 時發布的,並非本篇文章範例中發布的套件,僅用於示例。
使用 GitLab Package Registry 上的 npm 套件
完成了上述發布流程後,我們可以在本地端建立一個使用端專案,嘗試把剛剛發佈的套件下載下來使用。
-
建立使用端測試專案
mkdir consumer
cd consumer
yarn init -y -
Npm registry 身份驗證
# Set URL for your scoped packages.
# For example package with name `@foo/bar` will use this URL for download
@<scope>:registry <your domain name>/api/v4/projects/<project id>/packages/npm/
# Add the token for the scoped packages URL. Replace <your_project_id>
# with the project where your package is located.
//<your domain name>/api/v4/projects/<project id>/packages/npm/:_authToken=<your token>同上章節的 .npmrc 檔。
此外,也可以透過 npm config set 指令的方式來設定:
npm config set @<scope>:registry <your domain name>/api/v4/packages/<project id>/npm/
npm config set -- '//<your domain name>/api/v4/packages/npm/:_authToken' "<your_token>" -
下載專案
yarn add @bosh.kuo/published-package
若下載成功的話,就可以在
node_modules
底下看到套件,其包含的目錄與檔案會與前章節中設定於package.json
內的files
一致。 -
測試套件
// index.js
const sum = require("@bosh.kuo/published-package");
console.log(sum(10, 20));如果所有環節都沒有出錯,應該會看到
30
的輸出。
如果你看到正確的輸出結果,那麼恭喜你!你的套件已成功發布並可以正常使用。這表示你已經成功地將一個私人 npm 套件發布到了 Gitlab Package Registry,並成功地下載並使用了它。