-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
enhancementNew feature or requestNew feature or request
Description
⚡ 效能類型
打包大小
📊 問題描述
根據 motion.dev 官方文件分析和程式碼審查,目前專案中的 motion components 實作存在以下優化機會:
Primary Issues (主要問題)
- Bundle Size 過大: 使用完整的
motion組件 (34kb) 而非輕量版本 - Feature Loading: 未使用 LazyMotion 進行功能分割和延遲載入
- Tree Shaking: 未充分利用 bundler 的 tree-shaking 能力
Minor Issues Identified (次要問題)
-
Potential Motion Warnings (Low Priority)
- Location:
src/components/landing/cta-section.tsx:47-92 - Issue: 三個浮動元素可能觸發 React 關於 motion props 的警告
<motion.div className="absolute top-10 left-10..." animate={{ /* complex animation */ }} />
- Impact: 開發環境中的裝飾性 console 警告
- Recommendation: 監控 React warnings about motion props on DOM elements
- Location:
-
Animation Performance on Low-End Devices (Low Priority)
- Location: Background blur effects with multiple simultaneous animations
- Issue: 多重模糊效果與同時動畫可能在低階裝置造成效能問題
- Recommendation: 考慮新增 prefers-reduced-motion 媒體查詢支援以提升無障礙性
當前實作問題:
// src/components/landing/cta-section.tsx
import { motion } from "motion/react"; // 34kb 完整版本
// 多重複雜動畫同時執行 - 可能觸發警告
<motion.div animate={{ scale: [1, 1.2, 1], opacity: [0.3, 0.6, 0.3] }} />📈 效能數據
當前 Bundle 影響:
- motion 組件: ~34kb (未 tree-shake)
- 實際使用功能: 僅動畫和基礎手勢
- 建議優化後: ~4.6kb (初始) + 15kb (domAnimation 延遲載入)
- 潛在節省: ~14.4kb (-42% bundle size)
Runtime 數據:
- 同時動畫元件: 3個浮動元素
- 動畫屬性: scale, opacity, x, y 軸變換
- 模糊效果: blur-3xl, blur-2xl 同時渲染
- Console warnings: 開發環境中可能出現 motion props 相關警告
建議測量工具:
- Bundlephobia
- Webpack Bundle Analyzer
- Chrome DevTools Performance tab
- React DevTools Profiler
🖥️ 測試環境
- OS: macOS 15.6.1
- Node.js: 當前專案版本
- 瀏覽器: Chrome, Safari, Firefox
- Bundler: Webpack (Next.js 內建)
🔄 重現方式
1. Bundle Size 分析
npm run build
npm install -g webpack-bundle-analyzer
npx webpack-bundle-analyzer .next/static/chunks/2. Motion Warnings 檢查
npm run dev
# 開啟瀏覽器 DevTools > Console
# 導航至 landing page
# 查看是否有 motion props 相關警告3. 低階裝置效能測試
# 啟動開發伺服器
npm run dev
# Chrome DevTools > Performance
# 設定 CPU throttling 為 4x slowdown
# 記錄 Landing page 載入和滾動互動
# 觀察 CTASection 動畫的 frame rate4. 載入效能測試
npm run build
npx lighthouse http://localhost:3000 --only-categories=performance💡 優化建議
1. 採用 LazyMotion + m 組件 (高優先級)
目標: 減少 42% bundle size (34kb → 19.6kb)
// 當前實作 - 完整 motion 組件 (34kb)
import { motion } from "motion/react";
// 建議實作 - LazyMotion + m 組件 (4.6kb 初始)
import { LazyMotion, domAnimation } from "motion/react";
import * as m from "motion/react-m";
// 1. App 層級設定 LazyMotion
function App({ children }) {
return (
<LazyMotion features={domAnimation} strict>
{children}
</LazyMotion>
);
}
// 2. 組件中使用 m 替代 motion
export const CTASection = () => {
return (
<m.section
data-testid="cta-section"
className="relative mx-6 overflow-hidden rounded-lg bg-card px-4 py-24 text-center lg:mx-12"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
{/* 其餘實作相同 */}
</m.section>
);
};2. 修正 Motion Props 警告 (中優先級)
// 問題位置: src/components/landing/cta-section.tsx:47-92
// 當前可能觸發警告的實作
<motion.div
className="absolute top-10 left-10..."
animate={{ scale: [1, 1.2, 1], opacity: [0.3, 0.6, 0.3] }}
/>
// 建議修正: 確保正確使用 motion components
<m.div
className="absolute top-10 left-10 will-change-transform"
animate={{
scale: [1, 1.1, 1], // 減少變化幅度
opacity: [0.4, 0.6, 0.4]
}}
transition={{
duration: 6, // 延長動畫減少 CPU 負擔
repeat: Infinity,
ease: "easeInOut"
}}
/>3. 新增 prefers-reduced-motion 支援 (高優先級)
// 解決低階裝置效能問題
import { useReducedMotion } from "motion/react";
const CTABackgroundEffects = () => {
const shouldReduceMotion = useReducedMotion();
if (shouldReduceMotion) {
return (
<div
data-testid="cta-background-effects"
className="pointer-events-none absolute inset-0 z-10"
>
{/* 靜態背景效果,無動畫 */}
<div className="absolute top-10 left-10 h-64 w-64 rounded-full bg-primary/20 blur-3xl" />
<div className="absolute right-10 bottom-10 h-48 w-48 rounded-full bg-secondary/30 blur-3xl" />
</div>
);
}
return (
// 原始動畫實作
<div
data-testid="cta-background-effects"
className="pointer-events-none absolute inset-0 z-10"
>
{/* 動畫版本 */}
</div>
);
};4. 延遲載入進階功能 (中優先級)
// features.js - 分離功能載入
import { domAnimation } from "motion/react";
export default domAnimation;
// App.tsx - 延遲載入
import { LazyMotion } from "motion/react";
const loadFeatures = () =>
import("./features.js").then(res => res.default);
function App() {
return (
<LazyMotion features={loadFeatures} strict>
{/* 動畫將在 loadFeatures 解析後執行 */}
{children}
</LazyMotion>
);
}5. 功能包選擇最佳化 (中優先級)
// 當前需求分析:
// ✅ 需要: animations, variants, tap/hover/focus gestures
// ❌ 不需要: pan/drag gestures, layout animations
// 建議使用 domAnimation (15kb) 而非 domMax (25kb)
import { domAnimation } from "motion/react"; // +15kb
// 避免: import { domMax } from "motion/react"; // +25kb6. 嚴格模式防護 (高優先級)
// 防止意外使用完整 motion 組件
<LazyMotion features={domAnimation} strict>
{/* 這將拋出錯誤提醒 */}
{/* <motion.div /> */}
{/* 正確使用 */}
<m.div />
</LazyMotion>7. 測試環境相容性更新 (必須)
// jest.setup.ts - Mock 更新
jest.mock("motion/react", () => ({
LazyMotion: ({ children }: any) => children,
domAnimation: {},
useReducedMotion: () => false, // 測試環境預設啟用動畫
}));
jest.mock("motion/react-m", () => ({
m: {
section: ({ children, className, ...props }: any) => (
<section className={className} {...props}>
{children}
</section>
),
div: ({ children, className, ...props }: any) => (
<div className={className} {...props}>
{children}
</div>
),
},
}));8. 動畫效能優化 (低優先級)
// 優化多重模糊效果的渲染
const optimizedEffects = `
.floating-effect {
transform: translateZ(0); /* 強制硬體加速 */
backface-visibility: hidden; /* 避免背面渲染 */
perspective: 1000px; /* 3D 加速 */
will-change: transform; /* 預告瀏覽器即將變換 */
}
`;
// 錯開動畫啟動時間,避免同時計算
const variants = {
hidden: { opacity: 0, scale: 0.8 },
visible: (i: number) => ({
opacity: [0.3, 0.6, 0.3],
scale: [1, 1.1, 1],
transition: {
delay: i * 0.5, // 錯開 0.5s
duration: 4,
repeat: Infinity,
}
})
};🚀 實作時程建議
Phase 1 (本週): 核心優化
- 在 App 層級加入 LazyMotion wrapper
- 將 CTASection 的 motion 改為 m
- 使用 domAnimation 功能包
- 更新測試 mock
- 新增 prefers-reduced-motion 支援
Phase 2 (下週): 進階優化
- 實作 features.js 分離載入
- 啟用 strict mode
- 修正 motion props 警告
- Bundle size 驗證測試
Phase 3 (後續): 監控與維護
- 設定 bundle 大小 CI 檢查
- Lighthouse 效能回歸測試
- 低階裝置效能監控
- 動畫效能深度優化
✅ 成功指標
效能指標
- Bundle Size: 減少 14.4kb (-42%)
- 初始載入: 4.6kb motion 相關程式碼
- 延遲載入: 15kb domAnimation 功能
- 載入時間: Lighthouse Performance score 提升
品質指標
- Console 清潔: 開發環境無 motion warnings
- 無障礙性: 支援 prefers-reduced-motion 使用者
- 效能: 低階裝置保持 30+ FPS
- 開發體驗: strict mode 防止回歸
測試指標
- 測試通過: 所有現有測試繼續通過
- Mock 更新: 新的 motion 架構正確模擬
- 覆蓋率: 維持現有的測試覆蓋率
🔧 驗證方法
# 1. Bundle 分析
npm run build
du -sh .next/static/chunks/pages/_app-*.js
# 2. Bundlephobia 檢查
# Before: motion/react (~34kb)
# After: motion/react-m + domAnimation (~19.6kb)
# 3. Lighthouse 效能測試
npx lighthouse http://localhost:3000 --only-categories=performance
# 4. 測試環境驗證
npm test -- src/components/landing/__tests__/features.test.tsx
# 5. Console 警告檢查
npm run dev
# 檢查瀏覽器 Console 是否有 motion 相關警告📈 預期結果
根據官方文件,預期可達成:
- Initial Bundle: 4.6kb (m + LazyMotion)
- Feature Bundle: 15kb (domAnimation)
- Total Impact: 19.6kb vs 目前 34kb
- 節省比例: 42% bundle size 減少
- 載入改善: 首次載入時間顯著降低
- 使用體驗: 在行動裝置和慢速網路環境下的體驗提升
🔗 相關資源
- Motion.dev Bundle Size Reduction
- LazyMotion 官方文件
- useReducedMotion Hook
- Web.dev: prefers-reduced-motion
- Bundlephobia - 分析套件大小
📝 後續行動
此優化將顯著改善首次載入效能,同時解決開發環境警告和低階裝置效能問題。建議優先處理 LazyMotion 實作和 prefers-reduced-motion 支援,因為這些直接影響使用者體驗和無障礙性。
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request