# Day 18:前端模組化開發架構思考
**Published by:** [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake/)
**Published on:** 2025-12-15
**URL:** https://paragraph.com/@gcake/day-18
## Content
練習題目模組化重構時,思考 修煉圈圈 這個先前 Vibe Coding 做的小專案可以重構的方式,才發現 js 和 css 內建語法模組概念的不同,記錄一下思考過程。 修煉圈圈開發日誌📚 目錄核心概念JavaScript 模組化CSS 模組化對比分析建置工具開發 vs 生產環境實踐指南核心概念什麼是模組化?模組化 是將大的程式碼拆分成小的、獨立的、可重複使用的單元(模組),每個模組:✅ 職責單一✅ 易於維護✅ 易於測試✅ 可以獨立開發為什麼需要模組化?未模組化程式碼(1000+ 行) ↓ ❌ 難以理解 ❌ 難以維護 ❌ 容易出錯 ❌ 難以分工協作 模組化程式碼(多個 100-200 行檔案) ↓ ✅ 清晰易懂 ✅ 易於維護 ✅ 測試簡單 ✅ 便於團隊協作 模組化的目標開發階段(Developer Experience) ├─ 程式碼清晰易懂 ├─ 容易定位問題 ├─ 方便重複使用 └─ 便於團隊協作 ↓ 建置/合併工具 ↓ 生產環境(Browser Performance) ├─ 減少 HTTP 請求 ├─ 檔案大小最小化 ├─ 瀏覽器快速解析 └─ 性能最優化 JavaScript 模組化原生支援:ES6 ModulesJavaScript 有 原生的模組系統,開發者可以直接使用 import 和 export。基礎語法導出模組(Export)// 方式 1:具名導出 export function add(a, b) { return a + b; } export const PI = 3.14159; export class Calculator { multiply(a, b) { return a * b; } } // 方式 2:預設導出 export default function subtract(a, b) { return a - b; } // 方式 3:混合導出 export function divide(a, b) { return a / b; } export default { add, subtract, divide }; 導入模組(Import)// 導入具名導出 import { add, PI } from './math.js'; // 導入預設導出 import subtract from './math.js'; // 導入所有內容 import * as math from './math.js'; // 混合導入 import subtract, { add, PI } from './math.js'; // 使用 console.log(add(2, 3)); // 5 console.log(PI); // 3.14159 console.log(subtract(5, 2)); // 3 本專案的 JavaScript 模組結構src/ ├─ logic/ # 純業務邏輯模組 │ ├─ calculator.js # 進度計算邏輯 │ ├─ formatter.js # 日期和時間格式化 │ ├─ messages.js # 勵志訊息生成 │ ├─ timer.js # 計時器邏輯 │ └─ date-navigation.js # 日期導航邏輯(純函數) │ ├─ state/ # 狀態管理模組 │ └─ store.js # 集中式狀態儲存 │ ├─ services/ # API 服務模組 │ └─ api.js # 後端通訊 │ ├─ views/ # UI 層模組 │ ├─ dom.js # DOM 元素快取 │ ├─ render.js # 協調層(統一渲染入口) │ └─ components/ # UI 元件模組 │ ├─ day-card-view.js # 日卡片渲染 │ ├─ month-card-view.js # 月檢視渲染 │ ├─ rings-view.js # 進度圈渲染 │ ├─ timer-view.js # 計時器 UI │ ├─ history-view.js # 歷史記錄 UI │ └─ encourage-view.js # 勵志訊息 UI │ └─ constants/ # 常數模組 └─ config.js # 應用配置 導入鏈示例main.js (應用入口) ├─ import * as render from "./src/views/render.js" ├─ import * as timer from "./src/logic/timer.js" ├─ import { getState } from "./src/state/store.js" └─ import * as dateNav from "./src/logic/date-navigation.js" render.js (協調層) ├─ import * as dayCardView from "./components/day-card-view.js" ├─ import * as monthCardView from "./components/month-card-view.js" ├─ import * as ringsView from "./components/rings-view.js" ├─ import * as timerView from "./components/timer-view.js" ├─ import * as historyView from "./components/history-view.js" ├─ import * as encourageView from "./components/encourage-view.js" └─ import { getState } from "../state/store.js" 各元件模組 └─ import 所需的邏輯模組 和 狀態管理 優勢✅ 語言原生支援 - 無需額外工具 ✅ 清晰的依賴關係 - 一眼看出模組間的關係 ✅ 程式碼複用 - 同一函數可多次導入使用 ✅ 易於測試 - 可獨立測試各個模組 ✅ 優雅的語法 - 簡潔易讀CSS 模組化沒有原生支援CSS 沒有原生的模組系統,無法直接使用 @import 模組語法(它只能導入 CSS 檔案)。為什麼 CSS 沒有模組系統?歷史原因 - CSS 創建於 1994 年,當時無模組化概念設計理念 - CSS 是聲明式語言,不適合傳統模組系統演進緩慢 - CSS 標準更新速度遠低於 JavaScriptCSS 模組化的替代方案方案 A:單一檔案 + 清晰註解(推薦用於小型專案)/* style.css */ /* ================================================ */ /* 1. BASE STYLES - 基礎樣式和變數定義 */ /* ================================================ */ :root { --dora-blue: #009eff; --dora-red: #e92024; --dora-white: #ffffff; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Huninn', sans-serif; background-color: var(--dora-bg); } /* ================================================ */ /* 2. TIMER SECTION - 計時器相關樣式 */ /* ================================================ */ .timer-section { /* ... */ } .timer-display { /* ... */ } /* ================================================ */ /* 3. RINGS SECTION - 進度圈相關樣式 */ /* ================================================ */ .rings-section { /* ... */ } .ring-circle { /* ... */ } /* ... 以此類推 */ 優點:✅ 簡單直接✅ 無需額外工具✅ 瀏覽器快速解析(單一檔案)缺點:❌ 檔案越來越大難以維護❌ 無法自動優化方案 B:多檔案 + @import(無建置工具)/* style.css - 主入口檔案 */ @import url('styles/base.css'); @import url('styles/timer.css'); @import url('styles/rings.css'); @import url('styles/history.css'); @import url('styles/modal.css'); @import url('styles/responsive.css'); styles/ ├─ base.css # 變數、Reset、基礎 ├─ timer.css # 計時器相關 ├─ rings.css # 進度圈相關 ├─ history.css # 歷史記錄相關 ├─ modal.css # Modal 相關 └─ responsive.css # 手機版回應式 優點:✅ 模組化程式碼✅ 易於維護✅ 無需建置工具缺點:❌ 多個 HTTP 請求(性能)❌ 需要手動管理依賴方案 C:Sass/SCSS(需要編譯工具)// main.scss @import 'variables.scss'; @import 'base.scss'; @import 'timer.scss'; @import 'rings.scss'; @import 'history.scss'; @import 'responsive.scss'; 功能:✅ 變數、嵌套、混入✅ 自動編譯為 CSS✅ 支援導入其他 SCSS 檔案// variables.scss $primary-color: #009eff; $border-radius: 15px; // timer.scss .timer-section { color: $primary-color; border-radius: $border-radius; } 優點:✅ 高級 CSS 特性✅ 程式碼複用✅ 編譯為最小化 CSS缺點:❌ 需要編譯工具❌ 額外的學習成本方案 D:CSS Modules(需要建置工具如 Webpack)// Button.js import styles from './Button.module.css'; export function Button() { return ; } /* Button.module.css */ .primary { background-color: #009eff; color: white; padding: 10px 20px; } 編譯後會生成唯一的 class 名稱,避免衝突。 優點:✅ 避免樣式衝突✅ 組件級別的樣式作用域✅ 與 JavaScript 框架整合缺點:❌ 需要建置工具❌ 學習框架(React 等)本專案的 CSS 狀態目前:style.css (1003 行) ├─ 1. BASE STYLES ├─ 2. TIMER SECTION ├─ 3. RINGS SECTION ├─ 4. HISTORY SECTION ├─ 5. MODAL / DAY CARD ├─ 6. MONTH VIEW └─ 7. RESPONSIVE 問題: ❌ 檔案過大,難以維護 ❌ 無法自動優化 ✅ 但對於當前規模足夠 對比分析JavaScript vs CSS 模組化面向JavaScriptCSS原生支援✅ ES6 Modules❌ 無原生系統導入語法import { x } from "..."❌ 無模組語法開發方式模組化(import/export)手動組織語言特性函數、類、對象聲明式依賴管理自動追蹤手動管理程式碼複用✅ 容易⚠ 需要工具導入方式對比/* ===== JavaScript ===== */ // 具名導出和導入 export function add(a, b) {} import { add } from './math.js'; // 預設導出和導入 export default subtract; import subtract from './math.js'; // 萬用導入 import * as math from './math.js'; math.add(2, 3); /* ===== CSS ===== */ /* 只能導入 CSS 檔案,無模組概念 */ @import url('base.css'); @import url('timer.css'); /* 結果:所有樣式會疊加到全局作用域 */ /* 無法像 JS 一樣「接收特定導出」 */ 為什麼 CSS 沒有像 JavaScript 那樣的模組系統?建置工具什麼是建置工具?建置工具 是自動化開發流程的軟體,它在開發環境和生產環境之間起橋樑作用:開發環境 (模組化程式碼) ↓ 建置工具 (Webpack/Vite) ↓ 合併 + 壓縮 + 最小化 ↓ 生產環境 (最優化單一檔案) 常見建置工具1. Webpack (最成熟)// webpack.config.js module.exports = { entry: './src/main.js', output: { filename: 'bundle.js', path: __dirname + '/dist', }, module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'], }, ], }, }; 特點:✅ 功能全面✅ 生態龐大❌ 配置複雜❌ 學習曲線陡峭2. Vite (現代推薦)// vite.config.js import { defineConfig } from 'vite' export default defineConfig({ build: { outDir: 'dist', } }) 特點:✅ 配置簡單✅ 開發速度快✅ 現代化設計✅ 預設最優化3. Parcel (零配置)# 無需配置檔案! parcel build index.html 特點:✅ 零配置✅ 自動偵測✅ 速度快建置工具做了什麼?輸入(開發環境) ├─ src/main.js ├─ src/logic/timer.js ├─ src/views/render.js ├─ src/styles/base.css ├─ src/styles/timer.css └─ src/styles/rings.css ↓ 建置工具處理 ↓ 1. 解析 import/export 2. 遞迴收集所有依賴 3. 合併所有 JS 檔案 4. 合併所有 CSS 檔案 5. 壓縮 + 最小化 6. 生成 Source Map(偵錯用) 7. 添加指紋(cache busting) 輸出(生產環境) ├─ dist/bundle.abc123.js (合併+壓縮) ├─ dist/style.def456.css (合併+壓縮) └─ dist/index.html (指向新檔案) CSS 合併工具除了完整的建置工具,還有專門的 CSS 合併工具:PostCSS自動添加瀏覽器前綴壓縮 CSS處理兼容性Sass/SCSS編譯 SCSS 為 CSS自動合併 @importCSS Minifier線上或命令行工具壓縮和合併 CSS開發 vs 生產環境無建置工具的情況開發環境 網路請求: GET /style.css (1003 行) GET /main.js GET /src/state/store.js GET /src/logic/timer.js GET /src/views/render.js ... (多個 HTTP 請求) 優點:易於開發調試 缺點:性能較差 生產環境 - CSS 未壓縮 - JS 未合併 - 文件大小較大 - 多個 HTTP 請求 有建置工具的情況開發環境npm run dev 開發伺服器啟動 ├─ 熱模組更新 (HMR) ├─ 即時編譯 ├─ Source Map(原始碼對應) └─ 快速刷新 開發者寫程式碼時: file: src/logic/timer.js (修改) ↓ 自動編譯 ↓ 瀏覽器自動刷新 ↓ 即時看到改動 (無需手動刷新) 生產環境npm run build 建置流程: 1. 解析依賴 2. 合併模組 3. 程式碼最小化 4. CSS 壓縮 5. 生成指紋版本 輸出結果: dist/ ├─ bundle.a1b2c3d4.js (合併+壓縮,50 KB) ├─ style.e5f6g7h8.css (合併+壓縮,15 KB) ├─ index.html └─ assets/ HTML 自動指向新檔案名: 優點: ✅ 最小化 HTTP 請求(2 個) ✅ 最小化檔案大小 ✅ 瀏覽器快速解析 ✅ 指紋版本便於快取更新 性能對比無建置工具: CSS: 1003 行 → 無壓縮 → ~30 KB JS: 分散在多個檔案 → ~200 KB HTTP 請求: 10+ 個 解析時間: 較長 有建置工具: CSS: 1003 行 → 壓縮 → ~15 KB (-50%) JS: 合併+壓縮 → ~50 KB (-75%) HTTP 請求: 2-3 個 (-80%) 解析時間: 較短 結論:性能提升 3-5 倍! 實踐指南本專案當前狀態評估✅ JavaScript 模組化成熟度:★★★★★ - 使用 ES6 import/export - 清晰的目錄結構 - 邏輯分離完善 ⚠️ CSS 模組化成熟度:★★☆☆☆ - 單一檔案(1003 行) - 有清晰註解分組 - 尚未拆分成多個檔案 ⚠️ 建置工具成熟度:★☆☆☆☆ - 無建置工具 - 無自動優化 - 開發體驗簡單但性能有限 升級路徑第 1 階段:改進 CSS 組織(無工具,立即可做)現在就可以做的:改進 CSS 註解分組使用更清晰的分隔符添加 CSS 變數(已有)整理選擇器順序/* style.css */ /* ================================================= */ /* 1. BASE STYLES */ /* ================================================= */ /* 功能:CSS 變數、Reset、基礎樣式 */ :root { } * { } body { } /* ================================================= */ /* 2. TIMER SECTION */ /* ================================================= */ /* 功能:計時器顯示、按鈕、模式標籤 */ .timer-section { } .timer-display { } /* ... */ 第 2 階段:CSS 檔案分割(可選)如果 CSS 繼續增長:src/styles/ ├─ index.css (主入口,只做 @import) ├─ _variables.css ├─ _base.css ├─ _timer.css ├─ _rings.css ├─ _history.css ├─ _modal.css └─ _responsive.css /* index.css */ @import url('_variables.css'); @import url('_base.css'); @import url('_timer.css'); @import url('_rings.css'); @import url('_history.css'); @import url('_modal.css'); @import url('_responsive.css'); 第 3 階段:引入建置工具(長期規劃)當專案變複雜時考慮:# 初始化 Vite npm create vite@latest . -- --template vanilla # 或 Webpack npm install webpack webpack-cli --save-dev 優點:✅ 自動合併 JS + CSS✅ 自動壓縮最小化✅ 開發時熱更新✅ 性能優化決策樹CSS 超過多少行? │ ├─ < 800 行 → 保持現狀 + 改進註解 │ ├─ 800-1500 行 → 考慮 @import 拆分 │ └─ > 1500 行 → 引入建置工具或 Sass JavaScript 複雜度如何? │ ├─ 低複雜度 → 無需建置工具 │ ├─ 中複雜度 → 可考慮 Vite(簡單配置) │ └─ 高複雜度 → 引入框架 + 建置工具 推薦方案組合小型專案(當前階段)JavaScript: ✅ ES6 Modules (無工具) CSS: ✅ 單一檔案 + 清晰註解 工具: ❌ 無 維護成本: 低 性能: 可接受 中型專案(6-12 個月後)JavaScript: ✅ ES6 Modules CSS: ✅ SCSS 或多檔案 @import 工具: ✅ Vite 維護成本: 中等 性能: 優秀 大型專案(1+ 年後)JavaScript: ✅ ES6 Modules + 框架 (React/Vue) CSS: ✅ CSS Modules 或 CSS-in-JS 工具: ✅ Webpack / Vite + 框架配置 維護成本: 中等 性能: 最優 關鍵知識點總結1⃣ JavaScript 有原生模組系統✅ import/export 語法 ✅ 瀏覽器原生支援(現代瀏覽器) ✅ 清晰的依賴追蹤 ✅ 易於維護和測試 2⃣ CSS 沒有原生模組系統❌ 無 import/export 語法 ❌ 所有樣式應用到全局作用域 ✅ 但有多種替代方案(註解、@import、Sass、CSS Modules) ❌ 需要外部工具進行最佳化 3⃣ 建置工具的作用開發環境:保持模組化(易於理解) ↓ 建置工具:自動合併 + 壓縮 + 最小化 ↓ 生產環境:單一最優化檔案(性能最佳) 4️⃣ 升級時機現在: 專注核心功能開發 未來: 當程式碼複雜度增加時考慮工具 遠期: 引入框架和完整工具鏈 相關資源學習資料MDN - JavaScript ModulesCSS Modules 官方文件Webpack 官方文件Vite 官方文件工具Vite - 現代建置工具Sass - CSS 預處理器PostCSS - CSS 轉換工具Webpack - 成熟的模組打包工具
## Publication Information
- [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake/): Publication homepage
- [All Posts](https://paragraph.com/@gcake/): More posts from this publication
- [RSS Feed](https://api.paragraph.com/blogs/rss/@gcake): Subscribe to updates