12.1 Vue SSR最佳实践总结

12.1.1 架构设计最佳实践

// 推荐的项目架构
const recommendedArchitecture = {
  // 目录结构
  structure: {
    'src/': {
      'client/': '客户端特定代码',
      'server/': '服务端特定代码',
      'shared/': '共享代码',
      'components/': '通用组件',
      'pages/': '页面组件',
      'store/': '状态管理',
      'router/': '路由配置',
      'utils/': '工具函数',
      'api/': 'API接口',
      'assets/': '静态资源'
    }
  },
  
  // 代码组织原则
  principles: [
    '单一职责原则',
    '依赖注入',
    '配置与代码分离',
    '环境隔离',
    '模块化设计'
  ],
  
  // 性能优化策略
  performance: {
    caching: '多级缓存策略',
    bundling: '智能代码分割',
    loading: '渐进式加载',
    optimization: '资源优化'
  }
}

12.1.2 代码规范与约定

// .eslintrc.js - ESLint配置
module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
    es2021: true
  },
  extends: [
    '@nuxtjs/eslint-config-typescript',
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier'
  ],
  plugins: [
    '@typescript-eslint',
    'vue'
  ],
  rules: {
    // Vue规则
    'vue/component-name-in-template-casing': ['error', 'PascalCase'],
    'vue/no-v-html': 'off',
    'vue/require-default-prop': 'off',
    'vue/require-explicit-emits': 'error',
    'vue/multi-word-component-names': 'off',
    
    // TypeScript规则
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-explicit-any': 'warn',
    
    // 通用规则
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
    'prefer-const': 'error',
    'no-var': 'error',
    'object-shorthand': 'error',
    'prefer-template': 'error'
  },
  
  // SSR特定规则
  overrides: [
    {
      files: ['server/**/*.js', 'server/**/*.ts'],
      env: {
        browser: false,
        node: true
      },
      rules: {
        'no-console': 'off' // 服务端允许console
      }
    },
    {
      files: ['client/**/*.js', 'client/**/*.ts'],
      env: {
        browser: true,
        node: false
      }
    }
  ]
}
// prettier.config.js - Prettier配置
module.exports = {
  semi: false,
  singleQuote: true,
  quoteProps: 'as-needed',
  trailingComma: 'none',
  bracketSpacing: true,
  bracketSameLine: false,
  arrowParens: 'avoid',
  printWidth: 100,
  tabWidth: 2,
  useTabs: false,
  endOfLine: 'lf',
  
  // Vue文件特定配置
  overrides: [
    {
      files: '*.vue',
      options: {
        parser: 'vue'
      }
    }
  ]
}

12.1.3 组件设计模式

<!-- 推荐的组件设计模式 -->
<template>
  <div class="product-card" :class="cardClasses">
    <!-- 图片区域 -->
    <div class="product-card__image">
      <LazyImage
        :src="product.image"
        :alt="product.name"
        :placeholder="placeholderImage"
        @load="onImageLoad"
        @error="onImageError"
      />
      
      <!-- 标签 -->
      <div v-if="product.tags?.length" class="product-card__tags">
        <span
          v-for="tag in product.tags"
          :key="tag"
          class="product-card__tag"
        >
          {{ tag }}
        </span>
      </div>
    </div>
    
    <!-- 内容区域 -->
    <div class="product-card__content">
      <h3 class="product-card__title">
        <NuxtLink :to="productUrl" class="product-card__link">
          {{ product.name }}
        </NuxtLink>
      </h3>
      
      <p class="product-card__description">
        {{ truncatedDescription }}
      </p>
      
      <div class="product-card__price">
        <span v-if="product.originalPrice" class="product-card__original-price">
          {{ formatPrice(product.originalPrice) }}
        </span>
        <span class="product-card__current-price">
          {{ formatPrice(product.price) }}
        </span>
        <span v-if="discountPercentage" class="product-card__discount">
          -{{ discountPercentage }}%
        </span>
      </div>
      
      <!-- 评分 -->
      <div v-if="product.rating" class="product-card__rating">
        <StarRating :rating="product.rating" :readonly="true" />
        <span class="product-card__rating-text">
          ({{ product.reviewCount || 0 }})
        </span>
      </div>
    </div>
    
    <!-- 操作区域 -->
    <div class="product-card__actions">
      <button
        class="product-card__cart-btn"
        :disabled="!product.inStock || loading"
        @click="addToCart"
      >
        <LoadingSpinner v-if="loading" size="small" />
        <template v-else>
          <CartIcon />
          {{ product.inStock ? '加入购物车' : '缺货' }}
        </template>
      </button>
      
      <button
        class="product-card__wishlist-btn"
        :class="{ 'is-active': isInWishlist }"
        @click="toggleWishlist"
      >
        <HeartIcon :filled="isInWishlist" />
      </button>
    </div>
  </div>
</template>

<script>
import { defineComponent, computed, ref } from 'vue'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'

// 组件
import LazyImage from '@/components/common/LazyImage.vue'
import StarRating from '@/components/common/StarRating.vue'
import LoadingSpinner from '@/components/common/LoadingSpinner.vue'
import CartIcon from '@/components/icons/CartIcon.vue'
import HeartIcon from '@/components/icons/HeartIcon.vue'

// 工具函数
import { formatPrice, truncateText } from '@/utils/helpers'
import { trackEvent } from '@/utils/analytics'

export default defineComponent({
  name: 'ProductCard',
  
  components: {
    LazyImage,
    StarRating,
    LoadingSpinner,
    CartIcon,
    HeartIcon
  },
  
  props: {
    product: {
      type: Object,
      required: true,
      validator: (product) => {
        return product && typeof product === 'object' && product.id && product.name
      }
    },
    
    variant: {
      type: String,
      default: 'default',
      validator: (value) => ['default', 'compact', 'featured'].includes(value)
    },
    
    showActions: {
      type: Boolean,
      default: true
    }
  },
  
  emits: [
    'add-to-cart',
    'toggle-wishlist',
    'image-load',
    'image-error'
  ],
  
  setup(props, { emit }) {
    const store = useStore()
    const router = useRouter()
    
    // 响应式数据
    const loading = ref(false)
    const imageLoaded = ref(false)
    const imageError = ref(false)
    
    // 计算属性
    const cardClasses = computed(() => ({
      [`product-card--${props.variant}`]: true,
      'product-card--loading': loading.value,
      'product-card--no-stock': !props.product.inStock
    }))
    
    const productUrl = computed(() => `/products/${props.product.slug || props.product.id}`)
    
    const truncatedDescription = computed(() => {
      const maxLength = props.variant === 'compact' ? 60 : 120
      return truncateText(props.product.description || '', maxLength)
    })
    
    const discountPercentage = computed(() => {
      if (!props.product.originalPrice || !props.product.price) return null
      
      const discount = ((props.product.originalPrice - props.product.price) / props.product.originalPrice) * 100
      return Math.round(discount)
    })
    
    const isInWishlist = computed(() => {
      return store.getters['wishlist/isInWishlist'](props.product.id)
    })
    
    const placeholderImage = computed(() => {
      return `/images/placeholder-${props.variant}.jpg`
    })
    
    // 方法
    const addToCart = async () => {
      if (!props.product.inStock || loading.value) return
      
      loading.value = true
      
      try {
        await store.dispatch('cart/addItem', {
          productId: props.product.id,
          quantity: 1
        })
        
        // 分析追踪
        trackEvent('add_to_cart', {
          product_id: props.product.id,
          product_name: props.product.name,
          price: props.product.price,
          category: props.product.category
        })
        
        emit('add-to-cart', props.product)
        
        // 显示成功消息
        store.dispatch('notifications/show', {
          type: 'success',
          message: '商品已加入购物车'
        })
        
      } catch (error) {
        console.error('添加到购物车失败:', error)
        
        store.dispatch('notifications/show', {
          type: 'error',
          message: '添加失败,请重试'
        })
      } finally {
        loading.value = false
      }
    }
    
    const toggleWishlist = async () => {
      try {
        if (isInWishlist.value) {
          await store.dispatch('wishlist/removeItem', props.product.id)
          trackEvent('remove_from_wishlist', { product_id: props.product.id })
        } else {
          await store.dispatch('wishlist/addItem', props.product)
          trackEvent('add_to_wishlist', { product_id: props.product.id })
        }
        
        emit('toggle-wishlist', {
          product: props.product,
          inWishlist: !isInWishlist.value
        })
        
      } catch (error) {
        console.error('收藏操作失败:', error)
        
        store.dispatch('notifications/show', {
          type: 'error',
          message: '操作失败,请重试'
        })
      }
    }
    
    const onImageLoad = () => {
      imageLoaded.value = true
      imageError.value = false
      emit('image-load', props.product)
    }
    
    const onImageError = () => {
      imageError.value = true
      imageLoaded.value = false
      emit('image-error', props.product)
    }
    
    return {
      // 响应式数据
      loading,
      imageLoaded,
      imageError,
      
      // 计算属性
      cardClasses,
      productUrl,
      truncatedDescription,
      discountPercentage,
      isInWishlist,
      placeholderImage,
      
      // 方法
      addToCart,
      toggleWishlist,
      onImageLoad,
      onImageError,
      formatPrice
    }
  }
})
</script>

<style lang="scss" scoped>
.product-card {
  display: flex;
  flex-direction: column;
  background: var(--color-white);
  border-radius: var(--border-radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: all 0.3s ease;
  
  &:hover {
    box-shadow: var(--shadow-lg);
    transform: translateY(-2px);
  }
  
  &--compact {
    .product-card__content {
      padding: var(--spacing-sm);
    }
    
    .product-card__title {
      font-size: var(--font-size-sm);
    }
  }
  
  &--featured {
    border: 2px solid var(--color-primary);
    
    .product-card__title {
      color: var(--color-primary);
    }
  }
  
  &--loading {
    pointer-events: none;
    opacity: 0.7;
  }
  
  &--no-stock {
    .product-card__image::after {
      content: '缺货';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background: rgba(0, 0, 0, 0.8);
      color: white;
      padding: var(--spacing-xs) var(--spacing-sm);
      border-radius: var(--border-radius-sm);
      font-weight: bold;
    }
  }
}

.product-card__image {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
}

.product-card__tags {
  position: absolute;
  top: var(--spacing-sm);
  left: var(--spacing-sm);
  display: flex;
  gap: var(--spacing-xs);
}

.product-card__tag {
  background: var(--color-primary);
  color: white;
  padding: var(--spacing-xs) var(--spacing-sm);
  border-radius: var(--border-radius-sm);
  font-size: var(--font-size-xs);
  font-weight: bold;
}

.product-card__content {
  flex: 1;
  padding: var(--spacing-md);
}

.product-card__title {
  margin: 0 0 var(--spacing-sm);
  font-size: var(--font-size-md);
  font-weight: bold;
  line-height: 1.4;
}

.product-card__link {
  color: inherit;
  text-decoration: none;
  
  &:hover {
    color: var(--color-primary);
  }
}

.product-card__description {
  margin: 0 0 var(--spacing-md);
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
  line-height: 1.5;
}

.product-card__price {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-sm);
}

.product-card__original-price {
  color: var(--color-text-secondary);
  text-decoration: line-through;
  font-size: var(--font-size-sm);
}

.product-card__current-price {
  color: var(--color-primary);
  font-weight: bold;
  font-size: var(--font-size-lg);
}

.product-card__discount {
  background: var(--color-error);
  color: white;
  padding: var(--spacing-xs) var(--spacing-sm);
  border-radius: var(--border-radius-sm);
  font-size: var(--font-size-xs);
  font-weight: bold;
}

.product-card__rating {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  margin-bottom: var(--spacing-md);
}

.product-card__rating-text {
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
}

.product-card__actions {
  display: flex;
  gap: var(--spacing-sm);
  padding: var(--spacing-md);
  border-top: 1px solid var(--color-border);
}

.product-card__cart-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-xs);
  padding: var(--spacing-sm) var(--spacing-md);
  background: var(--color-primary);
  color: white;
  border: none;
  border-radius: var(--border-radius-sm);
  font-weight: bold;
  cursor: pointer;
  transition: background-color 0.3s ease;
  
  &:hover:not(:disabled) {
    background: var(--color-primary-dark);
  }
  
  &:disabled {
    background: var(--color-gray-400);
    cursor: not-allowed;
  }
}

.product-card__wishlist-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: transparent;
  border: 2px solid var(--color-border);
  border-radius: var(--border-radius-sm);
  cursor: pointer;
  transition: all 0.3s ease;
  
  &:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
  }
  
  &.is-active {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: white;
  }
}

// 响应式设计
@media (max-width: 768px) {
  .product-card {
    &--compact {
      .product-card__content {
        padding: var(--spacing-xs);
      }
    }
  }
  
  .product-card__actions {
    flex-direction: column;
    
    .product-card__wishlist-btn {
      width: 100%;
      height: 44px;
    }
  }
}
</style>

12.2 性能优化案例分析

12.2.1 大型电商平台优化案例

// 案例:某大型电商平台SSR优化实践
const ecommerceOptimization = {
  // 问题分析
  challenges: {
    initialLoad: {
      problem: '首屏加载时间过长(>3秒)',
      causes: [
        '大量商品数据预取',
        '图片资源未优化',
        '第三方脚本阻塞',
        '服务端渲染性能瓶颈'
      ]
    },
    
    userExperience: {
      problem: '用户交互响应慢',
      causes: [
        'JavaScript包过大',
        '组件渲染性能差',
        '状态管理复杂',
        '内存泄漏问题'
      ]
    },
    
    seo: {
      problem: 'SEO效果不佳',
      causes: [
        '动态内容渲染不完整',
        'Meta信息缺失',
        '结构化数据不规范',
        '页面加载速度影响排名'
      ]
    }
  },
  
  // 优化方案
  solutions: {
    // 1. 服务端渲染优化
    serverOptimization: {
      // 组件级缓存
      componentCache: `
        // 实现组件级缓存
        const LRU = require('lru-cache')
        const cache = new LRU({ max: 1000, ttl: 1000 * 60 * 15 }) // 15分钟
        
        // 缓存包装器
        function createCacheWrapper(component) {
          return {
            ...component,
            serverCacheKey: (props) => {
              return \`\${component.name}::\${JSON.stringify(props)}\`
            },
            
            // 自定义缓存逻辑
            cache: {
              get: (key) => cache.get(key),
              set: (key, value) => cache.set(key, value),
              has: (key) => cache.has(key)
            }
          }
        }
      `,
      
      // 数据预取优化
      dataFetching: `
        // 智能数据预取
        async function optimizedAsyncData({ route, store, params }) {
          const cacheKey = \`page::\${route.path}\`
          
          // 检查缓存
          const cached = await store.dispatch('cache/get', cacheKey)
          if (cached && !cached.expired) {
            return cached.data
          }
          
          // 并行获取数据
          const [products, categories, user] = await Promise.all([
            store.dispatch('products/fetchList', { 
              page: params.page || 1,
              category: params.category 
            }),
            store.dispatch('categories/fetchAll'),
            store.dispatch('auth/fetchUser')
          ])
          
          const data = { products, categories, user }
          
          // 缓存结果
          await store.dispatch('cache/set', {
            key: cacheKey,
            data,
            ttl: 300 // 5分钟
          })
          
          return data
        }
      `
    },
    
    // 2. 客户端优化
    clientOptimization: {
      // 代码分割
      codeSplitting: `
        // 路由级代码分割
        const routes = [
          {
            path: '/',
            component: () => import('@/pages/Home.vue')
          },
          {
            path: '/products',
            component: () => import('@/pages/Products.vue'),
            children: [
              {
                path: ':id',
                component: () => import('@/pages/ProductDetail.vue')
              }
            ]
          },
          {
            path: '/cart',
            component: () => import('@/pages/Cart.vue')
          }
        ]
        
        // 组件级代码分割
        export default {
          components: {
            // 懒加载重型组件
            ProductRecommendations: () => import('@/components/ProductRecommendations.vue'),
            ReviewsList: () => import('@/components/ReviewsList.vue'),
            
            // 条件加载
            AdminPanel: () => {
              if (store.getters['auth/isAdmin']) {
                return import('@/components/AdminPanel.vue')
              }
              return Promise.resolve(null)
            }
          }
        }
      `,
      
      // 图片优化
      imageOptimization: `
        // 响应式图片组件
        <template>
          <picture class="responsive-image">
            <!-- WebP格式 -->
            <source 
              :srcset="webpSrcset" 
              type="image/webp"
            >
            
            <!-- 回退格式 -->
            <img
              :src="fallbackSrc"
              :srcset="srcset"
              :sizes="sizes"
              :alt="alt"
              :loading="loading"
              @load="onLoad"
              @error="onError"
            >
          </picture>
        </template>
        
        <script>
        export default {
          props: {
            src: String,
            alt: String,
            sizes: String,
            loading: { type: String, default: 'lazy' }
          },
          
          computed: {
            srcset() {
              return \`
                \${this.src}?w=320 320w,
                \${this.src}?w=640 640w,
                \${this.src}?w=1024 1024w
              \`
            },
            
            webpSrcset() {
              return \`
                \${this.src}?w=320&f=webp 320w,
                \${this.src}?w=640&f=webp 640w,
                \${this.src}?w=1024&f=webp 1024w
              \`
            },
            
            fallbackSrc() {
              return \`\${this.src}?w=640\`
            }
          }
        }
        </script>
      `
    },
    
    // 3. 缓存策略
    cachingStrategy: {
      // 多级缓存架构
      architecture: `
        // CDN缓存配置
        const cdnConfig = {
          // 静态资源
          static: {
            pattern: '/assets/*',
            ttl: '1y',
            headers: {
              'Cache-Control': 'public, max-age=31536000, immutable'
            }
          },
          
          // 页面缓存
          pages: {
            pattern: '/',
            ttl: '5m',
            vary: ['Accept-Encoding', 'User-Agent'],
            headers: {
              'Cache-Control': 'public, max-age=300, s-maxage=300'
            }
          },
          
          // API缓存
          api: {
            pattern: '/api/*',
            ttl: '1m',
            headers: {
              'Cache-Control': 'public, max-age=60'
            }
          }
        }
        
        // 服务端缓存
        const serverCache = {
          // Redis缓存
          redis: {
            host: process.env.REDIS_HOST,
            port: process.env.REDIS_PORT,
            keyPrefix: 'ssr:',
            ttl: 300
          },
          
          // 内存缓存
          memory: {
            max: 1000,
            ttl: 60
          }
        }
      `
    }
  },
  
  // 优化结果
  results: {
    performance: {
      firstContentfulPaint: '从3.2s降至1.1s',
      largestContentfulPaint: '从4.8s降至2.3s',
      cumulativeLayoutShift: '从0.25降至0.05',
      firstInputDelay: '从180ms降至45ms'
    },
    
    business: {
      conversionRate: '提升23%',
      bounceRate: '降低18%',
      pageViews: '增加31%',
      searchRanking: '平均提升15个位置'
    },
    
    technical: {
      bundleSize: '减少42%',
      serverResponse: '提升65%',
      cacheHitRate: '达到85%',
      errorRate: '降低78%'
    }
  }
}

12.2.2 新闻媒体网站优化案例

// 案例:新闻媒体网站SSR优化
const newsWebsiteOptimization = {
  // 业务特点
  characteristics: {
    content: '大量文本内容,频繁更新',
    traffic: '高并发访问,流量波动大',
    seo: 'SEO要求极高,需要快速索引',
    performance: '首屏速度要求严格'
  },
  
  // 优化策略
  strategies: {
    // 1. 内容优化
    contentOptimization: {
      // 文章预渲染
      articlePrerendering: `
        // 文章静态化生成
        class ArticleGenerator {
          constructor(options) {
            this.options = options
            this.cache = new Map()
          }
          
          async generateArticle(articleId) {
            const cacheKey = \`article:\${articleId}\`
            
            // 检查缓存
            if (this.cache.has(cacheKey)) {
              const cached = this.cache.get(cacheKey)
              if (Date.now() - cached.timestamp < 300000) { // 5分钟
                return cached.html
              }
            }
            
            // 获取文章数据
            const article = await this.fetchArticle(articleId)
            
            // 渲染HTML
            const html = await this.renderArticleHTML(article)
            
            // 缓存结果
            this.cache.set(cacheKey, {
              html,
              timestamp: Date.now()
            })
            
            return html
          }
          
          async renderArticleHTML(article) {
            const app = createApp({
              components: { ArticlePage },
              data: () => ({ article })
            })
            
            return await renderToString(app)
          }
        }
      `,
      
      // 图片懒加载
      imageLazyLoading: `
        // 智能图片加载
        class SmartImageLoader {
          constructor() {
            this.observer = null
            this.images = new Set()
            this.init()
          }
          
          init() {
            if ('IntersectionObserver' in window) {
              this.observer = new IntersectionObserver(
                this.handleIntersection.bind(this),
                {
                  rootMargin: '50px 0px',
                  threshold: 0.1
                }
              )
            }
          }
          
          observe(img) {
            if (this.observer) {
              this.observer.observe(img)
              this.images.add(img)
            } else {
              // 回退方案
              this.loadImage(img)
            }
          }
          
          handleIntersection(entries) {
            entries.forEach(entry => {
              if (entry.isIntersecting) {
                this.loadImage(entry.target)
                this.observer.unobserve(entry.target)
                this.images.delete(entry.target)
              }
            })
          }
          
          loadImage(img) {
            const src = img.dataset.src
            if (src) {
              img.src = src
              img.classList.add('loaded')
            }
          }
        }
      `
    },
    
    // 2. 缓存策略
    cachingStrategy: {
      // 分层缓存
      layeredCaching: `
        // 缓存层级配置
        const cacheConfig = {
          // L1: CDN缓存
          cdn: {
            articles: {
              pattern: '/articles/*',
              ttl: '1h',
              purgeOnUpdate: true
            },
            
            static: {
              pattern: '/static/*',
              ttl: '1d'
            }
          },
          
          // L2: 应用缓存
          application: {
            articles: {
              strategy: 'lru',
              maxSize: 1000,
              ttl: 900 // 15分钟
            },
            
            categories: {
              strategy: 'memory',
              ttl: 3600 // 1小时
            }
          },
          
          // L3: 数据库缓存
          database: {
            queries: {
              strategy: 'redis',
              ttl: 300 // 5分钟
            }
          }
        }
      `,
      
      // 智能缓存失效
      cacheInvalidation: `
        // 缓存失效策略
        class CacheInvalidator {
          constructor(cacheManager) {
            this.cache = cacheManager
            this.dependencies = new Map()
          }
          
          // 注册依赖关系
          addDependency(key, dependencies) {
            this.dependencies.set(key, dependencies)
          }
          
          // 失效缓存
          async invalidate(key) {
            // 直接失效
            await this.cache.delete(key)
            
            // 级联失效
            const dependents = this.findDependents(key)
            for (const dependent of dependents) {
              await this.cache.delete(dependent)
            }
            
            // 通知CDN
            await this.purgeCDN(key)
          }
          
          findDependents(key) {
            const dependents = []
            
            for (const [cacheKey, deps] of this.dependencies) {
              if (deps.includes(key)) {
                dependents.push(cacheKey)
              }
            }
            
            return dependents
          }
          
          async purgeCDN(key) {
            // 调用CDN API清除缓存
            try {
              await fetch('/api/cdn/purge', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ keys: [key] })
              })
            } catch (error) {
              console.error('CDN purge failed:', error)
            }
          }
        }
      `
    }
  },
  
  // 监控指标
  monitoring: {
    performance: {
      'Core Web Vitals': {
        LCP: '< 2.5s',
        FID: '< 100ms',
        CLS: '< 0.1'
      },
      
      'Custom Metrics': {
        'Article Load Time': '< 1.5s',
        'Search Response': '< 500ms',
        'Comment Load': '< 800ms'
      }
    },
    
    business: {
      'User Engagement': {
        'Bounce Rate': '< 40%',
        'Time on Page': '> 2min',
        'Pages per Session': '> 3'
      },
      
      'SEO Performance': {
        'Crawl Rate': '> 95%',
        'Index Coverage': '> 98%',
        'Search Visibility': 'Trending up'
      }
    }
  }
}

12.3 常见问题与解决方案

12.3.1 开发阶段常见问题

// 常见问题解决方案集合
const commonIssues = {
  // 1. 环境差异问题
  environmentDifferences: {
    problem: '服务端和客户端环境差异导致的问题',
    
    solutions: {
      // 浏览器API检查
      browserAPICheck: `
        // 安全的浏览器API使用
        function safelyUseBrowserAPI(callback) {
          if (typeof window !== 'undefined') {
            return callback()
          }
          return null
        }
        
        // 示例:安全使用localStorage
        const storage = {
          get(key) {
            return safelyUseBrowserAPI(() => {
              try {
                return JSON.parse(localStorage.getItem(key))
              } catch {
                return null
              }
            })
          },
          
          set(key, value) {
            return safelyUseBrowserAPI(() => {
              try {
                localStorage.setItem(key, JSON.stringify(value))
                return true
              } catch {
                return false
              }
            })
          }
        }
      `,
      
      // 通用工具函数
      universalUtils: `
        // 环境检测工具
        export const env = {
          isServer: typeof window === 'undefined',
          isClient: typeof window !== 'undefined',
          isDev: process.env.NODE_ENV === 'development',
          isProd: process.env.NODE_ENV === 'production'
        }
        
        // 通用事件处理
        export function addEventListener(element, event, handler, options) {
          if (env.isClient && element && element.addEventListener) {
            element.addEventListener(event, handler, options)
            
            // 返回清理函数
            return () => {
              element.removeEventListener(event, handler, options)
            }
          }
          
          return () => {} // 空清理函数
        }
      `
    }
  },
  
  // 2. 状态同步问题
  stateSynchronization: {
    problem: '服务端和客户端状态不一致',
    
    solutions: {
      // 状态序列化
      stateSerialization: `
        // 安全的状态序列化
        class StateSerializer {
          static serialize(state) {
            try {
              // 移除不可序列化的属性
              const cleanState = this.cleanState(state)
              return JSON.stringify(cleanState)
            } catch (error) {
              console.error('State serialization failed:', error)
              return '{}'
            }
          }
          
          static deserialize(stateString) {
            try {
              return JSON.parse(stateString)
            } catch (error) {
              console.error('State deserialization failed:', error)
              return {}
            }
          }
          
          static cleanState(obj, seen = new WeakSet()) {
            if (obj === null || typeof obj !== 'object') {
              return obj
            }
            
            // 防止循环引用
            if (seen.has(obj)) {
              return '[Circular]'
            }
            seen.add(obj)
            
            if (Array.isArray(obj)) {
              return obj.map(item => this.cleanState(item, seen))
            }
            
            const cleaned = {}
            for (const [key, value] of Object.entries(obj)) {
              // 跳过函数和Symbol
              if (typeof value === 'function' || typeof value === 'symbol') {
                continue
              }
              
              // 跳过DOM元素
              if (value && value.nodeType) {
                continue
              }
              
              cleaned[key] = this.cleanState(value, seen)
            }
            
            return cleaned
          }
        }
      `,
      
      // 状态验证
      stateValidation: `
        // 状态一致性验证
        function validateStateConsistency(serverState, clientState) {
          const issues = []
          
          function compareObjects(server, client, path = '') {
            if (typeof server !== typeof client) {
              issues.push({
                path,
                issue: 'type_mismatch',
                server: typeof server,
                client: typeof client
              })
              return
            }
            
            if (server === null || client === null) {
              if (server !== client) {
                issues.push({
                  path,
                  issue: 'null_mismatch',
                  server,
                  client
                })
              }
              return
            }
            
            if (typeof server === 'object') {
              const serverKeys = Object.keys(server)
              const clientKeys = Object.keys(client)
              
              // 检查缺失的键
              const missingInClient = serverKeys.filter(key => !clientKeys.includes(key))
              const missingInServer = clientKeys.filter(key => !serverKeys.includes(key))
              
              missingInClient.forEach(key => {
                issues.push({
                  path: path ? \`\${path}.\${key}\` : key,
                  issue: 'missing_in_client',
                  value: server[key]
                })
              })
              
              missingInServer.forEach(key => {
                issues.push({
                  path: path ? \`\${path}.\${key}\` : key,
                  issue: 'missing_in_server',
                  value: client[key]
                })
              })
              
              // 递归比较共同的键
              const commonKeys = serverKeys.filter(key => clientKeys.includes(key))
              commonKeys.forEach(key => {
                compareObjects(
                  server[key],
                  client[key],
                  path ? \`\${path}.\${key}\` : key
                )
              })
            } else if (server !== client) {
              issues.push({
                path,
                issue: 'value_mismatch',
                server,
                client
              })
            }
          }
          
          compareObjects(serverState, clientState)
          return issues
        }
      `
    }
  },
  
  // 3. 内存泄漏问题
  memoryLeaks: {
    problem: '长时间运行导致的内存泄漏',
    
    solutions: {
      // 内存监控
      memoryMonitoring: `
        // 内存使用监控
        class MemoryMonitor {
          constructor(options = {}) {
            this.options = {
              interval: 30000, // 30秒
              threshold: 0.8, // 80%
              ...options
            }
            
            this.measurements = []
            this.isMonitoring = false
          }
          
          start() {
            if (this.isMonitoring) return
            
            this.isMonitoring = true
            this.intervalId = setInterval(() => {
              this.measure()
            }, this.options.interval)
          }
          
          stop() {
            if (this.intervalId) {
              clearInterval(this.intervalId)
              this.intervalId = null
            }
            this.isMonitoring = false
          }
          
          measure() {
            if (typeof process !== 'undefined' && process.memoryUsage) {
              const usage = process.memoryUsage()
              const measurement = {
                timestamp: Date.now(),
                heapUsed: usage.heapUsed,
                heapTotal: usage.heapTotal,
                external: usage.external,
                rss: usage.rss,
                utilization: usage.heapUsed / usage.heapTotal
              }
              
              this.measurements.push(measurement)
              
              // 保留最近100次测量
              if (this.measurements.length > 100) {
                this.measurements.shift()
              }
              
              // 检查内存使用率
              if (measurement.utilization > this.options.threshold) {
                this.handleHighMemoryUsage(measurement)
              }
            }
          }
          
          handleHighMemoryUsage(measurement) {
            console.warn('High memory usage detected:', {
              utilization: \`\${(measurement.utilization * 100).toFixed(2)}%\`,
              heapUsed: \`\${(measurement.heapUsed / 1024 / 1024).toFixed(2)}MB\`,
              heapTotal: \`\${(measurement.heapTotal / 1024 / 1024).toFixed(2)}MB\`
            })
            
            // 触发垃圾回收(如果可用)
            if (global.gc) {
              global.gc()
            }
          }
          
          getReport() {
            if (this.measurements.length === 0) return null
            
            const latest = this.measurements[this.measurements.length - 1]
            const oldest = this.measurements[0]
            
            return {
              current: latest,
              trend: {
                heapGrowth: latest.heapUsed - oldest.heapUsed,
                timespan: latest.timestamp - oldest.timestamp
              },
              average: {
                utilization: this.measurements.reduce((sum, m) => sum + m.utilization, 0) / this.measurements.length
              }
            }
          }
        }
      `,
      
      // 资源清理
      resourceCleanup: `
        // 资源清理管理器
        class ResourceManager {
          constructor() {
            this.resources = new Set()
            this.cleanupTasks = new Map()
          }
          
          // 注册资源
          register(resource, cleanup) {
            this.resources.add(resource)
            if (cleanup) {
              this.cleanupTasks.set(resource, cleanup)
            }
          }
          
          // 注销资源
          unregister(resource) {
            const cleanup = this.cleanupTasks.get(resource)
            if (cleanup) {
              try {
                cleanup()
              } catch (error) {
                console.error('Resource cleanup failed:', error)
              }
              this.cleanupTasks.delete(resource)
            }
            this.resources.delete(resource)
          }
          
          // 清理所有资源
          cleanup() {
            for (const resource of this.resources) {
              this.unregister(resource)
            }
          }
          
          // 获取资源统计
          getStats() {
            return {
              totalResources: this.resources.size,
              withCleanup: this.cleanupTasks.size
            }
          }
        }
        
        // Vue组件中的使用示例
        export default {
          setup() {
            const resourceManager = new ResourceManager()
            
            onMounted(() => {
              // 注册定时器
              const timer = setInterval(() => {
                // 定时任务
              }, 1000)
              
              resourceManager.register(timer, () => {
                clearInterval(timer)
              })
              
              // 注册事件监听器
              const handleResize = () => {
                // 处理窗口大小变化
              }
              
              window.addEventListener('resize', handleResize)
              resourceManager.register('resize-listener', () => {
                window.removeEventListener('resize', handleResize)
              })
            })
            
            onUnmounted(() => {
              resourceManager.cleanup()
            })
            
            return {
              resourceManager
            }
          }
        }
      `
    }
  }
}

12.3.2 生产环境问题排查

// 生产环境问题诊断工具
const productionDiagnostics = {
  // 性能问题诊断
  performanceDiagnostics: {
    // 慢查询检测
    slowQueryDetection: `
      // 慢查询监控
      class SlowQueryMonitor {
        constructor(options = {}) {
          this.threshold = options.threshold || 1000 // 1秒
          this.queries = []
          this.maxQueries = options.maxQueries || 100
        }
        
        // 包装查询函数
        wrapQuery(queryFn, queryName) {
          return async (...args) => {
            const startTime = Date.now()
            
            try {
              const result = await queryFn(...args)
              const duration = Date.now() - startTime
              
              this.recordQuery({
                name: queryName,
                duration,
                success: true,
                args: this.sanitizeArgs(args),
                timestamp: startTime
              })
              
              if (duration > this.threshold) {
                this.handleSlowQuery(queryName, duration, args)
              }
              
              return result
            } catch (error) {
              const duration = Date.now() - startTime
              
              this.recordQuery({
                name: queryName,
                duration,
                success: false,
                error: error.message,
                args: this.sanitizeArgs(args),
                timestamp: startTime
              })
              
              throw error
            }
          }
        }
        
        recordQuery(query) {
          this.queries.push(query)
          
          // 保持队列大小
          if (this.queries.length > this.maxQueries) {
            this.queries.shift()
          }
        }
        
        handleSlowQuery(name, duration, args) {
          console.warn(\`Slow query detected: \${name} took \${duration}ms\`, {
            args: this.sanitizeArgs(args)
          })
          
          // 发送到监控系统
          this.sendToMonitoring({
            type: 'slow_query',
            name,
            duration,
            timestamp: Date.now()
          })
        }
        
        sanitizeArgs(args) {
          return args.map(arg => {
            if (typeof arg === 'object' && arg !== null) {
              // 移除敏感信息
              const sanitized = { ...arg }
              delete sanitized.password
              delete sanitized.token
              delete sanitized.secret
              return sanitized
            }
            return arg
          })
        }
        
        getReport() {
          const slowQueries = this.queries.filter(q => q.duration > this.threshold)
          const avgDuration = this.queries.reduce((sum, q) => sum + q.duration, 0) / this.queries.length
          
          return {
            total: this.queries.length,
            slow: slowQueries.length,
            avgDuration: Math.round(avgDuration),
            slowestQueries: slowQueries
              .sort((a, b) => b.duration - a.duration)
              .slice(0, 10)
          }
        }
        
        async sendToMonitoring(data) {
          try {
            await fetch('/api/monitoring/metrics', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify(data)
            })
          } catch (error) {
            console.error('Failed to send monitoring data:', error)
          }
        }
      }
    `,
    
    // 渲染性能分析
    renderingPerformance: `
      // 渲染性能分析器
      class RenderingProfiler {
        constructor() {
          this.profiles = new Map()
          this.isEnabled = process.env.NODE_ENV === 'development'
        }
        
        startProfile(componentName) {
          if (!this.isEnabled) return
          
          const profileId = \`\${componentName}_\${Date.now()}\`
          this.profiles.set(profileId, {
            componentName,
            startTime: performance.now(),
            phases: []
          })
          
          return profileId
        }
        
        markPhase(profileId, phaseName) {
          if (!this.isEnabled || !this.profiles.has(profileId)) return
          
          const profile = this.profiles.get(profileId)
          profile.phases.push({
            name: phaseName,
            timestamp: performance.now()
          })
        }
        
        endProfile(profileId) {
          if (!this.isEnabled || !this.profiles.has(profileId)) return
          
          const profile = this.profiles.get(profileId)
          profile.endTime = performance.now()
          profile.totalDuration = profile.endTime - profile.startTime
          
          // 计算各阶段耗时
          profile.phaseDurations = profile.phases.map((phase, index) => {
            const prevTime = index === 0 ? profile.startTime : profile.phases[index - 1].timestamp
            return {
              name: phase.name,
              duration: phase.timestamp - prevTime
            }
          })
          
          // 如果渲染时间过长,记录警告
          if (profile.totalDuration > 16) { // 超过一帧时间
            console.warn(\`Slow rendering detected: \${profile.componentName} took \${profile.totalDuration.toFixed(2)}ms\`, profile)
          }
          
          this.profiles.delete(profileId)
          return profile
        }
        
        // Vue组件混入
        createMixin() {
          return {
            beforeCreate() {
              this._profileId = this.$profiler?.startProfile(this.$options.name || 'Anonymous')
            },
            
            created() {
              this.$profiler?.markPhase(this._profileId, 'created')
            },
            
            beforeMount() {
              this.$profiler?.markPhase(this._profileId, 'beforeMount')
            },
            
            mounted() {
              this.$profiler?.markPhase(this._profileId, 'mounted')
              this.$profiler?.endProfile(this._profileId)
            }
          }
        }
      }
    `
  },
  
  // 错误追踪
  errorTracking: {
    // 错误聚合分析
    errorAggregation: `
      // 错误聚合器
      class ErrorAggregator {
        constructor(options = {}) {
          this.errors = new Map()
          this.maxErrors = options.maxErrors || 1000
          this.reportInterval = options.reportInterval || 60000 // 1分钟
          
          this.startReporting()
        }
        
        addError(error) {
          const signature = this.getErrorSignature(error)
          
          if (this.errors.has(signature)) {
            const existing = this.errors.get(signature)
            existing.count++
            existing.lastOccurrence = Date.now()
            existing.occurrences.push({
              timestamp: Date.now(),
              url: error.url,
              userAgent: error.userAgent
            })
            
            // 限制occurrence记录数量
            if (existing.occurrences.length > 10) {
              existing.occurrences.shift()
            }
          } else {
            this.errors.set(signature, {
              signature,
              message: error.message,
              stack: error.stack,
              count: 1,
              firstOccurrence: Date.now(),
              lastOccurrence: Date.now(),
              occurrences: [{
                timestamp: Date.now(),
                url: error.url,
                userAgent: error.userAgent
              }]
            })
          }
          
          // 限制错误总数
          if (this.errors.size > this.maxErrors) {
            const oldestSignature = this.errors.keys().next().value
            this.errors.delete(oldestSignature)
          }
        }
        
        getErrorSignature(error) {
          // 生成错误签名用于聚合
          const stack = error.stack || ''
          const message = error.message || ''
          
          // 提取关键信息
          const stackLines = stack.split('\n').slice(0, 3) // 前3行堆栈
          const normalizedStack = stackLines
            .map(line => line.replace(/:\d+:\d+/g, ':*:*')) // 移除行号
            .join('\n')
          
          return `${message}|${normalizedStack}`
        }
        
        startReporting() {
          setInterval(() => {
            this.sendReport()
          }, this.reportInterval)
        }
        
        async sendReport() {
          if (this.errors.size === 0) return
          
          const report = {
            timestamp: Date.now(),
            errors: Array.from(this.errors.values())
              .sort((a, b) => b.count - a.count) // 按频率排序
              .slice(0, 50) // 最多50个错误类型
          }
          
          try {
            await fetch('/api/errors/report', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify(report)
            })
            
            // 清空已报告的错误
            this.errors.clear()
          } catch (error) {
            console.error('Failed to send error report:', error)
          }
        }
        
        getTopErrors(limit = 10) {
          return Array.from(this.errors.values())
            .sort((a, b) => b.count - a.count)
            .slice(0, limit)
        }
      }
    `
  }
}

## 12.4 团队协作与工作流

### 12.4.1 开发工作流规范

```javascript
// Git工作流配置
const gitWorkflow = {
  // 分支策略
  branchStrategy: {
    main: '生产环境分支,只接受来自release的合并',
    develop: '开发主分支,集成所有功能',
    feature: 'feature/功能名称,从develop分出',
    release: 'release/版本号,从develop分出用于发布准备',
    hotfix: 'hotfix/问题描述,从main分出用于紧急修复'
  },
  
  // 提交规范
  commitConvention: {
    format: 'type(scope): description',
    types: {
      feat: '新功能',
      fix: '修复bug',
      docs: '文档更新',
      style: '代码格式调整',
      refactor: '重构',
      perf: '性能优化',
      test: '测试相关',
      chore: '构建或工具相关'
    },
    examples: [
      'feat(auth): add user login functionality',
      'fix(ssr): resolve hydration mismatch issue',
      'perf(cache): optimize component caching strategy'
    ]
  },
  
  // 代码审查清单
  reviewChecklist: [
    '代码符合项目规范',
    '功能实现正确',
    '性能影响评估',
    '安全性检查',
    '测试覆盖充分',
    'SSR兼容性确认',
    '文档更新完整'
  ]
}

12.4.2 CI/CD流水线

# .github/workflows/ci-cd.yml
name: Vue SSR CI/CD Pipeline

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [16.x, 18.x]
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run linting
      run: npm run lint
    
    - name: Run type checking
      run: npm run type-check
    
    - name: Run unit tests
      run: npm run test:unit
    
    - name: Run integration tests
      run: npm run test:integration
    
    - name: Build application
      run: npm run build
    
    - name: Run E2E tests
      run: npm run test:e2e
    
    - name: Upload coverage reports
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage/lcov.info
  
  security:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Run security audit
      run: npm audit --audit-level high
    
    - name: Run dependency check
      uses: dependency-check/Dependency-Check_Action@main
      with:
        project: 'vue-ssr-app'
        path: '.'
        format: 'HTML'
  
  deploy-staging:
    needs: [test, security]
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/develop'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18.x'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Build for staging
      run: npm run build:staging
      env:
        NODE_ENV: staging
        API_BASE_URL: ${{ secrets.STAGING_API_URL }}
    
    - name: Deploy to staging
      run: |
        echo "Deploying to staging environment"
        # 部署脚本
  
  deploy-production:
    needs: [test, security]
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18.x'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Build for production
      run: npm run build:production
      env:
        NODE_ENV: production
        API_BASE_URL: ${{ secrets.PRODUCTION_API_URL }}
    
    - name: Deploy to production
      run: |
        echo "Deploying to production environment"
        # 生产部署脚本

12.5 未来发展趋势

12.5.1 Vue 3与Composition API

// Vue 3 SSR最佳实践
const vue3SSRBestPractices = {
  // Composition API在SSR中的应用
  compositionAPI: {
    // 数据获取组合函数
    useAsyncData: `
      // composables/useAsyncData.js
      import { ref, onServerPrefetch } from 'vue'
      
      export function useAsyncData(key, fetcher) {
        const data = ref(null)
        const error = ref(null)
        const pending = ref(false)
        
        const execute = async () => {
          pending.value = true
          error.value = null
          
          try {
            data.value = await fetcher()
          } catch (err) {
            error.value = err
          } finally {
            pending.value = false
          }
        }
        
        // 服务端预取
        onServerPrefetch(execute)
        
        // 客户端执行(如果服务端没有数据)
        if (process.client && !data.value) {
          execute()
        }
        
        return {
          data: readonly(data),
          error: readonly(error),
          pending: readonly(pending),
          refresh: execute
        }
      }
    `,
    
    // 状态管理组合函数
    useStore: `
      // composables/useStore.js
      import { inject, provide } from 'vue'
      
      const StoreSymbol = Symbol('store')
      
      export function provideStore(store) {
        provide(StoreSymbol, store)
      }
      
      export function useStore() {
        const store = inject(StoreSymbol)
        if (!store) {
          throw new Error('Store not provided')
        }
        return store
      }
      
      // 使用示例
      export default {
        setup() {
          const store = useStore()
          
          const { data: products } = useAsyncData('products', () => {
            return store.dispatch('products/fetchList')
          })
          
          return {
            products
          }
        }
      }
    `
  },
  
  // Suspense组件
  suspenseComponent: {
    usage: `
      <!-- 使用Suspense处理异步组件 -->
      <template>
        <div class="app">
          <Suspense>
            <template #default>
              <AsyncProductList />
            </template>
            
            <template #fallback>
              <div class="loading">
                <LoadingSpinner />
                <p>加载商品列表中...</p>
              </div>
            </template>
          </Suspense>
        </div>
      </template>
      
      <script>
      import { defineAsyncComponent } from 'vue'
      import LoadingSpinner from '@/components/LoadingSpinner.vue'
      
      export default {
        components: {
          LoadingSpinner,
          AsyncProductList: defineAsyncComponent(() => 
            import('@/components/ProductList.vue')
          )
        }
      }
      </script>
    `
  }
}

12.5.2 边缘计算与CDN

// 边缘计算SSR实现
const edgeSSR = {
  // Cloudflare Workers实现
  cloudflareWorkers: `
    // worker.js
    import { createApp } from './app'
    import { renderToString } from '@vue/server-renderer'
    
    export default {
      async fetch(request, env, ctx) {
        const url = new URL(request.url)
        
        // 静态资源直接返回
        if (url.pathname.startsWith('/assets/')) {
          return env.ASSETS.fetch(request)
        }
        
        try {
          // 创建Vue应用实例
          const { app, router } = createApp()
          
          // 设置路由
          await router.push(url.pathname)
          await router.isReady()
          
          // 渲染HTML
          const html = await renderToString(app)
          
          // 生成完整页面
          const fullHtml = \`
            <!DOCTYPE html>
            <html>
              <head>
                <meta charset="utf-8">
                <title>Vue SSR App</title>
                <link rel="stylesheet" href="/assets/style.css">
              </head>
              <body>
                <div id="app">\${html}</div>
                <script src="/assets/client.js"></script>
              </body>
            </html>
          \`
          
          return new Response(fullHtml, {
            headers: {
              'Content-Type': 'text/html;charset=UTF-8',
              'Cache-Control': 'public, max-age=300'
            }
          })
        } catch (error) {
          return new Response('Internal Server Error', {
            status: 500
          })
        }
      }
    }
  `,
  
  // Vercel Edge Functions
  vercelEdge: `
    // api/ssr.js
    import { createApp } from '../app'
    import { renderToString } from '@vue/server-renderer'
    
    export const config = {
      runtime: 'edge'
    }
    
    export default async function handler(request) {
      const url = new URL(request.url)
      
      try {
        const { app, router } = createApp()
        
        await router.push(url.pathname)
        await router.isReady()
        
        const html = await renderToString(app)
        
        return new Response(html, {
          headers: {
            'Content-Type': 'text/html;charset=UTF-8'
          }
        })
      } catch (error) {
        return new Response('Error', { status: 500 })
      }
    }
  `
}

12.6 本章小结

本章全面总结了Vue SSR的最佳实践与案例分析,包括:

核心要点

  1. 最佳实践总结

    • 架构设计原则
    • 代码规范与约定
    • 组件设计模式
  2. 性能优化案例

    • 大型电商平台优化
    • 新闻媒体网站优化
    • 实际效果分析
  3. 问题解决方案

    • 开发阶段常见问题
    • 生产环境问题排查
    • 系统性解决方案
  4. 团队协作

    • 开发工作流规范
    • CI/CD流水线
    • 代码质量保证
  5. 未来发展趋势

    • Vue 3与Composition API
    • 边缘计算与CDN
    • 技术演进方向

最佳实践

  1. 架构设计

    • 遵循单一职责原则
    • 合理的目录结构
    • 模块化设计
  2. 性能优化

    • 多级缓存策略
    • 智能代码分割
    • 资源优化
  3. 开发效率

    • 统一的代码规范
    • 自动化工作流
    • 完善的测试体系
  4. 团队协作

    • 清晰的分支策略
    • 规范的提交格式
    • 有效的代码审查

学习建议

  1. 持续学习

    • 关注Vue生态发展
    • 学习新的优化技术
    • 参与社区讨论
  2. 实践应用

    • 在实际项目中应用
    • 总结经验教训
    • 分享最佳实践
  3. 性能监控

    • 建立监控体系
    • 定期性能分析
    • 持续优化改进

通过本教程的学习,你应该已经掌握了Vue SSR的核心概念、实现方法、优化技巧和最佳实践。希望这些知识能够帮助你在实际项目中构建高性能、可维护的Vue SSR应用。

结语

Vue SSR是一个强大的技术,它能够显著提升应用的性能和SEO效果。但同时,它也带来了额外的复杂性。在选择是否使用SSR时,需要根据项目的具体需求进行权衡。

记住,技术是为业务服务的。选择合适的技术方案,并持续优化和改进,才能真正发挥Vue SSR的价值。

祝你在Vue SSR的学习和实践中取得成功!