# How To Make Angular Library & Npm Package
## Create Angular Library Project
Angular Cli v6 之後支援 monorepo 架構,可以在同一個 repo 中管理多個專案,在開發 library 時,方便將 library 及 demo 用的 application 建置在一起。
首先,我們用 `ng new` 建立一個不包含 application 的空 workspace:
```bash=
$ ng new ngx-time-picker --create-application false
```
root directory 下只會有設定檔及 `node_modules/`,而不會出現常見的 `src/`。
接著依序建立 library `ngx-time-picker`
```bash=
$ ng generate library ngx-time-picker
# shortcut: ng g lib <library name>
```
及 application `demo`:
```bash=
$ ng generate application demo
# shortcute: ng g app <application name>
```
application `demo` 的用途是在開發期間用來測試 library。
建立完成後的 workspace 架構會如下:
<kbd>

</kbd>
---
## Angular Library Develop Environment
在 library 開發過程中,我們希望可以將 library 引入 demo 中顯示並監看異動,可以建立以下的開發環境:
### Build Library
在被其他專案引入使用之前,angular library 需要先被完整建置
```bash=
ng build --watch ngx-time-picker
```
- 加上 `--watch` 參數,可以監測程式碼異動,自動重新建置。
- 建置 library 預設就是 production。因此不需要加上 `--prod`。
- 當 ngx-time-picker 為 `defaultProject` 時 project name 可省略 (`ng b --watch`)。
### Export Public APIs
我們需要將 library 中所有對外暴露的部分寫進 `public-api.ts` 中:
```typescript=
export * from './lib/ngx-time-picker.module';
// export * from './lib/ngx-time-picker.directive';
```
### 在 demo project 中引入 ngx-time-picker
```bash=
$ ng serve --project=demo
```
> 如果 workspace 中只有一個 application 時, application name 也可以省略。
在創建 library 時,angular 已經自動將 library path 寫進 `tsconfig.json` 的 paths mapping:
```json=
"paths": {
"ngx-time-picker": [
"dist/ngx-time-picker"
],
"ngx-time-picker/*": [
"dist/ngx-time-picker/*"
]
}
```
因此當我們要在 project demo 中引入時,只需要使用 path alias:
```typescript=
import { NgxTimePickerModule } from 'ngx-time-picker';
```
---
## Angular Library Dependencies
angular 官方建議 library 對 angular 套件的 dependency,應該要寫入 package.json 的 `peerDependencies` 欄位:
```json=
"peerDependencies": {
"@angular/common": "^8.2.0",
"@angular/core": "^8.2.0",
"@angular/forms": "~8.2.0",
"@angular/cdk": "^8.2.3"
},
```
如果是將依賴寫在套件的 `dependencies` 欄位,遇到相依套件版本衝突時,npm 可能會在套件下的 node_modules 安裝另一個版本,因而產生在同一個專案下有多套 angular 的情況發生。
---
## Pack Angular Library as Npm Package
### local package
在已經建置好的 `ngx-time-picker` 資料夾中執行
```bash=
$ npm pack
```
產生的 `ngx-time-picker-0.0.1.tgz` 即是 npm 的 local package。
其他專案可以以下方式,直接安裝此 package:
```bash=
$ npm i <local package path>
```
安裝 local package 一樣會將安裝紀錄寫進 package.json:

> npm 5 以後 `npm install <package>` 預設會寫進 `dependencies`,不需要再加上 `--save`,如果希望不寫入 `dependencies` 則可使用 `--no-save`。
### publish package to npm registry
要將建置好的 angular library 發佈在 npm registry,需要先在 npm 上註冊會員並登入。
```bash=
$ npm login
```
登入後在已建置的 `ngx-time-picker` 資料夾中執行
```bash=
$ npm publish
```
就會將我們的 library 推上 npm registry 囉!
- npm registry 會以 `package.json` 來取得套件資訊
```json=
{
"name": "ngx-time-picker",
"version": "0.0.2",
"description": "Time picker for Angular reactive form",
"peerDependencies": {
"@angular/common": "^8.2.0",
"@angular/core": "^8.2.0",
"@angular/forms": "~8.2.0",
"@angular/cdk": "^8.2.3"
},
"author": "kristxeng",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/kristxeng/ngx-time-picker"
},
"keywords": [
"angular",
"cdk"
]
}
```
- 在 npm registry 發佈新套件之前,要先確認 name 欄位沒有與 npm 上現有套件相同,如果有相名套件,npm 會預設你要 publish 該套件,而回傳權限的錯誤。
- 再次發佈時,版號也不能與之前相同,所以在每次新發佈之前都需要修改版號。
---
## 附註A: npm 打版號的方式
可以利用 npm version 指令幫我們自動打版號並標上 tag
假設 `package.json` 內 `version` 為 `1.1.3`
> npm 打版號的指令:
> `npm version major` 1.1.3 -> 2.0.0
> `npm version minor` 1.1.3 -> 1.2.0
> `npm version patch` 1.1.3 -> 1.1.4
以升 major 版本為例,下 `$ npm version major` 指令,除了 `package.json` 內的版本號由 `1.1.3` 變為 `2.0.0`,還自動提交 message 為 `2.0.0` 的 commit,並標上 `v2.0.0` 的 tag。
---
## 附註B: Private Npm Registry
### Verdaccio · A lightweight open source private npm proxy registry
verdaccio 是在本地端架設的輕量級 npm registry 資料庫。在本地搜尋不到相關套件時,預設會向官方的 npm registry 搜尋。
全域安裝 verdaccio
```bash=
$ npm install -g verdaccio
```
啟動 verdaccio
```bash=
$ verdaccio
```
verdaccio server 預設開啟在 `http://localhost:4873`
**verdaccio 的 GUI**
<kbd>

</kbd>
### 變更 npm registry 指向
全域變更:
```bash=
$ npm set registry http://localhost:4873
```
如果只有單次指令變更 registry 指向,可以使用 `--registry` 參數的方式:
```bash=
$ npm i local-ngx-time-picker --registry http://locahost:4873
```
{"metaMigratedAt":"2023-06-15T03:27:54.595Z","metaMigratedFrom":"Content","title":"How To Make Angular Library & Npm Package","breaks":true,"contributors":"[{\"id\":\"2a77d55c-abe0-413d-b49c-f19e74b63460\",\"add\":7485,\"del\":3059}]"}