进阶指南

性能优化

构建体积优化、渲染速度优化、CSS 优化、开发服务器性能与实际优化案例

模板项目的性能优化涉及构建体积、渲染速度、CSS 大小和开发体验。本页讲解实用优化技巧和实际案例。

构建体积优化

Tree-shaking

确保只打包使用的代码:

karin.template.ts
export default ({
  : {
    : {
      : {
        : {
          : false // 移除无副作用的未使用代码
        }
      }
    }
  }
})

具名导入而非全量导入

// ✅ 好:tree-shakable
import { ,  } from '@heroui/react'

export const  = <>好的写法</>
// ❌ 差:命名空间导入,打包器无法 tree-shake,整库进产物
import * as  from '@heroui/react'

export const  = <.>差的写法</.>

动态导入

大组件或第三方库按需加载:

ktr/template/chart/stats/index.tsx
import { , type  } from '@karinjs/template-react'
import { ,  } from 'react'

// 懒加载图表库
const  = (() => import('react-chartjs-2').(() => ({ : . })))

interface StatsData {
  : string[]
  : number[]
}

const  = ({  }: <StatsData>) => (
  < ={<>加载中...</>}>
    < ={{ : ., : [{ : . }] }} />
  </>
)

export default ({
  : 
})

依赖分析

使用 rollup-plugin-visualizer 查看打包体积:

karin.template.ts
export default ({
  : ({  }) =>
     === 'build'
      ? {
          : [
            ({
              : 'dist/stats.html',
              : true,
              : true,
              : true
            })
          ]
        }
      : {}
})

外部化依赖

生产环境不打包 React(假设运行时已提供):

vite.config.ts
export default ({
  : {
    : {
      : ['react', 'react-dom', 'react/jsx-runtime'],
      : {
        : {
          : 'React',
          'react-dom': 'ReactDOM'
        }
      }
    }
  }
})

压缩优化

karin.template.ts
export default ({
  : {
    : [
      ({
        : 'brotliCompress',
        : '.br',
        : 1024 // 只压缩 > 1KB 的文件
      })
    ],
    : {
      : 'esbuild',
      : 'lightningcss'
    }
  }
})

渲染速度优化

组件懒加载

仅在使用时加载组件:

ktr/template/dashboard/index.tsx
import { , type  } from '@karinjs/template-react'
import { ,  } from 'react'

const  = (() => import('../../components/HeavyChart'))
const  = (() => import('../../components/HeavyTable'))

interface DashboardData {
  : boolean
  : boolean
}

const  = ({  }: <DashboardData>) => (
  <>
    {. && (
      < ={<>加载图表...</>}>
        < />
      </>
    )}
    {. && (
      < ={<>加载表格...</>}>
        < />
      </>
    )}
  </>
)

export default ({
  : 
})

React.memo 避免重渲染

ktr/template/components/UserCard.tsx
import React from 'react'

interface UserCardProps {
  : string
  : string
}

export const  = React.<UserCardProps>(({ ,  }) => {
  .('UserCard 渲染')

  return (
    < ="flex items-center gap-3">
      < ={} ={} ="size-12 rounded-full" />
      < ="font-medium">{}</>
    </>
  )
})

useMemo 缓存计算

import {  } from 'react'

interface Item {
  : number
}
interface Props {
  : Item[]
}

function ({  }: Props) {
  const  = (() => {
    .('计算总分')
    return .((, ) =>  + ., 0)
  }, [])

  return <>总分: {}</>
}

虚拟列表

长列表使用 react-window:

ktr/template/user/list/index.tsx
import { , type  } from '@karinjs/template-react'
import { , type  } from 'react-window'

interface User {
  : string
  : string
}

interface ListData {
  : User[]
}

const  = ({ , ,  }: <{ : User[] }>) => (
  < ={} ="px-4 py-2 border-b">
    {[].}
  </>
)

const  = ({  }: <ListData>) => (
  < ={} ={..} ={48} ={{ : . }} ={{ : 600 }} />
)

export default ({
  : 
})

图片优化

使用现代图片格式和懒加载:

import React from 'react'

const : React.<{ : string; : string }> = ({ ,  }) => (
  <>
    < ={`${}?format=avif`} ="image/avif" />
    < ={`${}?format=webp`} ="image/webp" />
    < ={} ={} ="lazy" ="async" ="w-full" />
  </>
)

CSS 优化

按需生成 Tailwind

只打包使用的类名:

ktr/template/style.css
@import 'tailwindcss';
@import '@karinjs/template-react/styles';

/* 限制扫描范围 */
@source '../ktr/template';

/* 或手动指定 */
@source '../ktr/template/**/*.tsx';

PurgeCSS 移除未使用样式

karin.template.ts
export default ({
  : {
    : {
      : {
        : [
          ({
            : ['./ktr/template/**/*.{tsx,ts}'],
            : [/^bg-/, /^text-/, /^hover:/] // 保留动态类名
          })
        ]
      }
    }
  }
})

CSS 压缩

使用 Lightning CSS:

karin.template.ts
export default ({
  : {
    : {
      : 'lightningcss'
    },
    : {
      : 'lightningcss'
    }
  }
})

内联关键 CSS

小文件内联到 HTML:

import type { RenderPlugin } from '@karinjs/template-react'
import  from 'node:fs'

const : RenderPlugin = {
  : 'inline-critical-css',
  : () => {
    const  = .('dist/critical.css', 'utf-8')
    // afterRender 拿到的是包装前的模板片段,直接把 <style> 拼到片段前
    return `<style>${}</style>\n${.}`
  }
}

拆分 CSS

按模板拆分 CSS 文件:

karin.template.ts
export default ({
  : {
    : {
      : true // 每个入口生成独立 CSS
    }
  }
})

开发服务器性能

预构建依赖

加速首次启动:

karin.template.ts
export default ({
  : {
    : {
      : ['react', 'react-dom', '@heroui/react', 'framer-motion']
    }
  }
})

减少文件监听

排除不必要的目录:

karin.template.ts
export default ({
  : {
    : {
      : {
        : ['**/node_modules/**', '**/dist/**', '**/.git/**', '**/coverage/**']
      }
    }
  }
})

HMR 优化

限制热更新边界:

ktr/template/user/card/index.tsx
import {  } from '@karinjs/template-react'

const  = () => <>User Card</>

export default ({
  : 
})

// HMR 边界
if (import.meta.) {
  import.meta..()
}

并发限制

控制并发请求数:

karin.template.ts
export default ({
  : {
    : {
      : {
        : true
      },
      : true
    }
  }
})

实际优化案例

案例 1:减少首屏体积 70%

问题:首次加载需要下载 800KB JS。

优化

import {  } from '@karinjs/template-react'
import {  } from 'rollup-plugin-visualizer'

export default ({
  : {
    : [
      ({ : true }) // 1. 分析体积
    ],
    : {
      : {
        : {
          () {
            // 2. 拆分第三方库(vite 8 / rolldown 的 manualChunks 是函数形式)
            if (.('node_modules/react')) return 'vendor'
            if (.('@heroui')) return 'ui'
          }
        }
      }
    }
  }
})
import {  } from 'react'

// 3. 懒加载重组件
const  = (() => import('./HeavyChart'))

结果:首屏减少到 240KB。

案例 2:优化大列表渲染

问题:渲染 1000 个用户卡片卡顿。

优化

ktr/template/user/list/index.tsx
import { , type  } from '@karinjs/template-react'
import React from 'react'
import { , type  } from 'react-window'

interface User {
  : string
  : string
  : string
}

interface ListData {
  : User[]
}

// 1. memo 避免重渲染
const  = React.<{ : User }>(({  }) => (
  < ="flex items-center gap-3 px-4 py-2">
    < ={.} ="" ="size-10 rounded-full" />
    <>{.}</>
  </>
))

// 2. 虚拟列表
const  = ({ , ,  }: <{ : User[] }>) => (
  < ={}>
    < ={[]} />
  </>
)

const  = ({  }: <ListData>) => (
  < ={} ={..} ={56} ={{ : . }} ={{ : 600 }} />
)

export default ({
  : 
})

结果:渲染时间从 2.5s 降到 80ms。

案例 3:CSS 体积减少 60%

问题:Tailwind CSS 产物 350KB。

优化

ktr/template/style.css
/* 1. 样式基座整包引入:@karinjs/template-react/styles 已包含 HeroUI 语义色和 dark: 变体,
      不能再按 @heroui/theme/button 这种 v2 包路径分包导入 */
@import 'tailwindcss';
@import '@karinjs/template-react/styles';

/* 2. 限制扫描范围:Tailwind 只编译扫描到的类名,未使用的类不进产物 */
@source '../ktr/template';
karin.template.ts
import {  } from '@karinjs/template-react'

export default ({
  : {
    : {
      : 'lightningcss' // 3. 使用更好的压缩
    }
  }
})

结果:CSS 减少到 140KB。

案例 4:开发启动加速 3 倍

问题:开发服务器启动需要 12s。

优化

karin.template.ts
import {  } from '@karinjs/template-react'

export default ({
  : {
    // 1. 预构建常用依赖
    : {
      : ['react', 'react-dom', '@heroui/react', 'framer-motion', 'date-fns']
    },
    // 2. 减少监听范围
    : {
      : {
        : ['**/node_modules/**', '**/dist/**']
      }
    },
    // 3. 关闭不必要的功能
    : {
      : false
    }
  }
})

结果:启动时间降到 4s。

案例 5:SSR 渲染性能

问题:单个模板 SSR 渲染耗时 800ms。

优化

import { , type  } from '@karinjs/template-react'
import {  } from 'react'

interface Data {
  : <{ : string; : number }>
}

const  = ({  }: <Data>) => {
  // 1. 缓存计算结果
  const  = (() => [....].((, ) => . - .), [.])

  return (
    <>
      {.(() => (
        // 2. 使用 key 优化 reconciliation
        < ={.}>{.}</>
      ))}
    </>
  )
}

export default ({
  : 
})
import type { RenderPlugin } from '@karinjs/template-react'

// 3. 性能监控插件
const : RenderPlugin = {
  : 'perf',
  : () => {
    ;( as any).__startTime = .()
  },
  : () => {
    const  = .() - ( as any).__startTime
    if ( > 500) {
      .(`[慢渲染] ${.}: ${}ms`)
    }
  }
}

结果:渲染时间降到 120ms。

案例 6:图片优化

问题:模板包含大量高清图片,加载慢。

优化

import React from 'react'

// 1. 响应式图片
const : React.<{ : string; : string }> = ({ ,  }) => (
  <>
    < ={`${}?w=64&format=avif 1x, ${}?w=128&format=avif 2x`} ="image/avif" />
    < ={`${}?w=64&format=webp 1x, ${}?w=128&format=webp 2x`} ="image/webp" />
    < ={`${}?w=64`} ={} ="lazy" ="async" ="size-16 rounded-full" />
  </>
)
import type { RenderPlugin } from '@karinjs/template-react'
import  from 'node:fs'
import  from 'node:path'

// 2. 小图片内联(框架已内置该能力:html.assetsInlineLimit 默认 4096 字节,
//    需要更定制的规则时才用这种 afterRender 插件,比如按路径前缀区分阈值)
const : RenderPlugin = {
  : 'inline-small-images',
  : () => {
    return ..(/<img[^>]+src="\/assets\/([^"]+\.(?:png|jpg|svg))"[^>]*>/g, (, ) => {
      const  = .(., '../assets', )
      if (!.()) return 

      const  = .()
      if (. > 5120) return  // 只内联 < 5KB

      const  = .().(1)
      const  = .(, 'base64')
      return .(`src="/assets/${}"`, `src="data:image/${};base64,${}"`)
    })
  }
}

结果:图片加载时间减少 80%。

案例 7:减少重渲染

问题:父组件更新导致子组件不必要的重渲染。

优化

import React, {  } from 'react'

interface User {
  : string
  : string
}

// 1. memo + 原始值 props
const  = React.<{ : User }>(({  }) => {
  .('UserCard 渲染')
  return <>{.}</>
})

// 2. 回调使用 useCallback
const : React.<{ : User[] }> = ({  }) => {
  const [, ] = <string | null>(null)

  const  = React.((: string) => {
    ()
  }, [])

  return (
    <>
      {.(() => (
        < ={.} ={} />
      ))}
    </>
  )
}

结果:更新时只重渲染必要的组件。

案例 8:Monorepo 构建缓存

问题:Monorepo 每次全量构建耗时 5 分钟。

优化

turbo.json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", "lib/**"],
      "cache": true
    }
  }
}
# 使用 Turborepo 缓存
pnpm turbo build

# 或使用 Nx
pnpm nx run-many --target=build --all

结果:增量构建只需 30s。

性能监控

构建时监控

karin.template.ts
import {  } from '@karinjs/template-react'

export default ({
  : {
    : {
      : true, // 报告压缩后大小
      : 500 // 超过 500KB 警告
    }
  }
})

运行时监控

import type { RenderPlugin } from '@karinjs/template-react'
import  from 'node:fs'
import  from 'node:path'

const : RenderPlugin = {
  : 'metrics',
  : 'post',
  : async () => {
    const  = {
      : .,
      : ..,
      : .()
    }

    const  = .(., 'metrics.jsonl')
    await ..(, .() + '\n')
  }
}

性能预算

karin.template.ts
import {  } from '@karinjs/template-react'

export default ({
  : {
    : {
      : {
        : {
          : () => {
            // 检查文件大小
            if (.?.('.css')) {
              .(`CSS: ${.}`)
            }
            return 'assets/[name]-[hash][extname]'
          }
        }
      }
    }
  }
})

优化检查清单

构建优化

  • 启用 tree-shaking
  • 动态导入大组件
  • 分析打包体积
  • 外部化运行时依赖
  • 启用 Brotli 压缩
  • 拆分 vendor chunk
  • 移除 console 和 debugger

渲染优化

  • 使用 React.memo
  • useMemo 缓存计算
  • useCallback 稳定回调
  • 虚拟列表处理长列表
  • 懒加载非关键组件
  • 优化图片格式和大小
  • 避免内联大对象

CSS 优化

  • PurgeCSS 移除未使用样式
  • 限制 Tailwind 扫描范围
  • 使用 Lightning CSS
  • 内联关键 CSS
  • 按需导入组件库样式
  • 压缩 CSS

开发优化

  • 预构建依赖
  • 减少文件监听
  • HMR 边界优化
  • 关闭 sourcemap(生产)
  • 使用 SWC/esbuild

On this page