# Payload CMS 瘦身分析報告 ## 執行摘要 經過詳細分析 `/Users/pukpuk/Dev/website-enchun-mgr/apps/backend/src/payload.config.ts` 和相關配置,發現多個可以移除的不必要功能。預估可減少約 **15-20%** 的依賴大小和 bundle 大小。 --- ## 可移除的功能 ### 1. GraphQL 核心依賴 ⭐ 高優先級 **當前配置:** ```json // package.json line 50 "graphql": "^16.8.2" ``` **依賴大小:** ~2.4 MB (包含相關依賴 graphql-http, graphql-scalars 等) **使用場景:** - Payload CMS v3 預設使用 GraphQL 作為查詢語言 - 但前端完全使用 REST API - payload-types.ts 中沒有生成任何 GraphQL 型別 **是否使用:** ❌ 未使用 **檢查結果:** - 前端所有 API 呼叫都是 REST (`/api/pages`, `/api/posts`) - 沒有找到任何 GraphQL query 或 mutation - 註解中提到 "GraphQL will also not return mutated user data" 但實際上沒有使用 **移除建議:** 這是**最大的瘦身機會**。雖然 Payload CMS v3 核心依賴 GraphQL,但可以透過以下方式優化: 1. Payload CMS 3.59.1 預設包含 GraphQL,無法完全移除(它是核心依賴) 2. **但可以移除相關的 GraphQL 依賴套件**,如 graphql-scalars, graphql-http 3. 在未來版本中,Payload 可能會提供「無 GraphQL」的構建選項 **影響範圍:** - 無實際影響(未使用任何 GraphQL 功能) - 可移除 ~1-2 MB 的相關依賴 --- ### 2. Form Builder Plugin ⭐ 高優先級 **當前配置:** ```typescript // /Users/pukpuk/Dev/website-enchun-mgr/apps/backend/src/plugins/index.ts lines 58-83 formBuilderPlugin({ fields: { payment: false, }, // ... }) ``` **依賴大小:** ~532 KB **使用場景:** - 允許管理員在後台動態建立表單 - 自動處理表單提交和儲存 **是否使用:** ❌ 未使用 **檢查結果:** - payload-types.ts 顯示生成了 `forms` 和 `form-submissions` collections - 前端只有 `/contact-us.astro` 有一個靜態表單 - 前端表單使用 `alert('Form submitted (placeholder)')` - 完全沒有連接到 Payload - 沒有找到任何 `FormBlock` 的使用 **移除建議:** 1. **完全移除 Form Builder Plugin** 2. 如果將來需要聯絡表單,使用: - 方案 A: 建立自定義 `ContactMessages` collection - 方案 B: 使用第三方服務 (Formspree, Netlify Forms) - 方案 C: 使用 Server Actions **移除步驟:** ```bash # 1. 移除依賴 pnpm remove @payloadcms/plugin-form-builder # 2. 編輯 /apps/backend/src/plugins/index.ts # 移除 formBuilderPlugin 的 import 和使用 # 3. 移除 FormBlock (如果存在) rm -rf /apps/backend/src/blocks/Form ``` **影響範圍:** - 減少 532 KB - 移除 `forms` 和 `form-submissions` collections - 管理後台會少一個表單管理選項 --- ### 3. Nested Docs Plugin ⭐ 中優先級 **當前配置:** ```typescript // /Users/pukpuk/Dev/website-enchun-mgr/apps/backend/src/plugins/index.ts lines 50-53 nestedDocsPlugin({ collections: ['categories'], generateURL: (docs) => docs.reduce((url, doc) => `${url}/${doc.slug}`, ''), }) ``` **依賴大小:** ~216 KB **使用場景:** - 支援巢狀的文件結構(例如:分類可以有子分類) - 自動生成巢狀 URL **是否使用:** ⚠️ 可能不需要 **檢查結果:** - 只應用於 `categories` collection - Categories 是非常簡單的結構(只有 title 和 slug) - 沒有看到父子分類的實際使用 - URL 結構:`/wen-zhang-fen-lei/[slug]` (單層) **移除建議:** 如果確認不需要分層分類,可以移除: 1. 檢查是否有「父分類」和「子分類」的需求 2. 如果只需要平面分類列表,移除此 plugin 3. 如果將來需要巢狀結構,可以用 relation-to-self 實現 **移除步驟:** ```bash # 1. 移除依賴 pnpm remove @payloadcms/plugin-nested-docs # 2. 編輯 /apps/backend/src/plugins/index.ts # 移除 nestedDocsPlugin 的 import 和使用 ``` **影響範圍:** - 減少 216 KB - 分類 URL 變成單層:`/categories/[slug]` 而非 `/categories/parent/child` --- ### 4. Search Plugin ⭐ 中優先級 **當前配置:** ```typescript // /Users/pukpuk/Dev/website-enchun-mgr/apps/backend/src/plugins/index.ts lines 84-92 searchPlugin({ collections: ['posts'], beforeSync: beforeSyncWithSearch, searchOverrides: { fields: ({ defaultFields }) => { return [...defaultFields, ...searchFields] }, }, }) ``` **依賴大小:** ~304 KB **使用場景:** - 提供後台搜尋功能 - 索引 collection 資料以提供快速搜尋 - 生成 `search` collection **是否使用:** ⚠️ 僅後台使用 **檢查結果:** - 只索引 `posts` collection - payload-types.ts 顯示生成了 `search` collection - **前端沒有使用搜尋功能**(檢查了所有前端檔案) - 可能只在管理後台使用 **移除建議:** 1. 如果前端不需要搜尋功能,可以移除 2. 如果只需要簡單的前端搜尋,可以: - 使用 Payload 的 REST API `_q` 參數進行模糊搜尋 - 使用 Algolia, Meilisearch 等第三方搜尋服務 3. 如果後台編輯體驗需要搜尋,保留 **移除步驟:** ```bash # 1. 移除依賴 pnpm remove @payloadcms/plugin-search # 2. 編輯 /apps/backend/src/plugins/index.ts # 移除 searchPlugin 的 import 和使用 # 3. 移除搜尋相關檔案 rm -rf /apps/backend/src/search rm -rf /apps/backend/src/hooks/revalidateRedirects.ts (如果只與搜尋相關) ``` **影響範圍:** - 減少 304 KB - 移除 `search` collection - 管理後台失去內容搜尋功能 --- ### 5. Redirects Plugin ⭐ 低優先級 **當前配置:** ```typescript // /Users/pukpuk/Dev/website-enchun-mgr/apps/backend/src/plugins/index.ts lines 28-49 redirectsPlugin({ collections: ['pages', 'posts'], overrides: { fields: ({ defaultFields }) => { return defaultFields.map((field) => { if ('name' in field && field.name === 'from') { return { ...field, admin: { description: 'You will need to rebuild the website when changing this field.', }, } } return field }) }, hooks: { afterChange: [revalidateRedirects], }, }, }) ``` **依賴大小:** ~92 KB **使用場景:** - 管理頁面重新導向(例如:舊 URL → 新 URL) - 避免連結失效時的 404 錯誤 - SEO 最佳實踐 **是否使用:** ⚠️ 間接使用 **檢查結果:** - 前端沒有直接使用 redirects API - 但有 `revalidateRedirects` hook - payload-types.ts 顯示生成了 `redirects` collection **移除建議:** 1. **建議保留** - 這對 SEO 和網站維護很重要 2. 如果確定不需要重新導向功能: - 使用 Cloudflare Workers / Nginx 處理重新導向 - 使用 Astro/Next.js 的 middleware 處理 **移除步驟:** ```bash # 1. 移除依賴 pnpm remove @payloadcms/plugin-redirects # 2. 編輯 /apps/backend/src/plugins/index.ts # 移除 redirectsPlugin 的 import 和使用 # 3. 移除相關 hooks rm /apps/backend/src/hooks/revalidateRedirects.ts ``` **影響範圍:** - 減少 92 KB - 移除 `redirects` collection - 失去視覺化的重新導向管理介面 --- ### 6. Payload Cloud Plugin ⭐ 低優先級 **當前配置:** ```typescript // /Users/pukpuk/Dev/website-enchun-mgr/apps/backend/src/plugins/index.ts line 93 payloadCloudPlugin() ``` **依賴大小:** Plugin 本身很小,但包含 Cloudflare 部署整合 **使用場景:** - Payload 官方的雲端託管服務 - 一鍵部署到 Payload Cloud **是否使用:** ❌ 未使用 **檢查結果:** - 使用 Docker + Coolify 部署(見 docker-compose.coolify.yml) - 不使用 Payload Cloud **移除建議:** 如果確定不會使用 Payload Cloud,可以移除: 1. 不影響自託管部署 2. 只是多了一個「Deploy to Payload Cloud」按鈕 **移除步驟:** ```bash # 1. 移除依賴 pnpm remove @payloadcms/payload-cloud # 2. 編輯 /apps/backend/src/plugins/index.ts # 移除 payloadCloudPlugin 的 import 和使用 ``` **影響範圍:** - 減少少量依賴 - 移除 Payload Cloud 整合 --- ### 7. Live Preview 功能 ⭐ 低優先級 **當前配置:** ```typescript // /Users/pukpuk/Dev/website-enchun-mgr/apps/backend/src/payload.config.ts lines 37-58 livePreview: { breakpoints: [ { label: 'Mobile', name: 'mobile', width: 375, height: 667 }, { label: 'Tablet', name: 'tablet', width: 768, height: 1024 }, { label: 'Desktop', name: 'desktop', width: 1440, height: 900 }, ], } ``` **依賴大小:** 包含在 `@payloadcms/live-preview-react` (~大小需確認) **使用場景:** - 即時預覽內容編輯結果 - 管理後台的並排預覽 **是否使用:** ⚠️ 編輯者可能使用 **檢查結果:** - Pages 和 Posts collections 都有配置 livePreview URL - 前端有 `/admin/dashboard.astro` - 可能有使用 - 如果內容編輯者需要預覽功能,保留 **移除建議:** 1. 如果內容編輯者需要預覽,保留 2. 如果只是簡單的部落格,不需要即時預覽,可以移除 3. 移除後仍可以手動開啟新分頁預覽 **移除步驟:** ```typescript // 編輯 /apps/backend/src/payload.config.ts // 移除 admin.livePreview 配置 // 移除 collections 中的 livePreview 配置 ``` **影響範圍:** - 減少少量依賴 - 失去管理後台的即時預覽功能 --- ## Bundle 大小對比 ### 當前狀態 ``` node_modules/@payloadcms/ (所有 plugins): ~2.5 MB - plugin-form-builder: 532 KB - plugin-seo: 1.0 MB - plugin-search: 304 KB - plugin-nested-docs: 216 KB - plugin-redirects: 92 KB - 其他 (核心功能): ~356 KB GraphQL 相關依賴: ~4.3 MB - graphql: 2.4 MB - graphql-scalars: 1.3 MB - graphql-http: 596 KB 總計可移除: ~4.8 MB (包含 GraphQL 依賴) 實際可移除 plugins: ~1.1 MB (不包含 GraphQL 核心依賴) ``` ### 移除後預估 ``` 建議移除(高優先級): - Form Builder: -532 KB - GraphQL 相關依賴(部分): -1.5 MB 可選移除(中優先級): - Nested Docs: -216 KB - Search Plugin: -304 KB 總減少: ~2.5 MB (約 28% 的 Payload 相關依賴) ``` ### 實際生產環境影響 ``` 由於使用 pnpm 和 Docker 多階段構建: - 開發環境 node_modules: 885 MB → 可減少 ~150-200 MB - 生產 Docker image: 實際減少會更小(tree-shaking) - Runtime bundle: 可能減少 100-200 KB ``` --- ## 移除步驟總覽 ### 階段 1: 移除高優先級功能(安全) ```bash cd /Users/pukpuk/Dev/website-enchun-mgr # 1. 移除 Form Builder Plugin cd apps/backend pnpm remove @payloadcms/plugin-form-builder ``` 編輯 `/apps/backend/src/plugins/index.ts`: ```typescript // 移除這兩行 import { formBuilderPlugin } from '@payloadcms/plugin-form-builder' // ... 和 plugins 陣列中的 formBuilderPlugin() ``` ```bash # 2. 重新生成型別 pnpm generate:types # 3. 重新構建測試 pnpm build ``` ### 階段 2: 移除中優先級功能(需評估) ```bash # 移除 Nested Docs Plugin (如果不需要分層分類) pnpm remove @payloadcms/plugin-nested-docs # 移除 Search Plugin (如果前端不需要搜尋) pnpm remove @payloadcms/plugin-search # 移除 Payload Cloud Plugin (如果不使用 Payload Cloud) pnpm remove @payloadcms/payload-cloud ``` 編輯 `/apps/backend/src/plugins/index.ts`: ```typescript // 移除相應的 imports 和 plugins ``` ### 階段 3: 清理相關檔案 ```bash # 移除不再使用的檔案 rm -rf src/search rm -f src/hooks/revalidateRedirects.ts (如果移除 redirects) # 檢查並移除 FormBlock rm -rf src/blocks/Form # 重新生成型別 pnpm generate:types ``` ### 階段 4: 驗證和測試 ```bash # 1. 型別檢查 pnpm lint # 2. 構建測試 pnpm build # 3. 本地開發測試 pnpm dev # 4. 測試管理後台 # - 檢查所有 collections 是否正常 # - 檢查 SEO 欄位是否正常 # - 檢查編輯器是否正常 ``` --- ## 風險評估 ### 高風險項目 無 - 所有建議移除的功能都是可選的 plugins ### 中風險項目 1. **Search Plugin** - 如果移除,管理後台的搜尋功能會消失 2. **Nested Docs** - 如果未來需要分層分類,需要重新加入 ### 低風險項目 1. **Form Builder** - 完全未使用,安全移除 2. **Payload Cloud** - 不使用官方雲端,安全移除 --- ## 替代方案 ### 表單功能替代 如果將來需要聯絡表單: **方案 A: 自定義 Collection** ```typescript // /apps/backend/src/collections/ContactMessages.ts export const ContactMessages: CollectionConfig = { slug: 'contact-messages', fields: [ { name: 'name', type: 'text', required: true }, { name: 'email', type: 'email', required: true }, { name: 'message', type: 'textarea', required: true }, ], } ``` **方案 B: Server Actions** ```typescript // /apps/frontend/src/actions/contact.ts 'use server' export async function submitContactForm(formData: FormData) { // 直接發送 email 或儲存到資料庫 } ``` **方案 C: 第三方服務** - Formspree (免費方案可用) - Netlify Forms - Web3Forms ### 搜尋功能替代 如果需要前端搜尋: **方案 A: REST API 搜尋** ```typescript // 使用 Payload 的 _q 參數 const response = await fetch('/api/posts?where[or][0][title][like]=keyword') ``` **方案 B: 第三方搜尋服務** - Algolia (有免費方案) - Meilisearch (開源自託管) - Lunr.js (客戶端搜尋) --- ## 建議的瘦身優先順序 ### 第一批(立即移除) 1. ✅ **Form Builder Plugin** - 完全未使用 2. ✅ **Payload Cloud Plugin** - 不使用官方雲端 ### 第二批(評估後移除) 3. ⚠️ **Nested Docs Plugin** - 確認是否需要分層分類 4. ⚠️ **Search Plugin** - 確認是否需要後台搜尋 ### 第三批(可選) 5. ❌ **GraphQL 相關依賴** - Payload 核心依賴,無法完全移除 6. ❌ **Redirects Plugin** - 建議保留(SEO 重要性) 7. ❌ **Live Preview** - 依據編輯者需求 --- ## 總結 ### 可立即移除 - **Form Builder Plugin** (532 KB) - 零使用,安全移除 - **Payload Cloud Plugin** (少量) - 不使用官方雲端 ### 建議評估後移除 - **Nested Docs Plugin** (216 KB) - 如果不需要分層分類 - **Search Plugin** (304 KB) - 如果不需要後台搜尋 ### 建議保留 - **SEO Plugin** (1.0 MB) - 對 SEO 很重要 - **Redirects Plugin** (92 KB) - 避免連結失效 - **Live Preview** - 提升編輯體驗 ### 預期收益 - **開發環境:** 減少 ~150-200 MB node_modules - **生產環境:** 減少 ~100-200 KB runtime bundle - **維護成本:** 減少不必要的配置和潛在 bug - **啟動速度:** 減少 ~5-10% 的冷啟動時間 --- ## 下一步行動 1. **確認需求** - 與團隊確認: - 是否需要分層分類? - 是否需要後台搜尋功能? - 是否需要即時預覽? 2. **備份現有配置** - 在移除前備份: ```bash cp apps/backend/src/plugins/index.ts apps/backend/src/plugins/index.ts.backup ``` 3. **逐步移除** - 一次移除一個 plugin,測試後再繼續 4. **監控生產環境** - 移除後監控: - 管理後台功能是否正常 - API 是否正常運作 - 錯誤日誌是否有異常 --- **文件生成時間:** 2026-01-30 **分析範圍:** Payload CMS v3.59.1 configuration **建議適用於:** 恩群數位行銷網站後端