說在前頭~
既然已經達成30天了,乾脆把庫存一次全部PO完好了~
安安,我是 ChiYu!
昨天,我們為 App 裝上了堅固的大門與門鎖,成功地實現了完整的使用者認證流程。至此,我們 MVP (最小可行產品) 的所有核心功能,已全部開發完成!這是一個巨大的里程碑,再次為堅持到這裡的你,獻上最熱烈的掌聲!
但是,我們的旅程還沒結束。一個專業的專案,不僅僅是功能的堆砌。回頭看看我們的 frontend/script.js
檔案,它現在已經變成一個包含了狀態管理、UI 渲染、API 請求、認證邏輯、事件監聽... 的巨大怪獸。它雖然能跑,但已經變得難以閱讀和維護。
今天,我們將進行系列文的最後一次程式碼實作,也是從「開發者」邁向「架構師」的關鍵一步。我們將扮演一位「程式碼整形醫師」,為我們臃腫的 script.js
進行一次徹底的「整形手術」,引入專業的 JavaScript 模組化,讓我們的專案達到生產級別的清晰度。
在我們動刀之前,先來理解一下我們手術的指導原則—— 「高內聚,低耦合 (High Cohesion, Low Coupling)」。這聽起來很玄,但卻是衡量所有軟體架構好壞的黃金標準。
我們現在的 script.js
,就是一個典型的「低內聚、高耦合」的壞例子:它什麼都做(低內聚),而且裡面所有功能都互相糾纏在一起(高耦合)。
而我們的解決方案,就是使用現代 JavaScript 內建的 ES6 Module (import
/export
)。它能讓我們像整理工具箱一樣,將不同功能的程式碼,放進各自專屬的 .js
檔案中,然後在需要的時候,精準地「進口 (import
)」我們需要的工具即可。
好了,理論武裝完畢!讓我們進入 gemini chat
模式,指揮 AI 為我們完成這次複雜的、外科手術級別的重構任務。
角色 (Role)
你是一位頂尖的 JavaScript 前端架構師,是「高內聚,低耦合」與「單一職責原則」的忠實信徒。你最擅長的工作,就是將一個巨大、混亂的單體 JavaScript 檔案,重構成為一個結構清晰、職責分離、易於維護的模組化專案。
**目標 (Objective)**
請對我現有的 `@frontend/script.js` 進行一次全面的、生產級別的模組化重構。
**上下文 (Context)**
- **目標重構檔案**: `@frontend/script.js`
**你的任務與產出要求 (Your Task & Output Requirements)**
請一步到位,為我執行以下所有檔案操作與程式碼重構任務:
**1. 建立新模組檔案**
在 `frontend` 資料夾中,建立以下四個新的 JavaScript 檔案:
- `state.js`
- `ui.js`
- `api.js`
- `auth.js`
**2. 拆分與遷移程式碼**
- **`state.js` (狀態中心)**:
- 將 `script.js` 中的 `state` 物件、`setState` 函式,完整地剪下並貼上到此檔案中。
- `state` 物件應被 `export`。
- `setState` 函式需要 `import render from './ui.js'`,並在內部呼叫它。
- **`api.js` (通訊模組)**:
- 將 `script.js` 中所有與 `fetch` 相關的函式 (`fetchHabits`, `addHabit`, `loginUser` 等),完整地剪下並貼上到此檔案中。
- 所有函式都應被 `export`。
- **`ui.js` (渲染引擎)**:
- 將 `script.js` 中所有 DOM 元素的選擇器 (`const habitListContainer = ...`)、以及所有渲染相關的函式 (`render`, `renderHabitList` 等),完整地剪下並貼上到此檔案中。
- `render` 函式需要 `import state from './state.js'`。
- `render` 函式應被 `export default`。
- **`auth.js` (認證模組)**:
- 將 `script.js` 中所有與認證相關的函式 (`saveTokenToStorage`, `getTokenFromStorage`, `routeGuard`, `handleLogin`, `handleLogout` 等),完整地剪下並貼上到此檔案中。
- 這些函式可能需要 `import` 其他模組的函式來協同工作 (例如 `import { loginUser } from './api.js'` 或 `import setState from './state.js'`)。
**3. 建立主入口檔案 `app.js`**
- 將舊的 `script.js` 重新命名為 `app.js`。
- 清空 `app.js` 的內容。
- 在 `app.js` 中,只保留應用程式的初始化邏輯,也就是 `DOMContentLoaded` 事件監聽器和所有事件綁定的程式碼。
- `app.js` 將作為「總指揮」,從其他模組 `import` 所需的函式來設定事件監聽。
**4. 更新 `index.html`**
- 修改 `@frontend/index.html`,將原本引用 `script.js` 的標籤,改為 `<script type="module" src="app.js"></script>`。`type="module"` 屬性至關重要。
AI 完成操作後,讓我們來欣賞一下我們煥然一新的、專業的 frontend
資料夾結構。
【重構後的專案結構】
frontend/ ├── assets/ │ └── logo.png ├── api.js # 只負責跟後端說話 ├── auth.js # 只負責登入登出 ├── state.js # 只負責管理數據 ├── ui.js # 只負責畫畫 ├── app.js # 總指揮,負責綁定事件 ├── index.html └── style.css
state.js
- 獨立的「大腦記憶體」:將 state
和 setState
獨立出來,讓我們的數據核心變得極度純粹和可預測。api.js
- 專職的「外交官」:所有與外部世界的溝通(後端 API),都由這個模組統一負責。未來如果後端 API 有變動,我們只需要修改這個檔案。ui.js
- 專心的「藝術家」:這個模組只關心一件事:拿到數據 (state
),然後把它畫出來。它完全不管數據是從哪裡來的。auth.js
- 盡責的「保全」:所有關於身份驗證的複雜邏輯,都被封裝在這裡。app.js
- 運籌帷幄的「專案經理」:它不再親自動手做任何事,而是像一位專案經理,負責協同各個專業模組,告訴它們「當使用者點擊這個按鈕時,請 auth.js
去處理登入」。這就是「單一職責原則」的完美體現!
是時候驗收了!再次啟動 Live Server。
你會發現,我們的 App 功能 與昨天完全一樣,完美無缺! 但是,它的「內部結構」,已經從一個混亂的作坊,進化成了一條分工明確、高度協同的現代化生產線!
refactor(frontend): modularize javascript code into separate files
再次恭喜!今天,我們的 App 完成了最後一次、也是最重要的一次蛻變。它現在不僅功能完整、體驗流暢,更擁有一個清晰、專業、可長期維護的程式碼架構。這是一個可以讓你驕傲地展示給任何面試官看的作品。
我們的 MVP 開發之旅,到此已接近尾聲。明天,我們將為這趟旅程,安排一個從容、深刻的收尾。我們將帶領讀者進行一次 專案全解析,從上帝視角,回顧我們的作品是如何從一份文件,一步步地「長成」現在這個樣子的!並且發表一下完結感言~