[實作筆記] GCP Load Balancer

前言

Load Balancing 的主要目的是確保系統的可靠性、高可用性和性能。
透過平均分發網絡流量到多個伺服器,我們可以防止單一伺服器的過度負載,從而減少系統故障的風險。
此外,使用負載平衡器還可以提供可擴展性,使我們能夠根據流量需求自動調整伺服器的數量,確保系統在高負載情況下仍能保持良好的性能。

但是,我希望使用負載平衡器來達到降低對外 IP 地址和憑證費用的目的,以降低維運成本。
透過只需為負載平衡器配置一個對外 IP 地址和憑證,而不需要為背後的多個伺服器分別配置對外 IP 地址和憑證。

現在的公司,在舊架構上開了多台的 VM,並且都提供了對外的 IP address 與憑証,
對我來說,不僅實際上較為省錢,管理上也會更好理解。

架構

GCP LB

如圖所示,我有兩台 VM , 一台用來放置 api 相關的服務,比如說,member 會員系統,
另外還有一些整合性的服務,分別使用 Php 與 Nodejs 開發,簡單想成 api Server 就好,
實際上在 VM 當中有掛載 Nginx 系統來管理其相對應的路由設定。
另一台 VM 也不單純,儘管他只提供靜態的 Landing Page 網頁與 Vue 建置 SPA 網站,
但在可預知的未來他會 Host 更多的靜態網站。

也許可以考慮其它的 GCP 解決方案,ex:App Engine、Cloud Storage;
但總之目前就是這樣的架構,而我主要目的是不希望花太多時間處理憑証與對外的固定 IP 的問題,
所以本篇將會以這樣的架構進行建置 Load Balancer

實作

  1. 建立後端服務:在這個案例我們建立兩台 VM,實際上你也可使用 Cloud Storage 或 Container。
  2. 配置後端服務的群組:在這個案例我們建立兩個 Group,可以參加架構圖,真正的實務上,你的 Group 應該會有多個(至少要兩個) VM。
  3. 建立 Load Balancer:在本案我們使用 HTTP(S) Load Balancing
  4. 設定 Frontend configuration,在這裡我們給它一個對外的固定 IP 並建立憑証(certificate)
  5. 設定 Backend configuration,在這裡我們會建立一個名叫 Backend Service 的抽像層,選擇 Instance group(參考第 2 點,也可以在這階段再進行建立)
  6. 設定 Routing rules,選擇 Simple host and path rule:

    本案中,我們會有兩個 domain 分代表前後端 api.exampleapp.example
    host 設定為 domain,而路徑設定為/*,後端指向對應的 group ,如下
    api.example|/*|prod-api-group
    app.example|/*|prod-f2e-group

GCP 與 Load Balancer 相關的服務

整個建置流程與 SSL 憑証、IP Address、backend-services、instance-groups 等服務相關
雖然在建立 LB 的過程中就會建立憑証(certificate),
但有些情況可以使用 gcloud 指令作細節的控管

比如說,列出 SSL 憑證:

1
gcloud compute ssl-certificates list

更多資訊請執行以下語法,

1
gcloud compute addresses --help

同理,可以用類似的語法查詢其它的資源

1
gcloud compute instance-groups --help
1
gcloud compute addresses --help
1
gcloud compute backend-services --help

ChatGpt 有時會亂掰一些指令出來,我沒有一一實際執行過的這裡就不提供了。
測試負載平衡器:在將負載平衡器放入實際生產環境之前,您應該進行測試,確保負載平衡器正確運作並且可以處理預期的流量。
監控和調整:一旦負載平衡器正式運行,您應該定期監控其性能和健康狀況,並根據需求進行必要的調整和優化。

20230706 補充

如果想要從特定的 GCP VM 下載檔案到本地端可以用以下指令

1
gcloud compute scp {your-db-name}:/{some-service}.log ~

參考

(fin)

[實作筆記] Gitlab CI/CD 與 GCP - 防火牆設定

前言

請參考前篇
我們已經建立兩台 VM,
本篇將介紹 Firewall 的相關設定,
架構如下
GCP 與 Gitlab

情境

為了建立我們的 QA 測試環境,我們需要在 Google Cloud Platform (GCP) 上進行一些設定。
由於 QA 環境只能允許公司內部網路的存取,但我們又需要使用 Google 登入功能,這就需要綁定真實的 Domain 與對外 IP。
為了確保安全性,我們還需要設定防火牆,只允許經過公司路由的流量進入 QA 環境,以限制訪問權限。
這樣可以確保只有公司內部的流量可以訪問 QA 環境,保證資料的安全。
這個設定可以讓我們擁有一個安全、受控的 QA 環境,並且能夠順利使用 Google 登入功能,提供更好的使用體驗。

實作

登入至 GCP > VPC 網路防火牆設定頁面。在此頁面中,您可以新增防火牆規則。

接著,建立名稱為 “block-all” 的防火牆規則,並將優先級設定為 1000,以阻擋所有流量。
設定來源 IP 範圍為 0.0.0.0/0,並將允許的協定設定為 “deny”,以阻擋所有網路流量。
同時,建立名稱為 “allow-my-company” 的防火牆規則,並將優先級設定為 999,以允許公司內部網路的流量通過。
設定來源 IP 範圍為公司內部網路的 IP 範圍,並設定允許的協定包括 HTTP(80)、HTTPS(443)、SSH(22)和 ICMP,以便允許相應的流量通過。

最後,在創建防火牆規則時,務必勾選 “套用於標籤” 選項,並選擇要套用防火牆規則的 VM 的標籤。
確認防火牆規則的設定與標籤套用正確無誤後,點選 “建立” 來創建防火牆規則。
確保您的 VM 上都已經套用了 “block-all” 和 “allow-my-company” 這兩個防火牆規則的 tag,以確保該 VM 可以通過防火牆規則的設定進行存取。
最後,確認這兩個防火牆規則都已保存並生效,以確保 QA 環境只能通過公司內部網路存取,並且仍然可以使用 Google 登入功能。

建立 GCP 防火牆規則並套用 VM 標籤,確保 QA 環境的存取限制符合公司的需求。

參考

(fin)

[實作筆記] Gitlab CI/CD 與 GCP - 建立 Gitlab Runner VM

前言

請參考前篇,我們將建立兩台 VM,
一台作為 CI/CD 用的 Gitlab Runner,另一台作為 Web Server,
本篇將介紹 Gitlab Runner 的相關設定,
架構如下
GCP 與 Gitlab

建立 VM

建立 GCP VM 步驟如下:

  1. 登入 GCP 控制台並選擇適合的專案。
  2. 在主選單中選擇「Compute Engine」,進入虛擬機器的管理頁面。
  3. 點選「建立」(Create) 按鈕,開始建立新的虛擬機器。
  4. 選擇適合的地區 (Region) 與區域 (Zone),這會決定虛擬機器的物理位置與可用性。
  5. 選擇適合的機器類型 (Machine type) 與規模 (Instance size),這會決定虛擬機器的運算能力與資源配置。
  6. 選擇適合的作業系統映像 (Operating System Image),這會作為虛擬機器的基本作業系統。基本上我都選 Ubantu
  7. 選擇適合的開機磁碟 (Boot disk) 配置與容量,這會作為虛擬機器的主要儲存空間。
  8. 選擇適合的防火牆設定 (Firewall) 與網路 (Network) 設定,這會決定虛擬機器的網路連線與安全性設定。
  9. 完成其他選項設定,例如使用者資料 (User data)、預設密鑰 (SSH Keys)、啟用擴展 (Enable extensibility) 等。
  10. 檢閱與確認虛擬機器的設定,並按下「建立」(Create) 按鈕,開始建立虛擬機器。
  11. 等待 GCP 完成虛擬機器的建立與啟動。
  12. 成功建立虛擬機器後,可以透過 SSH 連線或其他遠端連線方式進入虛擬機器,並進行相關的設定與應用程式部署。

註冊 Group Runner

  1. 安裝 GitLab Runner, 參考 GitLab Runner 官方文件 上的指南進行安裝。

  2. 將該 Runner 註冊到您的 GitLab 項目中。注意 Runner 有 Group/Project/Shared 之分。

  3. 我們選擇 Group Runner, 請安裝 CLI

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 添加 Gitlab Runner 存儲庫的 GPG 金鑰
    $ curl -L https://packages.gitlab.com/gpgkey/gitlab-runner/gpgkey | apt-key add -

    # 添加 Gitlab Runner 存儲庫
    $ curl -L https://packages.gitlab.com/runner/gitlab-runner/ubuntu/$(lsb_release -cs)/

    # 更新 apt 軟體包索引
    $ apt-get update

    # 安裝 Gitlab Runner
    $ apt-get install gitlab-runner
  4. 執行註冊

1
2
# 註冊 Gitlab Runner,請按照提示輸入 Gitlab 的 URL 和 Runner 的註冊 token
$ gitlab-runner register

您可以在 GitLab 網站的項目設定中找到 Runner 註冊的相關資訊,並按照指南進行註冊。
下面是 2023 年的實作記錄,如果你有遇到任何狀況,再查閱 Gitlab 相關文件.

註: 需注意 Gitlab 的官方文章指出,未來將計劃棄用 Gitlab Register Token 的方式

The new registration process is expected to become available in %16.0,
and the legacy registration process will be available side-by-side
for a few milestones before the being sunset through a feature flag.
Removal is planned for %17.0.

參考

首先,你必須是 Group Owner。
接下來在 Group > CI/CD > Register a group runner > Registration token > 👁️ 取得 Token
執行 gitlab-runner register, 依提示輸入

  • url 這是指 gitlab 的 服務網址,如果你不是自已架設的 gitlab server 請輸入 “https://gitlab.com/
  • registration-token 這是在前面步驟取得的 token ,但這個作法預計在 Gitlab 17 版被棄用需注意
  • executor 請輸入 “docker” , 更多資訊請參考

其它參數請參考
執行命令後,應該可以在 Group > CI/CD > Runner 看到它,記得要啟動才會開始作業

建立 Group Variable

我們現在完成了 Gitlab-Runner,如果你也完成了你的服務伺服器設定,回頭看一下架構圖,
可以注意到,我們會透過 docker container 執行我們的 CI/CD 工作,
並且存取 GCP 的資源,在我們的例子中是使用 VM ,讓我們先忽略防火牆與使用者帳號的相關設定,
單純的連線機器實體,我會採用 SSH 的連線方式。

在一般的情況,我們會在 Client 端機器上生成 Private Key 與 Public Key,並且將 Public Key 放到 Server 端(服務伺服器)上,
不過在使用 docker container 的情況下,我們的 Client 端可以想像成是一個拋棄式的機器,
每次都建立新的 Private/Public Key 會讓 Server 端記錄著一大堆沒有用的 Public Key,
所以我們先建立好一組 Key,然後透過 Gitlab Variable 的機制傳遞到 Docker Container。

設定

  • 在群組中,前往「Settings > CI/CD」。
  • 選擇「Add variable」並填入相關資訊:
    • Key:必須是單行文字,不能包含空格,只能使用字母、數字或底線。
    • Value:無限制。
    • Type:變數類型,預設為「Variable」,也可以選擇「File」。
    • Environment scope:可選,可以選擇套用到全部環境 (All) 或特定環境。
    • Protect variable:可選,如果選中,該變數只會在運行於受保護的分支或標籤的流程中使用。
    • Mask variable:可選,如果選中,該變數的值將在作業日誌中被遮蔽。如果變數的值不符合遮蔽要求,則無法保存。

在此例中我,我用「File」儲存 Private Key。
未來可能會再評估一下資安風險。

參考

[實作筆記] Gitlab CI/CD 與 GCP - 建立 Web Server VM

前言

請參考前篇,我們將建立兩台 VM,
一台作為 CI/CD 用的 Gitlab Runner,另一台作為 Web Server,
本篇將介紹 Web Server 的相關設定,
架構如下
GCP 與 Gitlab

建立 VM

建立 GCP VM 步驟如下:

  1. 登入 GCP 控制台並選擇適合的專案。
  2. 在主選單中選擇「Compute Engine」,進入虛擬機器的管理頁面。
  3. 點選「建立」(Create) 按鈕,開始建立新的虛擬機器。
  4. 選擇適合的地區 (Region) 與區域 (Zone),這會決定虛擬機器的物理位置與可用性。
  5. 選擇適合的機器類型 (Machine type) 與規模 (Instance size),這會決定虛擬機器的運算能力與資源配置。
  6. 選擇適合的作業系統映像 (Operating System Image),這會作為虛擬機器的基本作業系統。基本上我都選 Ubantu
  7. 選擇適合的開機磁碟 (Boot disk) 配置與容量,這會作為虛擬機器的主要儲存空間。
  8. 選擇適合的防火牆設定 (Firewall) 與網路 (Network) 設定,這會決定虛擬機器的網路連線與安全性設定。
  9. 完成其他選項設定,例如使用者資料 (User data)、預設密鑰 (SSH Keys)、啟用擴展 (Enable extensibility) 等。
  10. 檢閱與確認虛擬機器的設定,並按下「建立」(Create) 按鈕,開始建立虛擬機器。
  11. 等待 GCP 完成虛擬機器的建立與啟動。
  12. 成功建立虛擬機器後,可以透過 SSH 連線或其他遠端連線方式進入虛擬機器,並進行相關的設定與應用程式部署。

Web Server

Web Server 我們建置得很簡單,
使用 Vue 建立的靜態網站,並且由 Nginx 來 host 它

  • 安裝 Nginx
1
2
sudo apt update
sudo apt install nginx

設定 Nginx:預設的 Nginx 設定檔通常位於 /etc/nginx/nginx.conf.。
可以編輯此設定檔,設定 Nginx 如何處理 Vue 的靜態檔案。
以下是一個範例設定檔:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {
listen 80;
server_name example.com; # 替換為你的網域名稱

root /www/example_output; # Vue 建置的靜態檔在 .output/public 之中

location / {
try_files $uri $uri/ /index.html; # 使用 Vue 的路由模式,將所有請求都導向 index.html
}
}

server {
listen 443 ssl;
server_name example.com;
root /www/example_output;
index index.html;

ssl_certificate /etc/letsencrypt/live/example.com/full_chain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/private_key.pem;

location /www/example_output {
index index.html;
}
}

在建立測試環境的 Web Server 時,需設定 public IP 以對外提供服務,
但同時需要建立防火牆以保障安全性。其他如 DNS、憑證、防火牆等設定,之後再補充。

建立 Vue 專案

將 Vue 應用程式編譯成靜態檔案:在 Vue 應用程式的專案目錄中,可以使用以下命令編譯 Vue 應用程式成靜態檔案:

1
npm run generate

編譯完成後,靜態檔案會生成在 ./output 目錄下。

將編譯完成的靜態檔案放置到 Nginx 的目錄,
重新啟動 Nginx 即完成部署,如果有設定 Hot Reload 則不需要重新啟動
現在可以透過瀏覽器來測試 Vue 的靜態網站是否正常運作。

Tips

重啟 nginx

1
systemctl restart nginx

Nginx hot reload

1
nginx -s start

參考

(fin)

[實作筆記] Gitlab CI/CD 與 GCP - 架構全貌

前言

在一個團隊合作開發的場景中,多個開發人員可能同時對同一個程式碼庫進行更改,
而 CI/CD 可以自動進行建置、測試和部署,以確保程式碼的品質和穩定性。
此外,CI/CD 還可以幫助提高交付速度,減少錯誤,並支持快速反饋和迭代開發。

在這個背景下,選擇 GitLab CI/CD 與 Google Cloud Platform(GCP)作為 CI/CD 解決方案有幾個優點。
首先,GitLab CI/CD 提供了完整的 CI/CD 功能,包括強大的持續整合和持續部署工具,能夠無縫集成到 GitLab 的版本控制平台中,
方便團隊進行版本控制、自動建置和測試,並實現自動化的程式碼部署。
其次,GCP 是一個廣泛使用的雲端平台,提供了豐富的計算、儲存、網路和資料庫等服務,
方便團隊在雲端環境中進行應用程式部署和運行,並且與 GitLab CI/CD 有良好的整合性,可以輕鬆設定和管理 CI/CD 流程。

替代方案:若不選擇 GitLab CI/CD 與 GCP,團隊可能需要考慮其他 CI/CD 工具和雲端平台的組合。
例如,替代 GitLab 的版本控制工具可以是 GitHub、Bitbucket 等;替代 GCP 的雲端平台可以是 AWS、Azure 等。

架構

在我們的架構之中,我們使用 Docker 作為 GitLab Runner 的執行環境,
並在 GCP 上使用虛擬機器(VM)作為運行應用程式(web server)部署環境。
透過 GitLab Runner 和 Docker,我們能夠自動執行 CI/CD 任務,
並根據需要動態調整運行環境,確保我們的應用程式在開發和部署過程中保持高品質和穩定性。
如下圖。

GCP 與 Gitlab

步驟

接下來我將進行以下動作:

  • 在 GCP 上建立兩個虛擬機器(VM),一個作為我們的 Web Server,另一個作為 GitLab Runner。
  • 將 GitLab Runner VM 註冊為 GitLab Group runner,以便進行自動化的建置和部署。
  • 設定適當的防火牆規則,讓 Gitlab Runner 可以存取 Web Server
  • 讓 GitLab Runner VM 的 Docker 容器可以存取我們的 Web Server,我會設定相應的公鑰和私鑰,以確保安全的連線。
  • 我會撰寫一個適合的 gitlab-ci.yml 檔案,來定義建置和部署的流程,並將其配置在 GitLab CI/CD 中,以實現自動化的流程。
  • 最後,我會在 Web Server 上設定好使用者、群組與 Nginx 的 Hot reload。

以上的步驟將協助我們建立基於 Gitlab 與 GCP 的 CI/CD 流程,並以此提供程式開發的品質和穩定性。

參考

(fin)

[翻譯] TypeScript 寫給 C#/Java 工程師

前言

工作上有開發前端專案的需求,主流使用 JavaScript。
而聽說了一些強型別語言的優點,加上我有開發 C# 的經驗,我常常改用 TypeScript,
但實際上確常常覺得反而更笨重了,覺得開發上不太順暢。

一個是 node_module 的問題

相依性的管理十分麻煩,常常有新版的模組更新,但其相依的模組卻尚未更新。
運氣好等幾周就會有更新,運氣不好是模組的開發者已經不在維護,目前我的處理方式是使用 ncu ,
但也有其極限,而在其上花費的大量時間,反而拖累開發的速度。

TypeScript

另一個麻煩的點是使用 TypeScript ,雖然我有 C# 的經驗,也熟悉 JavaScript,
但是常常覺得開發仍然不順,直到閱讀官方的這篇文章,才稍解一些疑惑。
並稍作記錄如下。

翻譯

本文出處為TypeScript for Java/C# Programmers
我不會逐字翻譯,只針對我認為重要的觀念作筆記。

Class 的反思

在 C#/Java Class 是程式的基本單位,這類的程式語言我們稱之為 mandatory OOP
而在 TypeScript/JavaScript 當中 Function 才是程式語言的基本單位。
Function 可以自由的存在,而不需要寄生在 Class 之中。
這帶來了靈活性的優點,在思考 TypeScript 時,應以此作為考量。
因此,C#和 Java 的某些結構,如 Singleton 和 Static Class 在 TypeScript 中是不必要的。

Type 的反思

Nominal Reified Type Systems vs Structural System
C#/Java 使用 Nominal Reified Type Systems ,
這表示 C#/Java 程式中所使用的值或物件,一定會是 null 或基本型別(int、string、boolean 等…)或具體的 Class。
而在 TypeScript 中,類別只是個集合。
你可以這樣描述一個值同時可能是 string 或 number

1
2
3
let stringNumber: string | number;
stringNumber = 1;
stringNumber = "123";

同時在作型別的推導的時候, C#/Java 會有具體的型別,而 TypeScript 會使用結構作推導,
參考下面的例子,我們沒有給 obj 具體的型別,但是在結構上符合 Pointlike 與 Named 所擁有的屬性,
使得呼叫方法時的型別推導在 TypeScript 是合法的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
interface Pointlike {
x: number;
y: number;
}
interface Named {
name: string;
}

function logPoint(point: Pointlike) {
console.log("x = " + point.x + ", y = " + point.y);
}

function logName(x: Named) {
console.log("Hello, " + x.name);
}

const obj = {
x: 0,
y: 0,
name: "Origin",
};

logPoint(obj);
logName(obj);

這樣的設計在 runtime 的時候,我們無法具體的知道型別是什麼,
下面的概念在 TypeScript 將不可行,
即使用 JavaScript 的 typeof 或 instanceof 你也只會拿到 “object”,而非具體的型別

1
2
3
4
// C#
static void LogType<T>() {
Console.WriteLine(typeof(T).Name);
}

即使如此,這樣的設計在編譯時期的檢查在實務上是足夠的,
另外兩個例子與長時間開發 C#/Java 的概念上可能會有所不同,

Empty Type

Typescript 允許設計無屬性的 Type,而基於 Structural System
你可以建立一個方法傳遞任何物件進去(而不是用 any 或 object 去定義傳入值)

1
2
3
4
5
6
7
8
class Empty {}

function fn(arg: Empty) {
// do something?
}

// No error, but this isn't an 'Empty' ?
fn({ k: 10 });

Identical Types

下面的程式不會發生錯誤,但是可能會讓 C#/Java 的開發者有點意外

1
2
3
4
5
6
7
8
9
10
11
12
class Car {
drive() {
// hit the gas
}
}
class Golfer {
drive() {
// hit the ball far
}
}
// No error?
let w: Car = new Golfer();

一樣基於 Structural System 的設計,有相同的屬性與方法簽章的兩個不同物件,
是允許這樣子的行為,而以官方的看法來說,實務上並不太容易發生這種情形(兩個不同的模型,卻有相同的方法、屬性等…)。

小結

以下是 C#/Java 與 TypeScript 的相同和不同之處:

相同之處:

  • C#/Java 和 TypeScript 都是物件導向編程語言。
  • C#/Java 和 TypeScript 都使用類(class)和物件(object)的概念。
  • C#/Java 和 TypeScript 都有靜態類型系統。

不同之處:

  • C#/Java 的類型系統基於類型聲明,而 TypeScript 的類型系統基於屬性的兼容性。
  • C#/Java 的類型在 runtime 是存在的,而 TypeScript 的類型在 runtime 時是不存在的。
  • C#/Java 類型之間的關係通過繼承關係或共同實現的接口來定義。而在 TypeScript 中,類型之間的關係是通過屬性的兼容性來定義。

心得

If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.

TypeScript 的類型設計讓我想起了鴨子測試,也讓我想起 golang 對 interface 的處理方式。
甚至想起一些對物種起源的探討,先有分類還是先有特性呢 ? 真實的世界分類反而是人類主觀強加上去的。
TypeScript 這樣的設計似乎比起強制性的類別設計(C#/Java),更貼近真實的世界。

參考

(fin)

[實作筆記] 不要用 Homebrew 安裝 nvm

前言

在開發 Node.js 應用程式時,我們可能需要在不同的 Node.js 版本之間進行切換。
在這種情況下,一個方便的解決方法是使用 Node Version Manager(nvm)。
而 Homebrew 則是一個流行的 macOS 套件管理工具。
在這篇文章中,我們將探討為什麼官方不建議使用 homebrew 安裝 nvm。

情況

首先,值得注意的是,nvm 官方文件明確表示不建議使用 Homebrew 安裝 nvm。
主要是因為 Homebrew 的安裝方式可能會干擾 nvm 的運作,導致一些奇怪的問題。
nvm 官方建議使用其提供的安裝方式,以確保 nvm 能夠正常運作。

那麼,標準的 nvm 安裝方式是什麼呢?
您可以在 nvm 的 GitHub 頁面上找到完整的安裝指南,這裡不再贅述。
簡而言之,您需要在終端機中運行一個安裝腳本,該腳本將安裝 nvm,並更新您的 shell 啟動腳本以使其能夠正常運行。

如果您仍然希望使用 Homebrew 安裝 nvm,可以參考一些額外的資源。
這裡有一篇詳細的文章,介紹了如何使用 Homebrew 安裝並配置 nvm。
不過,需要注意的是,這種方法仍然不是官方建議的方式。

實作

不管您選擇哪種方式安裝 nvm,一旦完成後,您需要在終端機中設置 nvm 的環境變數才能正常運行。
如果您希望在不關閉終端機窗口的情況下讓變數生效,可以使用以下命令:

1
source ~/.bashrc

如果您使用的是 zsh,則需要使用以下命令:

1
source ~/.zshrc

這將重新載入您的 shell 啟動檔案,使 nvm 環境變數生效。

參考:

(fin)

[AI 共筆] macOS Monterey 5000 Port 佔用原因與解方

前言

在 macOS Monterey 上如何處理開發伺服器使用端口被佔用的問題,
若使用其他 macOS 版本,請查看相關頁面。

問題

更新到最新的 macOS 作業系統時,發現我的前端網站,
顯示類似於「Port 5000 already in use」的訊息。

透過執行

1
lsof -i :5000

發現正在佔用該端口的進程名稱為 ControlCenter,這是一個原生的 macOS 應用程式。
即使你使用強制終止它,它還是會自動重新啟動。

處理方式

原來使用該端口的進程是 AirPlay 伺服器,
你可以在「系統偏好設定」 >「共享」中取消勾選「AirPlay Receiver」以釋放 5000 端口。

小結

網路大多的中文解法是關閉”隔空播放接收器”,在新版的 OS 找不到,可能是語言差異。
所幸找到英文的解法,順利停止佔用 port 的服務。

參考

(fin)

[AI 共筆] 自動重新加載 Node 專案工具比較

前言

在開發Node.js應用程序時,開發人員通常需要經常重新啟動應用程序來看到他們所做的更改。
這真的很煩,因為每次修改都需要重新啟動應用程序。
為了解決這個問題,開發人員可以使用許多自動重新加載工具,
例如 nodemon 和 pm2。

比較

首先,讓我們來比較 nodemon 和 pm2 自動重新加載功能。

nodemon

一個簡單易用的自動重新加載工具,可以在幾分鐘內完成安裝和設置。
它會監聽文件的更改,並在發現更改時自動重新加載應用程序。
此外,它還可以在命令行中顯示有用的日誌信息,例如錯誤和堆棧跟踪。
但是 nodemon 需要不斷監聽文件系統的更改,因此它會帶來一些性能開銷。
此外,它也不能用於在分佈式系統中部署 Node.js 應用程序。

pm2

pm2 是另一種自動重新加載工具,具有進程管理功能,例如重啟和停止應用程序,監聽應用程序的日誌等等。
它可以輕鬆地在分佈式系統中部署 Node.js 應用程序,並可以與其他 pm2 命令進行集成,
例如性能監測和自動縮放。 然而,相對於 nodemon,pm2 更為複雜,需要更多的配置和設置。
此外,某些 pm2 命令可能會影響系統的性能,例如性能監測和自動縮放。

小結

在開發 Node.js 應用程序時,自動重新加載工具是非常重要的。
如果開發人員只需要簡單的自動重新加載功能,並且不需要在分佈式系統中部署應用程序,
那麼 nodemon 是一個不錯的選擇。
如果需要進程管理功能和在分佈式系統中部署Node.js應用程序,
那麼 pm2 是一個更好的選擇。

參考

(fin)

[AI 共筆] tsconfig 中的 tsx 設定

前言

本篇是 AI Knows 的第一篇,ChatGPT 問世後,
在學習開發上,我認為又到了一個新的領域,
很多人開始作分享對 ChatGPT 的看法,在我看來還是社群時代的蹭流量作法。
更進一步的有人開始透過 AI 實作商業應用,商人果然是跑最快的。
另外一種,用嘴涮夢、涮 AI,開始賣書賣課的,我認為接近灰色地帶,就不予置評了。

問題

我正在替專案配置 EsLint 文件,過程當然直接請 AI 代勞,
但是有一些設置我不那麼清楚也懶得查文件。
就一樣也請教 AI 囉。

對話記錄

Q:tsconfig.json 中的 jsx 屬性為何?**

jsx 屬性是用來指定 TypeScript 如何處理 JSX 語法的選項。
JSX 是一種 JavaScript 語法擴展,允許在 JavaScript 代碼中直接使用
HTML 標籤來描述 UI 組件,使得開發 Web 應用程式更為方便。

在 tsconfig.json 中,jsx 屬性可以設置為以下值:

“react”:表示使用 React 的 JSX 語法。
“preserve”:表示將 JSX 語法保留為原始的 JSX 代碼。
“react-native”:表示使用 React Native 的 JSX 語法。
當設置為 “react” 時,TypeScript 會將 JSX 轉換為對應的 JavaScript 代碼,
這樣就可以在瀏覽器中運行。而當設置為 “preserve” 時,TypeScript 不會對
JSX 進行任何轉換,而是將其保留為原始的 JSX 代碼。

Q:為什麼我看到的設定是 “jsx”:”react-jsx”

在 TypeScript 4.1 之前,jsx 選項僅有兩個可選值,分別是 preserve 與 react。
其中 preserve 會保留 JSX 並將其轉換為對應的 React.createElement 函式,
而 react 則是直接轉換為對應的 JavaScript 代碼。

在 TypeScript 4.1 中,又新增了一個選項 react-jsx,用來代表 TypeScript
將會使用 @babel/plugin-transform-react-jsx 進行轉換,以此來與 Babel 兼容。

因此,如果你的 TypeScript 版本較新,通常會看到的 jsx 設定是 “jsx”: “react-jsx”,
表示 TypeScript 將會與 Babel 兼容。

小結

綜合以上問答,我們可以得知 JSX 是一種 JavaScript 語法擴展,讓開發 Web 應用程式更加方便,
而 tsconfig.json 中的 jsx 屬性用來指定 TypeScript 如何處理 JSX 語法的選項,
可以設置為 react、preserve 或 react-native 三種值,分別代表將 JSX 轉換為對應的 JavaScript 代碼、保留原始的 JSX 代碼或使用 React Native 的 JSX 語法。

而在 TypeScript 4.1 中,新增了 react-jsx 選項,用來與 Babel 兼容。
因此,如果 TypeScript 版本較新,通常會看到的 jsx 設定是 “jsx”: “react-jsx”。

寫在最後

通篇八成為 AI 牙慧,正確性未考究。

(fin)

Please enable JavaScript to view the LikeCoin. :P