﻿# 如何用 Angular CLI 與 .NET CLI 快速建立 Monorepo 專案

我們漸漸在不同專案中嘗試 [Monorepo](https://medium.com/hannah-lin/%E7%82%BA%E4%BB%80%E9%BA%BC%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E8%B6%8A%E4%BE%86%E8%B6%8A%E6%84%9B%E4%BD%BF%E7%94%A8-monorepo-%E6%9E%B6%E6%A7%8B-661afa90910a) 架構，讓前後端分離的專案中可以共用同一個 Repo 來進行專案開發與管理。今天這篇文章我就簡單分享如何利用 Angular CLI 與 .NET CLI 來快速打造一個 Monorepo 的專案。

![taiwan-skyline-beautiful-cityscape-sunset](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/4b1b5834b004032820d8-230425876-ac30835f-dc47-4485-ae87-1e2dab333f6c.jpg)

### 專案架構說明

我們的專案架構大概是這樣的：

1.  一個前台(Angular)、一個後台(API)
2.  前台有自己的前端與後端專案
3.  後台有自己的前端與後端專案

簡單來說，我們有四個專案，希望擺在同一個 Repo 底下。不過，我們此案只有規劃兩位開發者，一位負責做後端開發，一位負責做前端開發，所以我規劃第一層資料夾直接用「開發人員角色」來命名，其 PowerShell 命令如下：

```powershell
# 建立專案資料夾
mkdir G:\MYPROJ

# 進入專案資料夾
cd G:\MYPROJ

# 建立專案所需的 README.md 說明檔
echo '# MYPROJ' | Out-File -Encoding utf8 README.md

# 建立前後台所需目錄
mkdir backend
mkdir frontend
```

其目錄架構如下：

```
G:\MYPROJ
│   README.md
├───backend
└───frontend
```

先建立初始化版本控管：

```powershell
git init
git add .
git commit -m "Initial commit"
```

### 後端架構建立

首先，我們先建立後端架構，目前我們規劃會有 1 個「方案」且有 3 個「專案」，而透過 .NET CLI 建立專案的順序如下：

```powershell
# 進入 backend 資料夾
cd backend

# 建立 MYPROJ.API 方案檔 (MYPROJ.API.sln)
dotnet new sln -n MYPROJ.API

# 建立一個類別庫專案
dotnet new classlib -n MYPROJ.Data
dotnet sln MYPROJ.API.sln add .\MYPROJ.Data\MYPROJ.Data.csproj

# 建立前台的 ASP.NET Core Web API 專案
dotnet new webapi -n MYPROJ.API
dotnet sln MYPROJ.API.sln add .\MYPROJ.API\MYPROJ.API.csproj

# 建立後台的 ASP.NET Core Web API 專案
dotnet new webapi -n MYPROJ.API.Backend
dotnet sln MYPROJ.API.sln add .\MYPROJ.API.Backend\MYPROJ.API.Backend.csproj

# 建立 .gitignore 檔案 (預設用 VisualStudio 範本)
dotnet new gitignore

# 回到根目錄
cd ..
```

最終的目錄結構如下：

```
G:\MYPROJ\BACKEND
│   .gitignore
│   MYPROJ.API.sln
│
├───MYPROJ.API
│   │   appsettings.Development.json
│   │   appsettings.json
│   │   Program.cs
│   │   MYPROJ.API.csproj
│   │   WeatherForecast.cs
│   │
│   ├───Controllers
│   │       WeatherForecastController.cs
│   │
│   └───Properties
│           launchSettings.json
│
├───MYPROJ.API.Backend
│   │   appsettings.Development.json
│   │   appsettings.json
│   │   Program.cs
│   │   MYPROJ.API.Backend.csproj
│   │   WeatherForecast.cs
│   │
│   ├───Controllers
│   │       WeatherForecastController.cs
│   │
│   └───Properties
│           launchSettings.json
│
└───MYPROJ.Data
    │   Class1.cs
    │   MYPROJ.Data.csproj
```

建立後端版控：

```powershell
git add .
git commit -m "Initial commit for backend"
```

### 前端架構建立

接著，我們來建立前端架構，目前我們規劃會有 2 個 Angular 應用程式，一個是後台用，一個是前台用，使用 Angular CLI 建立專案的順序如下：

```powershell
# 建立 workspace 資料夾但不建立應用程式
ng new frontend --create-application=false --skip-git

# 進入 frontend 資料夾
cd frontend

# 建立前台的 Angular 應用程式
ng g application myproj-front --routing --skip-tests --style=css

# 建立後台的 Angular 應用程式
ng g application myproj-back --routing --skip-tests --style=css

# 回到根目錄
cd ..
```

最終的目錄結構如下：

```
G:\MYPROJ\FRONTEND
│   .editorconfig
│   .gitignore
│   angular.json
│   package-lock.json
│   package.json
│   README.md
│   tsconfig.json
│
├───.vscode
│       extensions.json
│       launch.json
│       tasks.json
│
└───projects
    ├───myproj-back
    │   │   tsconfig.app.json
    │   │   tsconfig.spec.json
    │   │
    │   └───src
    │       │   favicon.ico
    │       │   index.html
    │       │   main.ts
    │       │   styles.css
    │       │
    │       ├───app
    │       │       app-routing.module.ts
    │       │       app.component.css
    │       │       app.component.html
    │       │       app.component.ts
    │       │       app.module.ts
    │       │
    │       └───assets
    │               .gitkeep
    │
    └───myproj-front
        │   tsconfig.app.json
        │   tsconfig.spec.json
        │
        └───src
            │   favicon.ico
            │   index.html
            │   main.ts
            │   styles.css
            │
            ├───app
            │       app-routing.module.ts
            │       app.component.css
            │       app.component.html
            │       app.component.ts
            │       app.module.ts
            │
            └───assets
                    .gitkeep
```

建立前端版控：

```powershell
git add .
git commit -m "Initial commit for frontend"
```

### 總結

這篇文章主要介紹如何透過 CLI 工具快速的建立一個 Monorepo 專案架構，然而真實的專案還是要陸續微調到「實用」的狀態，以下我補充說明幾個可以調整的地方。

-   後端架構微調
    
    -   將用不到的預設檔案移除
        
        例如: `WeatherForecast.cs`, `WeatherForecastController.cs`, `Class1.cs`, ... 等等。
        
    -   微調 `Properties/launchSettings.json` 的設定
        
        相關文章: [認識 ASP.NET Core 7.0 的啟動設定檔 (Launch Profile)](/post/2023/03/03/Understanding-ASP-NET-Core-7-Launch-Profile)
        
    -   新增 SSDL 的 Database Project 對資料庫進行版控
        
-   前端架構微調
    
    -   調整 `.vscode/extensions.json` 內容，將常用的擴充套件加入
        
        建議調整如下，唯一真心推薦安裝 [Angular Extension Pack](https://marketplace.visualstudio.com/items?itemName=doggy8088.angular-extension-pack) 擴充套件包：
        
        ```json
        {
          // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
          "recommendations": [
            "doggy8088.angular-extension-pack",
            "esbenp.prettier-vscode"
          ]
        }
        ```
        
    -   在 `angular.json` 定義 `proxy.conf.json` 的路徑，設定前端的 Proxy 到後端 API
        
        相關文章: [如何在 Angular CLI 建立 proxy.config.json 轉發呼叫遠端 RESTful APIs](/post/2017/02/05/Setup-proxy-to-backend-in-Angular-CLI)
        
    -   多採用 [獨立元件](https://angular.tw/guide/standalone-components) 架構來開發
        
        ```powershell
        # 進入前台的前端 Angular 應用程式，直接進入應用程式的 src/app 目錄
        cd frontend/projects/myproj-front/src/app
        
        # 在該應用程式建立一個 NewsList 獨立元件頁面
        ng generate component NewsList --standalone
        ```
        
-   部署環境整合 (CI/CD)
    
    -   後端部署指定目標路徑與 IIS 所需的 web.config 檔案
        
        相關文章: [如何透過 dotnet publish 調整 ASP․NET Core 部署到 IIS 的 Web.config 內容](/post/2023/03/30/How-to-set-environment-name-for-webconfig-when-run-dotnet-publish)
        
        ```powershell
        dotnet publish -c Release -p:IsTransformWebConfigDisabled=false -p:EnvironmentName=Production -o G:\MYPROJ.API
        ```
        
    -   前端部署時設定與後端相符合的目標路徑
        
        直接將 Angular 建置結果輸出到 ASP.NET Core 的 `wwwroot` 目錄下
        
        ```powershell
        ng build myproj-front --configuration=production --output-path=G:\MYPROJ.API\wwwroot
        ```
        

### 相關連結

-   Monorepo
    -   [如何在 Monorepo 透過 Git 的 Sparse Checkout 取得部分 Repo 內容](/post/2022/05/17/Down-size-your-Monorepo-with-Git-Sparse-checkouts)
    -   [為什麼前端工程越來越愛使用 Monorepo 架構. Using single git repository to manage…| Hannah Lin | Medium](https://medium.com/hannah-lin/%E7%82%BA%E4%BB%80%E9%BA%BC%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E8%B6%8A%E4%BE%86%E8%B6%8A%E6%84%9B%E4%BD%BF%E7%94%A8-monorepo-%E6%9E%B6%E6%A7%8B-661afa90910a)
    -   [monorepo 之我見](https://blog.errorbaker.tw/posts/cwc329/monorepo/)
    -   [Monorepo Explained](https://monorepo.tools/)
-   .NET
    -   [.NET CLI | Microsoft Learn](https://learn.microsoft.com/zh-tw/dotnet/core/tools/?WT.mc_id=DT-MVP-4015686)
-   Angular
    -   [Angular - CLI Overview and Command Reference](https://angular.io/cli)
    -   [獨立元件入門](https://angular.tw/guide/standalone-components)
        -   [Getting started with standalone components](https://angular.io/guide/standalone-components)
