- API 路由统一: 移除 /api/h5/,统一 /api/pms/ 入口 - 二进制改名: api-server -> pms-api(与服务名一致) - nginx: 合并 /api/ + /pms/api/ 为 /api/pms/ - 新增 docs/API.md 接口文档 - 后端: CabinetDetail 增加 rssi/pow_fail/address/soc 等字段 - Redis 管道批量读取仓体实时数据(SOC/电压/电流/功率) - DB: 所有 TIMESTAMP 列改为 DATETIME(修复类型不匹配) - 用户管理: 新增创建时间/修改时间列,状态改用 Switch - 角色管理/用户管理: 操作按钮改为图标 - PC 设备详情: 基本信息补全 RSSI/ICCID/电源/地址 - PC 卡片: 通道统计改用 Lucide 图标,颜色统一 - PC 二维码: canvas 渲染,含编号文字,支持右键下载 - H5: 按 uni-app 规范修正导航(navigateTo 替代 reLaunch) - H5: 详情页加返回导航条 - H5: 扫码支持摄像头(jsQR)+ ?id= 参数 - H5: 底部 tabBar 在所有页面常显 - H5: 首页统计改为 6 项(设备/通道/空闲/充电/充满/故障) - H5: 下拉刷新 / 上拉加载 - 产品首页: 添加业务联系 - 文档: 清理过时文件,补充缺失规范章节
4.9 KiB
4.9 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Use SSR or SSG for Page Load Critical Applications | HIGH | Client-side SPAs require JavaScript execution before content appears, severely impacting LCP and INP metrics | capability |
|
Use SSR or SSG for Page Load Critical Applications
Impact: HIGH - Pure client-side SPAs must download, parse, and execute JavaScript before users see content. This significantly delays Largest Contentful Paint (LCP) and impacts Core Web Vitals. For page load-critical apps (marketing sites, e-commerce, content sites), use Server-Side Rendering (SSR) or Static Site Generation (SSG).
Choose your architecture based on your content's nature and page load requirements.
Task Checklist
- Evaluate if page load performance is critical for your use case
- Choose SSR for dynamic content that changes per request
- Choose SSG for content that doesn't change frequently
- Consider hybrid approaches (SSG for marketing, SPA for app)
- Use Nuxt.js for streamlined SSR/SSG with Vue
Architecture Decision Guide
| Content Type | Changes | Best Approach | Example |
|---|---|---|---|
| Marketing pages | Rarely | SSG | Landing pages, docs |
| Blog/content | On publish | SSG with regeneration | Blog, documentation |
| E-commerce catalog | Hourly/daily | SSG + ISR | Product listings |
| User dashboard | Per request | SPA (ok) | Admin panels |
| Social feed | Real-time | SSR or SPA | News feed |
| Authenticated app | Per user | SPA (ok) | Internal tools |
Incorrect:
// BAD: Pure client-side SPA for a marketing site
// Users see blank page until JS loads and executes
// main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app') // Nothing visible until this runs
// index.html - Users see empty #app until JS executes
// <div id="app"></div>
Correct:
// GOOD: Use Nuxt.js for SSR/SSG
// nuxt.config.ts
export default defineNuxtConfig({
// SSG: Pre-render at build time (best for static content)
ssr: true,
nitro: {
prerender: {
routes: ['/', '/about', '/pricing', '/blog']
}
}
})
// Or full SSR for dynamic content
export default defineNuxtConfig({
ssr: true // Server renders on each request
})
<!-- pages/index.vue - Works with both SSR and SSG -->
<template>
<div>
<HeroSection />
<FeatureList :features="features" />
<PricingTable />
</div>
</template>
<script setup>
// Data fetched at build time (SSG) or request time (SSR)
const { data: features } = await useFetch('/api/features')
</script>
Hybrid Approach: SSG Marketing + SPA App
// nuxt.config.ts - Hybrid rendering
export default defineNuxtConfig({
routeRules: {
// Static pages - pre-rendered at build
'/': { prerender: true },
'/about': { prerender: true },
'/pricing': { prerender: true },
'/blog/**': { prerender: true },
// Dynamic app sections - client-side only
'/dashboard/**': { ssr: false },
'/app/**': { ssr: false },
// API routes - server-side
'/api/**': { cors: true }
}
})
Manual SSR with Vue (without Nuxt)
// server.js - Express with Vue SSR
import express from 'express'
import { createSSRApp } from 'vue'
import { renderToString } from 'vue/server-renderer'
import App from './App.vue'
const app = express()
app.get('*', async (req, res) => {
const vueApp = createSSRApp(App)
const html = await renderToString(vueApp)
res.send(`
<!DOCTYPE html>
<html>
<head><title>My App</title></head>
<body>
<div id="app">${html}</div>
<script type="module" src="/client.js"></script>
</body>
</html>
`)
})
Performance Impact
| Approach | Time to First Byte | LCP | JavaScript Required |
|---|---|---|---|
| Client SPA | Fast | Slow (waits for JS) | Yes, before content |
| SSR | Slower | Fast (HTML ready) | No, for initial view |
| SSG | Fast (CDN) | Fast (HTML ready) | No, for initial view |
When Client-Side SPA Is Acceptable
- Internal tools and dashboards (users expect loading)
- Authenticated applications (initial load happens once)
- Real-time collaborative apps (WebSocket-heavy)
- PWAs where offline-first is the priority
- Complex interactive applications (Figma-like)
Static Site Generation with Vite
// vite.config.js - Using vite-ssg for SSG
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
ssgOptions: {
script: 'async',
formatting: 'minify'
}
})