跳至主要内容

2 篇文章 含有標籤「angular」

檢視所有標籤

將多個 Nx Apps 部署到同一個 Nginx 下

· 閱讀時間約 3 分鐘

Nx monorepo 內通常包含多個前端或後端應用,例如:

apps/
app1/
app2/
app3/

透過 Nx build 後,你會得到:

dist/apps/app1/
dist/apps/app2/
dist/apps/app3/

本篇文章將教你如何把這些 apps 同時部署到同一個 Nginx 下,並使用不同路徑或不同子網域。


方法 A:使用不同路徑(最常見)

例如:

Nginx 設定

server {
listen 80;
server_name example.com;

location /app1/ {
alias /usr/share/nginx/html/app1/;
try_files $uri $uri/ /app1/index.html;
}

location /app2/ {
alias /usr/share/nginx/html/app2/;
try_files $uri $uri/ /app2/index.html;
}
}

Angular / Nx Build 指令

nx build app1 --configuration production --base-href=/app1/
nx build app2 --configuration production --base-href=/app2/

部署的資料夾結構

/usr/share/nginx/html/
app1/
app2/

方法 B:使用不同子網域

例如:

Nginx 設定

server {
server_name app1.example.com;
root /usr/share/nginx/html/app1;
try_files $uri $uri/ /index.html;
}

server {
server_name app2.example.com;
root /usr/share/nginx/html/app2;
try_files $uri $uri/ /index.html;
}

Angular / Nx Build 指令

由於每個 app 直接掛在根目錄(/),baseHref 設為 / 即可:

nx build app1 --configuration production --base-href=/
nx build app2 --configuration production --base-href=/

方法 C:透過 Proxy Pass 導流到後端服務(API / SSR / Node / NodeJS)

如果你的 Nx monorepo 中包含後端服務(例如 NodeJS API),你可以使用 proxy_pass: 讓 Nginx 將 /api 相關請求導向後端 server。

Nginx Proxy Pass 設定範例

server {
listen 80;
server_name example.com;

# 前端 Angular App
location / {
root /usr/share/nginx/html/app1;
try_files $uri $uri/ /index.html;
}

# API Proxy
location /api/ {
proxy_pass http://localhost:3333/; # Nx serve / NodeJS 的 API port
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}

常見 Proxy Pass 場景

  1. Nx + Angular 前端 + NodeJS API

    • / → 前端
    • /api → 後端(NodeJS)
  2. 多後端服務(微服務結構)

    • /auth → Auth service
    • /order → Order service
    • /payment → Payment service

Nx + NodeJS 服務常用指令

nx serve api
nx build api

常見問題(FAQ)

為什麼重新整理會出現 404?

SPA(如 Angular)本身沒有真正的路徑,因此 Nginx 需要設定:

try_files $uri $uri/ /index.html;

這會讓所有路徑回到 Angular 的 router 處理。

Proxy Pass 無法連線?

檢查:

  • 後端 port 是否正確(如 3333
  • 後端是否允許來自 localhost 的 request
  • Nginx 有沒有加 proxy_set_header Host $host
  • 是否需要 HTTPS → HTTP 的 proxy_redirect off;

總結

你可以透過三種方式把多個 Nx apps 與後端部署在同一個 Nginx:

  1. 不同路徑(最常見、單一 domain)
  2. 不同子網域(乾淨、好管理)
  3. Proxy Pass 導後端 API(前後端整合最佳解)

只要正確設定:

  • Nginx alias/root
  • Angular baseHref
  • try_files
  • proxy_pass(如有後端 API)

即可達成完整的 Nx monorepo 部署架構。

Nx App 拆分優勢與策略步驟

· 閱讀時間約 7 分鐘
balnibarbian

1. 背景說明

目前前端專案採用 Nx monorepo,原本僅有單一應用程式 shopping-app,同時承載:

  • 一般使用者(前台)功能
  • 管理者/營運人員(後台)功能

隨著功能擴充與角色複雜度提升,單一 App 逐漸出現以下問題:

  • bundle 體積愈來愈大,首屏載入時間增加
  • 測試與除錯範圍變廣,改一小段功能要驗證很多頁面
  • 權限、導覽、UI 風格混雜在一起,維護成本高
  • 部署策略無法細緻,例如:只想更新後台功能但仍須重建整個 App

為解決上述問題,我們規劃將前端拆分為兩個獨立 App,並保留既有路由邏輯與使用者習慣。


2. 拆成兩個 App 的優勢

2.1 架構與責任分離

拆分後我們會有兩個應用:

  • shopping-app:前台,面向一般使用者
  • backoffice-app:後台,面向管理者/營運人員

優勢:

  • 前後台的路由、版型、權限可以完全分開設計
  • 開發時不會被另一個角色的 UI 汙染
  • 規格討論可以針對各自 App 進行,不互相牽扯

2.2 打包與建置時間優化

在 Nx 下,拆分多個 App 可以搭配:

  • incremental build(增量編譯)
  • affected:* 指令(只建置有受影響的專案)

實際效果:

  • 只修改後台程式碼時,可僅建置 backoffice-app
  • 前台沒有變動就不需重新 build,CI 時間與成本下降
  • 本地開發時可以只啟動自己關心的 App,啟動速度較快

2.3 bundle 大小與載入效能改善

  • 前台不再需要下載後台相關的頁面與元件
  • Admin 專用 UI / library 不會出現在前台 bundle 中
  • Lazy loading 策略可以更乾淨,依 App 設計懸掛不同的 chunk

2.4 權限與安全性清晰化

  • 後台 App 可以在 routing 層、部署層各自設計權限控管
  • 反向代理(nginx / gateway)可針對不同 path/domain 做額外保護
  • 不讓 admin 專用的頁面隨前台一起被發佈

2.5 部署與版本獨立

未來可實現:

  • 前台與後台採用不同的發版節奏
  • 僅更新後台功能時,不動到前台 bundle
  • 甚至可分別部署到不同 domain 或子路徑

3. 拆分核心策略:Clone & Carve

本次拆分採用「Clone & Carve」策略:

先完整複製,再在複製版本中慢慢「削減」成新形狀,而不是直接改原本的 App。

流程概念:

  1. 先複製現有 App → 得到兩份一模一樣的應用
  2. 確保兩個 App 都能正常 serve / build
  3. 在新 App 中逐步刪除不需要的功能頁面
  4. 建立路由/部署分流
  5. 拆完後,再逐步抽出共用的 libs

好處:

  • 原本的 shopping-app 在拆分初期完全不被動到
  • 出現問題可以隨時回退到舊的單一 App
  • 每個步驟都可以單獨測試與驗證

4. 視覺化流程與目錄結構

4.1 流程圖(文字版)

[現有 shopping-app]
|
v
[複製為 backoffice-app]
|
v
[確認兩者可獨立 serve & build]
|
v
[在 backoffice-app 內刪除前台頁面]
|
v
[建立兩者 routing / 部署分流]
|
v
[未來再抽出 shared libs]
|
v
[Build / 部署 / 權限 全面分離]

4.2 目錄結構變更

拆分前:

apps/
shopping-app/
pages/
home
note
article
tag
search
backoffice
admin
transcript

拆分後:

apps/
shopping-app/
pages/
home
note
article
tag
search

backoffice-app/
pages/
backoffice
admin
transcript

未來再視需求抽出 libs:

libs/
shared-model
shared-api
shared-domain
shared-ui
shared-utils

5. 實作步驟(操作手冊)

以下步驟以 Nx + Angular 為例,重點在「最小異動」與「可隨時回退」。

5.1 複製現有 App

  1. 在 repo 根目錄複製:

    cp -R apps/shopping-app apps/backoffice-app
  2. 確認複製後目錄存在:

    apps/
    shopping-app/
    backoffice-app/

此時兩個 App 的內容完全相同。

5.1.1 Nginx Proxy 導流測試(在拆分前先做)

server {
listen 80;
server_name yourdomain.com;

# 前台路由
location / {
proxy_pass http://localhost:4200;
}

# 後台路由
location /backoffice/ {
proxy_pass http://localhost:4300;
}

# 避免 Angular 路由錯誤
location /backoffice {
return 301 /backoffice/;
}
}

說明:

  • 在拆 App 之前,就先建立 nginx proxy 路由
  • nginx 充當反向代理,幫助我們先驗證 path 分流
  • 然後再複製 app 並建立 backoffice-app
[加上 nginx proxy → 建立 / 與 /backoffice 路由分流]
|
v
[確認分流可正常把流量導向不同開發 port]
|
v
[複製 shopping-app → backoffice-app]

5.2 調整 backoffice 專案設定

backoffice-app 底下,調整下列檔案:

  1. project.json

    • 將 name 由 shopping-app 調整為 backoffice-app
    • 確定 sourceRoot 指向 apps/backoffice-app/src
  2. tsconfig.app.json

    • 確認 extendsfilesinclude 等路徑指向 backoffice-app
  3. index.html

    • 修改 <title> 例如:Backoffice Admin

調整完成後,在本機執行:

nx serve shopping-app
nx serve backoffice-app

確認兩個 App 都能啟動且畫面正常,即可進入下一步。

5.3 在 backoffice-app 中刪除前台頁面

目標:在不影響 shopping-app 的前提下,慢慢把 backoffice-app 修剪成「只有後台功能」的應用。

做法:

  1. backoffice-app 中,先確定 routing 結構與檔案位置

  2. 針對明顯前台功能(例如:home, note, article, tag, search),依序:

    • 從 routing 設定中移除該 path
    • 移除頁面元件檔案
    • 移除對應的測試檔、style 等
  3. 每移除一組路由/頁面,都進行一次:

    nx build backoffice-app
    nx serve backoffice-app

    確認:

    • build 無錯誤
    • 主要後台路徑(例如 /backoffice, /admin, /transcript)仍可正常運作

完成後,目錄大致會變成:

apps/
backoffice-app/
pages/
backoffice
admin
transcript

5.4 建立路由與部署分流

在 gateway / nginx / 前端部署設定中,將路由切開,例如:

  • //app → 指向 shopping-app build 出來的 bundle
  • /backoffice/admin → 指向 backoffice-app build 出來的 bundle

如此一來:

  • 使用者造訪前台時,不會載入後台的程式碼
  • 後台可以獨立演進、獨立測試

5.5 拆分完成後的共用程式抽離(後期)

拆分前期不建議直接抽 libs,以免一次改動太大。

當兩個 App 穩定運作後,可以開始評估:

  • 共用的 model / DTO
  • 共用的 API service
  • 共用的 UI components
  • 共用的 util / helper

再逐步抽到 libs/ 底下的 shared 專案中,搭配 Nx 提供的 dependency graph 逐步優化結構。


6. 測試與風險控管

6.1 建議的測試順序

每一個拆分步驟都建議至少做:

  1. 單一 App build 測試:
    nx build shopping-app
    nx build backoffice-app
  2. 本地手動驗證關鍵路由:
    • 前台:主要使用者流程是否正常
    • 後台:登入、查詢、管理功能是否正常
  3. 重要節點時執行 e2e / smoke test

6.2 風險與對應策略

風險類型說明對應策略
build 爆炸一次改太多檔案每次只做小步驟,改完就 build 一次
路由錯亂path 指到錯的 App將前後台 routing 寫在文件與設定中統一管理
共用程式被誤刪後台仍需要前台某段邏輯初期只刪除「明顯純 UI」頁面,不動 domain / service
難以回退多步驟混在同一 commit每個重要步驟分開 commit,必要時可 git revert

7. 結語

本次 Nx App 拆分的目標,不是追求一次到位的「完美架構」,而是:

  1. 在不影響現有使用者的情況下,先把前後台在應用層分離開來
  2. 降低 build 時間與 bundle 大小,改善開發與使用體驗
  3. 為未來的 libs 抽離與獨立部署鋪路

核心心法:

Keep it working → Keep it separated → Keep it evolving

先讓系統穩定分家,再持續演進結構,是目前最務實、風險最低的拆分路線。