Next.js全栈电商实战:小米商城复刻与性能优化
1. 项目背景与核心价值去年双十一期间我在研究电商平台的前端性能优化时发现小米商城官网的加载速度明显优于同类竞品。通过Chrome DevTools分析发现其采用了Next.js的混合渲染策略。这激发了我用Next.js全栈技术栈完整复刻小米商城的想法——不仅要做界面克隆更要实现核心电商功能。这个项目完整实现了商品列表SSR渲染首屏加载时间控制在800ms内动态路由的商品详情页ISR增量静态再生购物车状态管理使用Zustand替代Redux支付流程模拟接入支付宝沙箱环境响应式布局TailwindCSS原子化方案技术选型关键点Next.js 14App Router TypeScript TailwindCSS的组合在保证类型安全的同时CSS体积减少了62%经PurgeCSS处理后2. 工程架构设计解析2.1 项目初始化与工具链配置使用Vite作为构建工具初始化Next.js项目npm create vitelatest xiaomi-store --template next-ts关键依赖版本dependencies: { next: ^14.1.0, react: ^18.2.0, tailwindcss: ^3.4.0, zustand: ^4.4.1 }特别注意Next.js 14默认启用TurboPack但实测发现与部分Tailwind插件存在兼容问题。解决方案是在next.config.js中显式关闭const nextConfig { experimental: { turbo: false } }2.2 目录结构设计采用Next.js App Router规范的新型结构/app /(main) # 营销页面组 /page.tsx /(shop) # 电商功能组 /products /[id] /page.tsx # 动态路由 /api # 路由处理器 /checkout /route.ts /public /mi-font # 小米兰亭字体创新点在于按业务域划分路由组Route Groups这种设计允许不同路径共享相同布局如/(shop)组共用购物车侧边栏实现代码分割的物理隔离营销页面与核心功能独立打包3. 核心功能实现细节3.1 商品列表的SSR优化传统方案痛点纯客户端渲染会导致SEO不友好而纯SSR在SKU量大的场景下服务器压力大。我们的混合方案// app/(shop)/products/page.tsx export async function getServerSideProps() { const res await fetch(https://api.mock.com/products?page1) const data await res.json() return { props: { initialData: data, // 下次重新验证时间秒 revalidate: 60 * 30 // 30分钟增量更新 } } }性能优化技巧使用next/link预加载可视区域内的商品详情页对图片使用next/image的priority属性标记首屏图片分页数据采用React Server Components减少客户端bundle3.2 购物车状态管理放弃Redux选择Zustand的原因零样板代码Redux需要约200行boilerplate与React 18并发特性兼容性更好更简单的异步处理购物车Store实现import { create } from zustand type CartItem { id: string quantity: number price: number } type CartStore { items: CartItem[] addItem: (item: OmitCartItem, quantity) void removeItem: (id: string) void } export const useCart createCartStore((set) ({ items: [], addItem: (item) set((state) { const existing state.items.find(i i.id item.id) return { items: existing ? state.items.map(i i.id item.id ? {...i, quantity: i.quantity 1} : i ) : [...state.items, {...item, quantity: 1}] } }), removeItem: (id) set((state) ({ items: state.items.filter(i i.id ! id) })) }))踩坑记录Next.js的App Router默认是服务端组件需要在组件顶部添加use client指令才能使用状态管理4. 样式系统深度优化4.1 TailwindCSS配置技巧针对小米商城的视觉规范在tailwind.config.js中扩展module.exports { theme: { extend: { colors: { mi-orange: #ff6700, mi-dark: #333333, mi-gray: #f5f5f5 }, fontFamily: { sans: [MiSans, system-ui] } } } }字体处理方案将小米兰亭字体MiSans放入public/mi-font在全局CSS中定义font-facefont-face { font-family: MiSans; src: url(/mi-font/MiSans-Normal.woff2) format(woff2); font-display: swap; }4.2 响应式布局实战实现小米官网特色的汉堡菜单吸底导航双模式div classNamelg:hidden {/* 移动端菜单 */} MobileNav / /div div classNamehidden lg:block {/* PC端导航 */} DesktopNav / /div关键断点设计sm: 640px手机md: 768px平板lg: 1024px桌面xl: 1280px大屏5. 性能优化全记录5.1 Lighthouse评分提升路径初始评分Performance: 68SEO: 92Accessibility: 85优化措施图片优化使用next/image的avif格式比WebP小20%设置sizes属性匹配响应式布局Image src/product.jpg width{600} height{400} sizes(max-width: 768px) 100vw, 50vw altProduct /代码分割动态导入非关键组件const ProductCarousel dynamic(() import(./Carousel), { ssr: false, loading: () Skeleton / })最终评分Performance: 96SEO: 100Accessibility: 985.2 缓存策略配置next.config.js的headers配置async headers() { return [ { source: /_next/static/:path*, headers: [ { key: Cache-Control, value: public, max-age31536000, immutable } ] } ] }6. 部署与CI/CD实践6.1 Vercel部署配置项目根目录添加vercel.json{ rewrites: [ { source: /api/:path*, destination: https://api.mock.com/:path* } ], headers: [ { source: /(.*), headers: [ { key: X-Frame-Options, value: SAMEORIGIN } ] } ] }6.2 GitHub Actions自动化.github/workflows/deploy.yml关键步骤- name: Cache Next.js build uses: actions/cachev3 with: path: | .next/cache key: ${{ runner.os }}-nextjs-${{ hashFiles(**/package-lock.json) }} - name: Run Lighthouse CI run: | npm install -g lhci/cli lhci autorun7. 项目复盘与进阶建议经过三个月迭代项目完整复刻了小米商城90%的核心功能。几个关键收获Next.js的App Router虽然学习曲线陡峭但带来的架构优势明显路由组实现逻辑隔离服务端组件减少客户端JS体积约40%流式渲染改善LCP指标TailwindCSS需要建立严格规范定义自定义class如.card封装常用原子类组合使用apply提取重复样式配合stylelint防止类名重复状态管理选择建议简单场景Zustand复杂状态机XState全局共享Context useReducer源码已完整开源在GitHub搜索xiaomi-store-nextjs包含详细的中文注释和项目文档。对于想深入学习Next.js全栈开发的同学建议从商品详情页的动态路由实现开始阅读代码这是最能体现Next.js特色的部分。