---
# System prepended metadata

title: github package && npm repo
tags: [github]

---

---
tags: github
---

[toc]

# github package && npm repo

## 開發流程
``` mermaid
graph TD;
local_package-->npm_login;
npm_login-->npm_build;
npm_build--->github_repo;

github_repo-->git_action;
git_action-->npm_publish;
npm_publish-->github_package;
npm_publish-->npm_repo;
```


---

### npm_login : 

**1. publish to npm repo**

驗證npm publish權限，登入npm 帳號。

**指令：npm login**

**2. publish to github package**

驗證npm publish權限，登入 github repo ower 帳號。


**指令 ： npm login --scope=@OWER --registry=https://npm.pkg.github.com**

**注意** ： 這時登入的密碼需要透過生成 **Personal access tokens** 當作密碼，以確保發布者的所有權限。

 [如何生成Personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)


---

### npm_publish

**npm publish** (發布私有包)
**npm publish --access public** （發布公開包）

**注意 :** **npm publish** 預設是私有狀態，如果 **package.json** 中有設定 **"private": false** 將會報錯

---

### npm_build
在 **package.json** 執行npm script測試打包後的模組結構指令如下。

```json=
//package.json
  "scripts": {
      "dev": "next dev",
      "start": "next start",
      "lint": "next lint",
      "build-next": "next build",
      "build": "rm -rf dist/ && npm run build:esm && npm run build:cjs && npm run build:css",
      "build:css": "tailwindcss build styles/globals.css -o public/styles.css --minify && copy-files-from-to",
      "build:esm": "tsc  --project tsconfig.production.json",
      "build:cjs": "tsc --project tsconfig.production.json --module CommonJS --outDir dist/cjs",
      "prepublish": "npm run build"
 },

 "copyFiles": [
    {
      "from": "public/styles.css",
      "to": "dist/main.css"
    }
  ],
```

### 打包規則
* **build:css** ：因為專案是用 tailwindcss 開發，所以需要打包 css 檔案，之後透過 copy-files-from-to 套件將打包好的 css 放到 dist 資料夾中。
* **build:esm && build:cjs** : 透過 tsconfig.production.json 打包需要模塊到 dist 資料夾中。
* **copyFiles** ：讓 copy-files-from-to 知道哪些哪檔案需要移入 。

#### 打包建議
因為打包套件很像在寫測試他是獨立的專案，所以建議把所有型別放 _TYPES_ 資料夾中去管理，之後引入套件才不會出錯。

![](https://i.imgur.com/w5hBRhs.png)

**備註 ：** 因為專案中也需要做 ts 檢測，所以會分成 tsconfig.production.json 作為打包的設定檔。

### 打包後的結構如下
使用套件時會考慮開發者使用什麼模塊所以會分別打包 **cjs（CommandJS）** 跟 **esm(esModule)** 兩種模塊，以及套件中用到的所有樣式檔案都在 main.css 中 。

![](https://i.imgur.com/ghOTda7.png)

每一個 component因為 tsconfig.production.json 設定的關係所以會有
* *.d.ts 型別宣告檔
* 基礎模塊*.js引用入口
* *.js.map 錯誤代碼位置讓之後更新套件方便查錯
![](https://i.imgur.com/xEUchZc.png)


### 如何使用套件

> #### step.1 在 _app.tsx 中引用打包好的樣式文件
![](https://i.imgur.com/ZPQPZaS.png)

> #### step.2 根據套件位置引入
![](https://i.imgur.com/c4LTJdO.png)

---

### git_action

**git action** 是一個 **CI** 工具，讓使用者可以推送到 **github repo** 時自動執行動作，例如推送打包的套件到 **npm repo** 或 **github PKG** ，**github** 稱以上的動作叫 **workflow**，**workflow** 可以在專案中新增以下的資料夾來啟用。

![](https://i.imgur.com/2z76Ccm.png)

```yml=
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages

name: Node.js Package

on:
  release:
    types: [created]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
      - run: npm ci
      - run: npm test

  publish-gpr:
    needs: build
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
          registry-url: https://npm.pkg.github.com/
      - run: npm ci
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

```

更多 **git action** 教學請看以下的連結 ：

[教學](https://docs.github.com/en/actions)

---


## 本地測試套件使用情形


``` mermaid
graph TD;
local_package-->npm_link;
local_package-->npm_install;
npm_link-->another_project;
npm_install-->another_project;
```
### 在本地測試套件有兩種方式 ：
**1. npm install ~/[PACKAGE_PATH]**
安裝方式跟平時使用 **npm i** 的方式一樣，差別在於要指定套件路徑去安裝。

**2. npm link**
使用npm link 之前要在套件專案下npm link指令，之後到要測試的專案使用 **npm link [@OWER/PACKAGENAME]**
 
**npm link** 其實就是將專案復用到電腦根目錄的位置，使用npm link 就是讓其他專案與根目錄的.nvm檔案做連結去使用。

> 結構如下 :

![](https://i.imgur.com/09jbEMv.png)

---

## package.json

### npm相關套件設定
```json= 
{
 "name": "@ani1788/danny",
 "version": "1.0.0",
 "main": "dist/cjs/index.js",
 "module": "dist/esm/index.js",
 "private": false,
 "files": [
  "dist"
 ],
 "repository": {
  "type": "git",
  "url": "https://github.com/ani1788/point-trade-platform-ui"
 },
 "publishConfig": {
  "@ani1788:registry": "https://npm.pkg.github.com"
 },
 "scripts": {
  "dev": "next dev",
  "start": "next start",
  "lint": "next lint",
  "build-next": "next build",
  "build": "rm -rf dist/ && npm run build:esm && npm run build:cjs && npm run build:css",
  "build:css": "tailwindcss build styles/globals.css -o public/styles.css --minify && copy-files-from-to",
  "build:esm": "tsc  --project tsconfig.production.json",
  "build:cjs": "tsc --project tsconfig.production.json --module CommonJS --outDir dist/cjs",
  "prepublish": "npm run build"
 },
  "copyFiles": [
    {
      "from": "public/styles.css",
      "to": "dist/main.css"
    }
  ],
 "dependencies": {
  "@svgr/webpack": "^6.4.0",
  "next": "12.3.1",
  "react": "^17.0.2",
  "react-dom": "^17.0.2"
 },
 "devDependencies": {
  "@types/node": "^18.7.18",
  "@types/react": "18.0.20",
  "@types/react-dom": "18.0.6",
  "autoprefixer": "^10.4.12",
  "eslint": "8.23.1",
  "eslint-config-next": "12.3.1",
  "postcss": "^8.4.17",
  "tailwindcss": "^3.1.8",
  "typescript": "4.8.3"
 },
 "peerDependencies": {
  "react": "^17.0.2",
  "react-dom": "^17.0.2"
 }
}



```
**name(套件名稱)** : @OWER/YOUR_PROJECT 。

**version** : 套件版本。

**main** ：模塊預設進入的路徑。

**files** ：npm build 時要包含哪些資料夾。

**repository** ：package存放位置。

**prepublish** ：這個指令是執行 **npm publish** 時會做的指令，使用情境很像用 **husky** 的 **precommit** 功能，目的在於部署前打包一個 **dist** 資料夾後推送上去。

**publishConfig** : 告訴你 **publish** 的 **repo** 套件擁有者跟套件名稱。

**peerDependencies** ： 當使用者下載你發佈的套件後會發現也把開源者使用的 **library** 也一起下載了，這樣會有重複下載其他套件的問題，會造成其他套件版本衝突，這時 **peerDependencies** 就是告訴 **npm** 我下載這個包時只會指定下載哪些使用者需要的 **library**。



---

## tsconfig.production.json
```json=

{
    "compilerOptions": {
        "allowSyntheticDefaultImports": true,
        "declaration": true,
        "esModuleInterop": true,
        "jsx": "react",
        "lib": ["es5", "es2015", "es2016", "dom", "esnext"],
        "types": ["node"],
        "module": "es2015",
        "moduleResolution": "node",
        "noImplicitAny": true,
        "noUnusedLocals": true,
        "outDir": "dist/esm",
        "sourceMap": true,
        "strict": true,
        "target": "es6"
    },
    "include": ["./components/**/*.ts", "./components/**/*.tsx"]
}
```
**declaration** : 打包時自動生成宣告檔。

**esModuleInterop** : 作用是支持使用import d from 'cjs'的方式引入commonjs包。

**jsx** : jsx檔案要用什麼方式解析。

**sourceMap** : 自動生成sourceMap。

**outDir** : 打包後的路徑。

**include** : 哪些檔案需要經過編譯。


---


## .npmrc（ 套件權限資訊 ）

```npm=
npm.pkg.github.com/:_authToken=YOUR_TOKEN
@OWER:registry=https://npm.pkg.github.com
```
**_authToken** : **npm login** 密碼

**@OWER** : github repo OWER


### customer npm init
https://blog.greenroots.info/tips-to-customize-npm-init-to-make-it-your-own
