☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
前端基礎 中級

📦 前端工具鏈與框架概覽

📌 什麼是前端工具鏈?

比喻:前端工具鏈就像工廠的生產線 🏭

想像你要大量生產家具(網頁應用程式),不可能全部手工打造。 你需要一條生產線:原料進貨系統(npm)、加工機台(Bundler)、 品質檢測站(Linter/TypeScript)、包裝出貨(Build)。 前端工具鏈就是這整條生產線,讓開發更有效率。


📌 npm / Node.js 基礎

# Node.js 是 JavaScript 的執行環境,npm 是套件管理工具
# 就像 C# 的 NuGet,npm 讓你下載和管理第三方套件

# 初始化專案(建立 package.json)
npm init -y # -y 表示全部使用預設值,快速建立

# 安裝套件
npm install axios # 安裝 axios 套件(HTTP 請求工具),加到 dependencies
npm install -D typescript # 安裝 TypeScript,加到 devDependencies(-D 是開發時依賴)

# package.json 的重要欄位
# {
#   "name": "my-app",           // 專案名稱
#   "version": "1.0.0",         // 版本號
#   "scripts": {                 // 自訂指令(像是 Makefile)
#     "dev": "vite",            // npm run dev → 啟動開發伺服器
#     "build": "vite build",    // npm run build → 建置正式版
#     "preview": "vite preview" // npm run preview → 預覽建置結果
#   },
#   "dependencies": {           // 正式環境需要的套件
#     "axios": "^1.6.0"         // ^ 表示允許自動升級次要版本
#   },
#   "devDependencies": {        // 只有開發時需要的套件
#     "typescript": "^5.3.0"    // TypeScript 編譯器
#   }
# }

# 常用 npm 指令
npm install # 根據 package.json 安裝所有依賴(別人拉專案後第一件事)
npm update # 更新所有套件到最新允許的版本
npm run dev # 執行 scripts 裡定義的 dev 指令
npm list --depth=0 # 列出目前安裝的所有頂層套件

📌 Bundler 概念(Webpack vs Vite)

// Bundler 的作用:把多個 JavaScript 檔案打包成少數幾個檔案
// 就像把一堆零件組裝成成品,方便運送(部署)

// === Webpack(老牌,功能完整,設定複雜) ===
// webpack.config.js 範例
module.exports = { // 匯出 Webpack 設定物件
    entry: "./src/index.js", // 進入點:從哪個檔案開始打包
    output: { // 輸出設定
        filename: "bundle.js", // 打包後的檔案名稱
        path: __dirname + "/dist" // 輸出到 dist 資料夾
    },
    module: { // 模組處理規則
        rules: [ // 定義不同檔案類型的處理方式
            {
                test: /\.css$/, // 正則表達式:匹配 .css 檔案
                use: ["style-loader", "css-loader"] // 用這兩個 loader 處理 CSS
            },
            {
                test: /\.js$/, // 匹配 .js 檔案
                exclude: /node_modules/, // 排除 node_modules 資料夾
                use: "babel-loader" // 用 Babel 轉譯新語法為舊瀏覽器能懂的
            }
        ]
    }
};

// === Vite(新一代,快速,設定簡單,推薦新專案使用) ===
// vite.config.js 範例
import { defineConfig } from "vite"; // 引入 Vite 的設定函式

export default defineConfig({ // 匯出 Vite 設定
    server: { // 開發伺服器設定
        port: 3000, // 開發伺服器使用 3000 埠
        proxy: { // 代理設定(解決開發時的 CORS 問題)
            "/api": { // 所有 /api 開頭的請求
                target: "http://localhost:5000", // 轉發到後端伺服器
                changeOrigin: true // 修改請求的 origin 標頭
            }
        }
    },
    build: { // 建置設定
        outDir: "../wwwroot" // 輸出到 ASP.NET Core 的 wwwroot 資料夾
    }
});

// Webpack vs Vite 比較:
// | 特性         | Webpack           | Vite              |
// |-------------|-------------------|-------------------|
// | 開發啟動速度  | 慢(全部打包)      | 快(按需載入)      |
// | 設定複雜度    | 高                | 低                |
// | 生態系       | 成熟豐富          | 快速成長           |
// | 推薦用於     | 大型遺留專案       | 新專案             |

📌 TypeScript 基礎(給 C# 開發者)

// TypeScript 是 JavaScript 的超集,加入了型別系統
// 對 C# 開發者來說,TypeScript 會感覺非常親切!

// === 基本型別(像 C# 的 int, string, bool) ===
let name: string = "小明"; // 字串型別(對應 C# 的 string)
let age: number = 25; // 數字型別(對應 C# 的 int/double)
let isActive: boolean = true; // 布林型別(對應 C# 的 bool)
let items: string[] = ["a", "b"]; // 字串陣列(對應 C# 的 string[])
let tuple: [string, number] = ["小明", 25]; // 元組(對應 C# 的 ValueTuple)

// === 介面(像 C# 的 interface) ===
interface User { // 定義 User 介面(像 C# 的 interface 或 class)
    id: number; // 必要屬性:ID
    name: string; // 必要屬性:名稱
    email?: string; // 可選屬性:信箱(? 表示可省略,像 C# 的 string?)
    readonly createdAt: Date; // 唯讀屬性(像 C# 的 { get; })
}

// 使用介面
const user: User = { // 建立符合 User 介面的物件
    id: 1, // ID
    name: "小明", // 名稱
    createdAt: new Date() // 建立日期
}; // email 是可選的,所以可以省略

// === 泛型(像 C# 的 Generic) ===
interface ApiResponse<T> { // 定義泛型介面(像 C# 的 ApiResponse<T>)
    data: T; // 泛型資料(對應 C# 的 T Data { get; set; })
    success: boolean; // 是否成功
    message: string; // 訊息
}

// 使用泛型
async function fetchApi<T>(url: string): Promise<ApiResponse<T>> { // 泛型函式
    const response = await fetch(url); // 送出請求
    return await response.json() as ApiResponse<T>; // 斷言回傳型別
}

// 呼叫時指定型別
const result = await fetchApi<User[]>("/api/users"); // T 是 User[]
console.log(result.data); // data 的型別是 User[],IDE 會提供自動完成

// === Enum(像 C# 的 enum) ===
enum OrderStatus { // 定義訂單狀態列舉
    Pending = "pending", // 待處理
    Processing = "processing", // 處理中
    Completed = "completed", // 已完成
    Cancelled = "cancelled" // 已取消
}

// 使用 enum
const status: OrderStatus = OrderStatus.Pending; // 指定狀態為待處理

// === 型別別名和聯合型別 ===
type ID = string | number; // 聯合型別:ID 可以是字串或數字
type Theme = "light" | "dark" | "system"; // 字面量型別:只能是這三個值之一

function setTheme(theme: Theme): void { // 參數只接受指定的值
    document.documentElement.dataset.theme = theme; // 設定 HTML 的 data-theme 屬性
}

setTheme("dark"); // 合法
// setTheme("blue"); // 編譯錯誤!"blue" 不在 Theme 型別中

📌 前端框架比較

// === React(Meta 開發,最大生態系) ===
// 特色:虛擬 DOM、JSX 語法、函式組件 + Hooks
// 適合:大型專案、豐富的第三方套件需求

// React 組件範例
function ProductCard({ product }) { // 函式組件,接收 props
    const [count, setCount] = useState(0); // useState Hook 管理狀態

    return ( // JSX 語法:在 JavaScript 中寫 HTML
        <div className="card"> {/* className 取代 HTML 的 class */}
            <h3>{product.name}</h3> {/* 用大括號插入 JavaScript 表達式 */}
            <p>數量:{count}</p> {/* 顯示狀態值 */}
            <button onClick={() => setCount(count + 1)}> {/* 事件處理 */}
                增加
            </button>
        </div>
    );
}

// === Vue(尤雨溪開發,漸進式框架) ===
// 特色:模板語法、響應式系統、Single File Component
// 適合:中小型專案、快速上手

// Vue 組件範例(Composition API)
// <template>
//   <div class="card">
//     <h3>{{ product.name }}</h3>        <!-- 模板語法:用雙大括號插值 -->
//     <p>數量:{{ count }}</p>            <!-- 顯示響應式資料 -->
//     <button @click="count++">增加</button>  <!-- @click 是 v-on:click 的簡寫 -->
//   </div>
// </template>
// <script setup>
// import { ref } from 'vue';            // 引入 ref 建立響應式資料
// const count = ref(0);                  // ref(0) 建立一個響應式的數字
// const product = defineProps(['product']); // 定義從父組件接收的 props
// </script>

// === Angular(Google 開發,企業級框架) ===
// 特色:完整框架(路由、表單、HTTP 全包)、TypeScript 優先、DI 系統
// 適合:大型企業專案、熟悉 C# 的開發者(概念相似)

// === Blazor(Microsoft 開發,用 C# 寫前端) ===
// 特色:使用 C# 和 Razor 語法、可選 WebAssembly 或 Server 模式
// 適合:純 .NET 團隊、不想學 JavaScript 的 C# 開發者

// Blazor 組件範例
// @page "/counter"
// <h3>計數器</h3>
// <p>目前數量:@count</p>                  <!-- Razor 語法:@ 開頭插入 C# -->
// <button @onclick="Increment">增加</button>  <!-- @onclick 綁定 C# 方法 -->
// @code {
//     private int count = 0;                // C# 的私有欄位
//     private void Increment() => count++;  // C# 的方法
// }

// 框架選擇建議:
// | 情境                        | 推薦框架      |
// |----------------------------|-------------|
// | 大型專案 + 大量第三方套件      | React       |
// | 中小型專案 + 快速開發         | Vue         |
// | 企業級 + 完整架構            | Angular     |
// | 純 .NET 團隊               | Blazor      |

📌 CSS 框架

<!-- === Bootstrap(最老牌,元件豐富) === -->
<!-- 用 class 就能快速建立響應式版面 -->
<div class="container"> <!-- container 自動置中和限制寬度 -->
    <div class="row"> <!-- row 建立一列 -->
        <div class="col-md-6"> <!-- col-md-6 在中等螢幕佔一半寬度 -->
            <div class="card"> <!-- card 預設的卡片元件 -->
                <div class="card-body"> <!-- 卡片內容區 -->
                    <h5 class="card-title">標題</h5> <!-- 卡片標題 -->
                    <p class="card-text">內容</p> <!-- 卡片內文 -->
                    <button class="btn btn-primary">按鈕</button> <!-- 主色按鈕 -->
                </div>
            </div>
        </div>
    </div>
</div>

<!-- === Tailwind CSS(Utility-First,近年最流行) === -->
<!-- 用小型工具 class 組合出任何設計 -->
<div class="max-w-sm mx-auto"> <!-- max-w-sm 最大寬度、mx-auto 水平置中 -->
    <div class="bg-white rounded-lg shadow-md p-6"> <!-- 白背景、圓角、陰影、內距 -->
        <h5 class="text-xl font-bold text-gray-800">標題</h5> <!-- 文字大小、粗體、深灰色 -->
        <p class="text-gray-600 mt-2">內容</p> <!-- 較淺灰色、上方間距 -->
        <button class="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"> <!-- 藍色按鈕、hover 變深 -->
            按鈕
        </button>
    </div>
</div>
/* Bootstrap vs Tailwind 比較 */
/* | 特性         | Bootstrap          | Tailwind CSS        | */
/* |-------------|--------------------|--------------------|  */
/* | 學習曲線     | 低(預設元件多)      | 中(需記 class 名)  | */
/* | 客製化       | 有限(覆蓋樣式)      | 極高(從零組合)      | */
/* | 檔案大小     | 較大(整包引入)      | 極小(只打包用到的)   | */
/* | 設計一致性   | 高(統一風格)        | 取決於開發者         | */
/* | 適合         | 快速原型、後台管理    | 客製化設計、現代專案   | */

📌 SPA vs MVC SSR:何時該用哪個?

// SPA(Single Page Application):整個應用是一個 HTML 頁面
// - 前後端完全分離
// - 使用 React/Vue/Angular 等框架
// - 頁面切換不重新載入(Client-Side Routing)
// - 適合:互動性強的應用(管理後台、社群平台、即時通訊)

// MVC SSR(Server-Side Rendering):伺服器產生完整 HTML
// - ASP.NET Core MVC + Razor Views
// - 每次換頁向伺服器請求新的 HTML
// - SEO 友好(搜尋引擎直接讀到完整內容)
// - 適合:內容網站、部落格、電商展示頁

// 混合方案:
// 1. ASP.NET Core MVC + 局部 JavaScript(最簡單)
//    - 大部分用 Razor 渲染,需要互動的地方加 JS

// 2. ASP.NET Core + Blazor Server(純 C# 方案)
//    - 用 SignalR 即時同步 UI,不需要寫 JavaScript

// 3. ASP.NET Core API + SPA 前端(最大彈性)
//    - 後端只提供 API,前端用 React/Vue 開發
//    - 適合前後端分開部署的場景

// 選擇建議:
// | 需求                    | 推薦方案                    |
// |------------------------|---------------------------|
// | SEO 重要 + 少互動       | MVC SSR(Razor Pages)     |
// | 高互動 + 即時更新        | SPA(React/Vue)           |
// | 純 .NET 團隊            | Blazor Server/WASM         |
// | 兩者都要                | Next.js / Nuxt.js(SSR+SPA)|

🤔 我這樣寫為什麼會錯?

❌ 錯誤 1:npm install 後忘記把 node_modules 加入 .gitignore

# 錯誤:把 node_modules 推上 Git,倉庫暴增數百 MB
git add . # 這會把 node_modules 裡的數萬個檔案全部加入
git commit -m "加入專案" # 推上去後別人 clone 要等很久

# 正確:在專案根目錄建立 .gitignore
# .gitignore 內容:
# node_modules/ # 忽略所有下載的套件(別人用 npm install 重新安裝)
# dist/ # 忽略建置輸出(CI/CD 會重新建置)
# .env # 忽略環境變數檔案(包含密鑰等敏感資訊)

❌ 錯誤 2:TypeScript 的型別斷言濫用

// 錯誤:用 as any 跳過所有型別檢查,失去 TypeScript 的意義
const data = response.data as any; // 任何型別都通過,完全沒有型別保護
console.log(data.nonExistentProp.value); // 執行時才會爆炸

// 正確:定義正確的型別
interface Product { // 定義產品介面
    id: number; // ID 是數字
    name: string; // 名稱是字串
    price: number; // 價格是數字
}

const data = response.data as Product; // 斷言為具體型別
console.log(data.name); // IDE 會提供自動完成,打錯字會有警告
// console.log(data.nonExistentProp); // 編譯錯誤!Property 不存在

❌ 錯誤 3:SPA 沒有處理 404 路由的後端設定

// 錯誤情境:SPA 部署到 IIS 或 Nginx 後,重新整理頁面得到 404

// 原因:SPA 的路由(例如 /products/123)是前端處理的
// 但重新整理時,瀏覽器會向伺服器請求 /products/123
// 伺服器找不到這個實際檔案,就回傳 404

// 解法:在 ASP.NET Core 中設定 Fallback
// Program.cs 中:
// app.UseStaticFiles();   // 先嘗試靜態檔案
// app.MapFallbackToFile("index.html");  // 找不到就回傳 index.html

// 或在 IIS 的 web.config 中:
// <rewrite>
//   <rules>
//     <rule name="SPA" stopProcessing="true">
//       <match url=".*" />
//       <conditions>
//         <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
//       </conditions>
//       <action type="Rewrite" url="/" />
//     </rule>
//   </rules>
// </rewrite>

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊