WebAssembly在前端工程中的实践:突破JavaScript性能瓶颈

引言 随着Web应用的复杂度不断提升,JavaScript在处理计算密集型任务时逐渐暴露出性能瓶颈。WebAssembly(Wasm)作为一种新型的二进制指令格式,为Web平台带来了接近原生的执行性能。本文将结合实际项目经验,深入探讨WebAssembly在前端工程中的应用实践。 WebAssembly的核心优势 1. 近原生执行性能 WebAssembly采用二进制格式,体积小、解析快,执行速度接近原生代码。以下是性能对比数据(基于斐波那契数列计算): 1 2 3 4 5 6 // JavaScript实现 function fibonacci(n) { return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); } // WebAssembly (Rust编译) 可提升10-50倍性能 2. 多语言支持 开发者可以使用Rust、C++、Go等多种语言编写Wasm模块: 1 2 3 4 5 6 7 8 9 // Rust实现斐波那契 #[wasm_bindgen] pub fn fibonacci(n: u32) -> u32 { match n { 0 => 0, 1 => 1, _ => fibonacci(n - 1) + fibonacci(n - 2), } } 3. 安全隔离 Wasm运行在沙箱环境中,内存隔离确保了安全性。 ...

SQL格式化与查询优化完全指南

深入讲解SQL格式化的最佳实践和查询优化技巧,帮助开发者编写高效、可读的SQL代码

WebAssembly 2025:从边缘技术到主流平台的跨越

引言 2025年是WebAssembly(WASM)走向成熟的关键一年。从实验性技术到主流平台,WASM正在重塑Web应用的边界。本文将深入分析WASM生态在2025年的重大突破,并展望2026年的发展方向。 一、WASM 2025技术突破 1.1 GC提案落地 垃圾回收支持 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 // 2025年WASM GC的实际应用 // 以前:手动管理内存,类似C语言 mod manual_memory { #[no_mangle] pub fn allocate_string(size: usize) -> *mut u8 { let layout = std::alloc::Layout::from_size_align(size, 1).unwrap(); unsafe { let ptr = std::alloc::alloc(layout); ptr as *mut u8 } } #[no_mangle] pub fn free_string(ptr: *mut u8, size: usize) { let layout = std::alloc::Layout::from_size_align(size, 1).unwrap(); unsafe { std::alloc::dealloc(ptr as *mut u8, layout); } } } // 现在:使用WASM GC,可以直接使用Rust的Vec、HashMap等 mod with_gc { use wasm_bindgen::prelude::*; #[wasm_bindgen] pub struct DataProcessor { // 可以直接使用集合类型 items: Vec<DataItem>, cache: HashMap<String, ProcessedData>, } #[wasm_bindgen] impl DataProcessor { #[wasm_bindgen(constructor)] pub fn new() -> Self { Self { items: Vec::new(), cache: HashMap::new(), } } #[wasm_bindgen] pub fn process(&mut self, input: &str) -> String { // 使用Rust标准库,无需手动内存管理 if let Some(cached) = self.cache.get(input) { return cached.result.clone(); } let result = self.heavy_computation(input); self.cache.insert(input.to_string(), result.clone()); result } fn heavy_computation(&self, input: &str) -> String { // 复杂计算逻辑 format!("Processed: {}", input) } } } GC带来的变革 ...

现代前端架构深度解析:构建可扩展的大型应用

引言 随着前端应用的复杂度不断增加,传统的单体前端架构已难以满足大型项目的需求。现代前端架构需要解决代码分割、团队协作、性能优化、可维护性等多方面的挑战。本文将从架构设计的角度,深入探讨如何构建可扩展的大型前端应用。 一、前端架构演进史 1.1 从页面到应用的发展历程 jQuery时代 → AMD/RequireJS → CommonJS/Node.js → ES6 Modules → 现代框架时代 发展阶段 阶段 特点 代表技术 局限性 静态页面 HTML + CSS + 少量JS jQuery、Prototype 代码复用差 模块化初期 RequireJS、SeaJS AMD、CMD 加载复杂 组件化 React、Vue诞生 Virtual DOM 状态管理混乱 工程化 Webpack、Rollup ES6 Modules 构建复杂度高 现代化 Next.js、Nuxt.js SSR、SSR Streaming 学习曲线陡峭 1.2 当前架构挑战 大型前端应用面临的核心问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // 问题1: 代码组织混乱 // src/ // components/ // 1000+ 组件 // pages/ // 200+ 页面 // utils/ // 工具函数散落各处 // api/ // API调用不规范 // 问题2: 状态管理复杂 // - 全局状态与局部状态边界模糊 // - 状态流转难以追踪 // - 多个状态管理方案混用 // 问题3: 性能瓶颈 // - 首屏加载时间长 // - 路由切换卡顿 // - 内存泄漏风险 // 问题4: 团队协作困难 // - 代码冲突频繁 // - 发布周期长 // - 技术栈不统一 二、架构设计原则 2.1 SOLID原则在前端的应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 // S - 单一职责原则 // ❌ 违反单一职责 class UserComponent { render() { } fetchUser() { } validateInput() { } formatData() { } logAnalytics() { } } // ✅ 遵循单一职责 class UserComponent { constructor( private renderer: UserRenderer, private userService: UserService, private validator: InputValidator ) { } render() { this.renderer.render() } fetchUser() { this.userService.fetch() } } // O - 开闭原则 // 使用插件系统扩展功能 interface ComponentPlugin { install(component: any): void uninstall(component: any): void } class Component { private plugins: ComponentPlugin[] = [] use(plugin: ComponentPlugin) { this.plugins.push(plugin) plugin.install(this) return this } } // L - 里氏替换原则 // 基类可被子类无缝替换 abstract class BaseStore<T> { abstract get(id: string): Promise<T> abstract set(id: string, data: T): Promise<void> } class UserStore extends BaseStore<User> { async get(id: string): Promise<User> { } async set(id: string, data: User): Promise<void> { } } // I - 接口隔离原则 // 拆分大接口为小接口 interface ReadOnlyRepository<T> { findById(id: string): Promise<T> findAll(): Promise<T[]> } interface WriteOnlyRepository<T> { create(data: T): Promise<T> update(id: string, data: Partial<T>): Promise<T> delete(id: string): Promise<void> } // D - 依赖倒置原则 // 依赖抽象而非具体实现 interface CacheService { get(key: string): Promise<any> set(key: string, value: any): Promise<void> } class UserService { constructor(private cache: CacheService) { } } 2.2 分层架构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 // 标准前端分层架构 ┌─────────────────────────────────────────────┐ │ Presentation Layer │ │ (Components, Pages, UI Logic) │ ├─────────────────────────────────────────────┤ │ Business Logic Layer │ │ (Hooks, Composables, Use Cases) │ ├─────────────────────────────────────────────┤ │ Data Access Layer │ │ (API Client, Cache, State Management) │ ├─────────────────────────────────────────────┤ │ Infrastructure Layer │ │ (HTTP, WebSocket, LocalStorage) │ └─────────────────────────────────────────────┘ // 实现示例 // ========== Presentation Layer ========== // views/UserList.vue <template> <UserDataTable :users="users" :loading="loading" @refresh="handleRefresh" /> </template> // ========== Business Logic Layer ========== // composables/useUserList.ts export function useUserList() { const { users, loading, error, fetch } = userRepository() const refresh = async () => { await fetch() analytics.track('user_list_refreshed') } const filteredUsers = computed(() => { return users.value.filter(user => user.active) }) return { users: filteredUsers, loading, error, refresh } } // ========== Data Access Layer ========== // repositories/userRepository.ts export function userRepository() { const api = useApiClient() const cache = useCache() const fetch = async () => { const cached = await cache.get('users') if (cached) return cached const data = await api.get('/users') await cache.set('users', data, 300) // 5分钟 return data } return { users: ref([]), loading: ref(false), error: ref(null), fetch } } // ========== Infrastructure Layer =========== // utils/apiClient.ts class ApiClient { private baseURL: string private interceptors: RequestInterceptor[] async get<T>(url: string): Promise<T> { const request = new Request(this.baseURL + url) return this.execute<T>(request) } } 2.3 领域驱动设计(DDD)在前端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 // 1. 领域模型定义 // domains/user/User.ts export class User { constructor( private readonly id: UserId, private readonly email: Email, private name: UserName, private status: UserStatus ) {} // 领域逻辑 activate(): void { if (this.status === UserStatus.ACTIVE) { throw new Error('User already active') } this.status = UserStatus.ACTIVE } deactivate(): void { this.status = UserStatus.INACTIVE } isActive(): boolean { return this.status === UserStatus.ACTIVE } } // 值对象 export class Email { constructor(private readonly value: string) { if (!this.validate(value)) { throw new Error('Invalid email') } } private validate(email: string): boolean { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) } getValue(): string { return this.value } } // 2. 领域服务 // domains/user/UserService.ts export class UserService { constructor( private userRepo: UserRepository, private emailService: EmailService ) {} async registerUser(data: RegisterUserData): Promise<User> { // 业务规则验证 if (await this.userRepo.existsByEmail(data.email)) { throw new Error('Email already registered') } // 创建领域对象 const user = new User( UserId.generate(), new Email(data.email), new UserName(data.name), UserStatus.PENDING ) // 持久化 await this.userRepo.save(user) // 发送欢迎邮件 await this.emailService.sendWelcome(user.email.getValue()) return user } } // 3. 应用服务(用例) // application/useCases/RegisterUserUseCase.ts export class RegisterUserUseCase { constructor(private userService: UserService) { } async execute(request: RegisterUserRequest): Promise<RegisterUserResponse> { try { const user = await this.userService.registerUser(request.data) return { success: true, userId: user.id.getValue(), message: 'Registration successful' } } catch (error) { return { success: false, error: error.message } } } } // 4. 在组件中使用 // components/RegisterForm.vue export default { setup() { const registerUser = useRegisterUserUseCase() const handleSubmit = async (formData) => { const result = await registerUser.execute({ data: { email: formData.email, name: formData.name, password: formData.password } }) if (result.success) { router.push(`/welcome/${result.userId}`) } else { showError(result.error) } } return { handleSubmit } } } 三、微前端架构 3.1 微前端架构模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 // 模式1: 路由分发 // 主应用根据路由加载不同子应用 const microApps = [ { name: 'user-center', entry: '//localhost:3001', container: '#subapp', activeRule: '/users' }, { name: 'order-system', entry: '//localhost:3002', container: '#subapp', activeRule: '/orders' } ] // 模式2: 组合式集成 // 主应用提供容器,子应用作为组件渲染 <template> <div> <AppHeader /> <MicroApp name="user-center" :props="userProps" /> <AppFooter /> </div> </template> // 模式3: EMP (EMP Module Federation) // 去中心化的模块共享 // 子应用A new ModuleFederationPlugin({ name: 'appA', exposes: { './UserList': './src/components/UserList' }, shared: ['vue', 'vue-router'] }) // 子应用B使用A的组件 import UserList from 'appA/UserList' 3.2 模块联邦实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 // webpack.config.js - 主应用 const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin') module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'host_app', remotes: { userApp: 'user_app@http://localhost:3001/remoteEntry.js', orderApp: 'order_app@http://localhost:3002/remoteEntry.js' }, shared: { vue: { singleton: true, requiredVersion: '^3.0.0' }, 'vue-router': { singleton: true } } }) ] } // 在主应用中使用远程模块 // src/App.vue <script> import { defineAsyncComponent } from 'vue' // 动态加载远程组件 const UserDashboard = defineAsyncComponent(() => import('userApp/Dashboard') ) const OrderList = defineAsyncComponent(() => import('orderApp/OrderList') ) export default { components: { UserDashboard, OrderList } } </script> // 子应用配置 - userApp // webpack.config.js module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'user_app', filename: 'remoteEntry.js', exposes: { './Dashboard': './src/components/Dashboard.vue', './UserProfile': './src/components/UserProfile.vue', './UserStore': './src/stores/user' }, shared: { vue: { singleton: true, requiredVersion: '^3.0.0' } } }) ] } 3.3 微前端通信方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 // ========== 方案1: 自定义事件总线 ========== // utils/eventBus.ts class MicroEventBus { private events: Map<string, Set<Function>> constructor() { this.events = new Map() } on(event: string, callback: Function) { if (!this.events.has(event)) { this.events.set(event, new Set()) } this.events.get(event)!.add(callback) } off(event: string, callback: Function) { this.events.get(event)?.delete(callback) } emit(event: string, data?: any) { this.events.get(event)?.forEach(callback => callback(data)) } } // 全局单例 export const microEventBus = new MicroEventBus() // 子应用A - 发送事件 import { microEventBus } from './eventBus' microEventBus.emit('user:login', { userId: '123', userName: 'Alice' }) // 子应用B - 监听事件 microEventBus.on('user:login', (user) => { console.log('User logged in:', user) updateUI(user) }) // ========== 方案2: 状态共享 ========== // stores/sharedStore.ts import { reactive, readonly } from 'vue' const state = reactive({ user: null, theme: 'light', locale: 'zh-CN' }) export const sharedStore = { state: readonly(state), setUser(user: any) { state.user = user }, setTheme(theme: string) { state.theme = theme }, setLocale(locale: string) { state.locale = locale } } // ========== 方案3: 全局状态管理 ========== // 使用Pinia创建跨应用store // stores/global.ts import { defineStore } from 'pinia' export const useGlobalStore = defineStore('global', { state: () => ({ currentUser: null, notifications: [] }), actions: { async login(credentials) { const user = await api.login(credentials) this.currentUser = user }, logout() { this.currentUser = null }, addNotification(notification) { this.notifications.push(notification) } } }) 3.4 样式隔离 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 // ========== 方案1: CSS Modules ========== // components/UserCard.module.css .card { padding: 20px; border-radius: 8px; background: white; } .title { font-size: 18px; color: #333; } // components/UserCard.vue <template> <div :class="$style.card"> <h3 :class="$style.title">{{ title }}</h3> </div> </template> <script> import styles from './UserCard.module.css' export default { $style: styles } </script> // ========== 方案2: Shadow DOM ========== // components/ShadowWidget.ts class ShadowWidget extends HTMLElement { constructor() { super() // 创建Shadow DOM const shadow = this.attachShadow({ mode: 'open' }) // 隔离的样式 const style = document.createElement('style') style.textContent = ` .widget { padding: 20px; background: #f5f5f5; } .widget h3 { color: #333; margin: 0 0 10px 0; } ` // 隔离的内容 const wrapper = document.createElement('div') wrapper.className = 'widget' wrapper.innerHTML = ` <h3>Shadow DOM Widget</h3> <p>This is isolated from host page styles</p> ` shadow.appendChild(style) shadow.appendChild(wrapper) } } customElements.define('shadow-widget', ShadowWidget) // ========== 方案3: CSS-in-JS ========== // 使用styled-components或emotion import styled from 'styled-components' const Card = styled.div` padding: 20px; border-radius: 8px; background: white; h3 { font-size: 18px; color: #333; } ` // 组件自动生成唯一类名 <Card> <h3>Title</h3> </Card> // ========== 方案4: 命名空间 ========== // 推荐的BEM + 命名空间组合 // [子应用名]-[块]__[元素]--[修饰器] .user-center-card__header--active { background: #007bff; } .order-system-list__item--highlighted { background: #ffc107; } 四、状态管理架构 4.1 状态管理选型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 // ========== 方案对比 ========== // 1. Redux Toolkit - 复杂应用 import { createSlice, configureStore } from '@reduxjs/toolkit' const userSlice = createSlice({ name: 'user', initialState: { user: null, status: 'idle' }, reducers: { setUser(state, action) { state.user = action.payload }, clearUser(state) { state.user = null } }, extraReducers: (builder) => { builder .addCase(fetchUser.pending, (state) => { state.status = 'loading' }) .addCase(fetchUser.fulfilled, (state, action) => { state.status = 'succeeded' state.user = action.payload }) } }) export const { setUser, clearUser } = userSlice.actions export default configureStore({ reducer: { user: userSlice.reducer } }) // 2. Zustand - 轻量级 import create from 'zustand' const useUserStore = create((set, get) => ({ user: null, status: 'idle', setUser: (user) => set({ user }), fetchUser: async (id) => { set({ status: 'loading' }) const user = await api.getUser(id) set({ user, status: 'succeeded' }) }, getUserAge: () => { const { user } = get() return user ? calculateAge(user.birthday) : 0 } })) // 3. Pinia - Vue推荐 import { defineStore } from 'pinia' export const useUserStore = defineStore('user', { state: () => ({ user: null, status: 'idle' }), getters: { isLoggedIn: (state) => !!state.user, userName: (state) => state.user?.name || 'Guest' }, actions: { async fetchUser(id) { this.status = 'loading' this.user = await api.getUser(id) this.status = 'succeeded' } } }) // 4. Jotai - 原子化状态 import { atom, useAtom } from 'jotai' // 原子状态 const userAtom = atom(null) const statusAtom = atom('idle') // 派生原子 const isLoggedInAtom = atom( (get) => !!get(userAtom) ) // 组件中使用 function UserProfile() { const [user, setUser] = useAtom(userAtom) const [status] = useAtom(statusAtom) const [isLoggedIn] = useAtom(isLoggedInAtom) // ... } 4.2 分层状态架构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 // ========== 状态分层设计 ========== // 1. 服务端状态 - React Query / SWR import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' // 获取数据 function useUser(id: string) { return useQuery({ queryKey: ['user', id], queryFn: () => api.getUser(id), staleTime: 5 * 60 * 1000, // 5分钟 cacheTime: 10 * 60 * 1000 // 10分钟 }) } // 修改数据 function useUpdateUser() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ id, data }) => api.updateUser(id, data), onSuccess: (data, variables) => { // 自动更新缓存 queryClient.setQueryData(['user', variables.id], data) // 或使缓存失效 queryClient.invalidateQueries(['user', variables.id]) } }) } // 2. 全局UI状态 - Zustand import create from 'zustand/vanilla' const uiStore = create((set) => ({ theme: 'light', sidebarOpen: true, modalOpen: false, toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })), toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })), openModal: () => set({ modalOpen: true }), closeModal: () => set({ modalOpen: false }) })) // 3. 表单状态 - 原子状态 import { atom, useAtom } from 'jotai' const formDataAtom = atom({ username: '', email: '', password: '' }) const formErrorsAtom = atom({}) const useForm = () => { const [data, setData] = useAtom(formDataAtom) const [errors, setErrors] = useAtom(formErrorsAtom) const updateField = (field, value) => { setData((prev) => ({ ...prev, [field]: value })) } const validate = () => { const newErrors = {} if (!data.username) newErrors.username = 'Required' if (!data.email) newErrors.email = 'Required' setErrors(newErrors) return Object.keys(newErrors).length === 0 } return { data, errors, updateField, validate } } // ========== 状态组合使用 ========== function UserProfile({ userId }) { // 服务端状态 const { data: user, isLoading } = useUser(userId) const updateUser = useUpdateUser() // UI状态 const { theme, toggleTheme } = useUiStore() // 本地状态 const [isEditing, setIsEditing] = useState(false) if (isLoading) return <Spinner /> return ( <div className={theme}> {isEditing ? ( <EditForm user={user} onSave={(data) => updateUser.mutate({ id: userId, data })} onCancel={() => setIsEditing(false)} /> ) : ( <UserDetail user={user} onEdit={() => setIsEditing(true)} /> )} <button onClick={toggleTheme}>Toggle Theme</button> </div> ) } 4.3 状态持久化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 // ========== 本地持久化方案 ========== // 1. Zustand + localStorage import { persist } from 'zustand/middleware' export const useUserStore = create( persist( (set) => ({ user: null, token: null, setUser: (user) => set({ user }), setToken: (token) => set({ token }), logout: () => set({ user: null, token: null }) }), { name: 'user-storage', // 部分持久化 partialize: (state) => ({ user: state.user, token: state.token }) } ) ) // 2. Pinia + localStorage import { createPinia } from 'pinia' import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' const pinia = createPinia() pinia.use(piniaPluginPersistedstate) export const useAuthStore = defineStore('auth', { state: () => ({ token: null, refreshToken: null }), actions: { setTokens(token, refreshToken) { this.token = token this.refreshToken = refreshToken } }, persist: { key: 'auth', storage: localStorage, pick: ['token', 'refreshToken'] } }) // 3. IndexedDB - 大量数据 import { openDB } from 'idb' const dbPromise = openDB('app-db', 1, { upgrade(db) { db.createObjectStore('cache') } }) export const idbStorage = { async getItem(key) { const db = await dbPromise return await db.get('cache', key) }, async setItem(key, value) { const db = await dbPromise return await db.put('cache', value, key) }, async removeItem(key) { const db = await dbPromise return await db.delete('cache', key) } } // 4. 服务端状态同步 import { useQuery, useMutation } from '@tanstack/react-query' // 自动同步到服务端 function useSyncedState(key, initialValue) { const queryClient = useQueryClient() const { data } = useQuery({ queryKey: ['state', key], queryFn: () => api.getState(key), initialData: initialValue }) const mutation = useMutation({ mutationFn: (value) => api.setState(key, value), onSuccess: () => { queryClient.invalidateQueries(['state', key]) } }) const setState = (value) => { mutation.mutate(value) } return [data, setState] } 五、性能优化架构 5.1 代码分割策略 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 // ========== 路由级别分割 ========== // Vue Router const routes = [ { path: '/dashboard', component: () => import( /* webpackChunkName: "dashboard" */ './views/Dashboard.vue' ) }, { path: '/users', component: () => import( /* webpackChunkName: "users" */ './views/Users.vue' ) } ] // React Router const Dashboard = lazy(() => import('./views/Dashboard')) const Users = lazy(() => import('./views/Users')) function App() { return ( <Suspense fallback={<Spinner />}> <Routes> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/users" element={<Users />} /> </Routes> </Suspense> ) } // ========== 组件级别分割 ========== // Vue 3 - defineAsyncComponent const HeavyComponent = defineAsyncComponent({ loader: () => import('./HeavyComponent.vue'), loadingComponent: LoadingSpinner, errorComponent: ErrorDisplay, delay: 200, timeout: 5000 }) // React - lazy + Suspense const HeavyChart = lazy(() => import('./HeavyChart')) function Dashboard() { const [showChart, setShowChart] = useState(false) return ( <div> <button onClick={() => setShowChart(true)}> Show Chart </button> {showChart && ( <Suspense fallback={<Spinner />}> <HeavyChart /> </Suspense> )} </div> ) } // ========== 条件加载 ========== // 只在需要时加载库 const loadMonaco = async () => { const monaco = await import('monaco-editor') return monaco } const loadChartLibrary = async () => { if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { return null // 用户不喜欢动画 } const chart = await import('echarts') return chart } // ========== 预加载策略 ========== // 预加载下一个可能访问的页面 function ProductList({ products }) { const prefetch = usePrefetch() const handleMouseEnter = (productId) => { // 鼠标悬停时预加载 prefetch(`/products/${productId}`) } return ( <ul> {products.map(product => ( <li key={product.id} onMouseEnter={() => handleMouseEnter(product.id)} > <Link to={`/products/${product.id}`}> {product.name} </Link> </li> ))} </ul> ) } // Webpack魔法注释 const ProductDetail = lazy(() => import( /* webpackPrefetch: true */ /* webpackChunkName: "product-detail" */ './ProductDetail' )) 5.2 渲染优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 // ========== 虚拟列表 ========== import { useVirtualizer } from '@tanstack/react-virtual' function VirtualList({ items }) { const parentRef = useRef() const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => parentRef.current, estimateSize: () => 50, // 每项高度 overscan: 5 // 额外渲染项数 }) return ( <div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}> <div style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }} > {virtualizer.getVirtualItems().map(virtualItem => ( <div key={virtualItem.key} style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: `${virtualItem.size}px`, transform: `translateY(${virtualItem.start}px)` }} > {items[virtualItem.index].content} </div> ))} </div> </div> ) } // ========== 防抖/节流 ========== import { useDebouncedCallback, useThrottledCallback } from '@hooks' function SearchInput() { // 防抖搜索 const debouncedSearch = useDebouncedCallback( (query) => { performSearch(query) }, 500 // 延迟 ) return ( <input type="text" onChange={(e) => debouncedSearch(e.target.value)} /> ) } function ScrollHandler() { // 节流滚动事件 const throttledScroll = useThrottledCallback( () => { updatePosition() }, 100 // 间隔 ) useEffect(() => { window.addEventListener('scroll', throttledScroll) return () => window.removeEventListener('scroll', throttledScroll) }, [throttledScroll]) } // ========== React优化 ========== import { memo, useMemo, useCallback, useRef } from 'react' // 1. 组件记忆化 const ExpensiveComponent = memo(function ExpensiveComponent({ data }) { return <div>{/* 复杂渲染 */}</div> }) // 2. 计算缓存 function DataProcessor({ items }) { const sorted = useMemo(() => { return items.sort((a, b) => a.value - b.value) }, [items]) // 只在items变化时重新计算 const filtered = useMemo(() => { return sorted.filter(item => item.active) }, [sorted]) return <List items={filtered} /> } // 3. 函数稳定化 function ParentComponent() { const [count, setCount] = useState(0) // 不稳定的函数引用 const handleClickBad = () => { setCount(count + 1) } // 稳定的函数引用 const handleClickGood = useCallback(() => { setCount(c => c + 1) }, []) // 依赖为空,函数引用不变 return <ChildComponent onClick={handleClickGood} /> } // 4. 列表渲染优化 function TodoList({ todos, onToggle }) { const todoRefs = useRef(new Map()) const handleToggle = useCallback((id) => { // 批量更新 startTransition(() => { onToggle(id) }) }, [onToggle]) return ( <ul> {todos.map(todo => ( <TodoItem key={todo.id} ref={(node) => { if (node) { todoRefs.current.set(todo.id, node) } else { todoRefs.current.delete(todo.id) } }} todo={todo} onToggle={handleToggle} /> ))} </ul> ) } const TodoItem = memo(function TodoItem({ todo, onToggle }) { return ( <li onClick={() => onToggle(todo.id)}> {todo.text} </li> ) }) // ========== Vue优化 ========== // 1. computed缓存 export default { setup() { const items = ref([]) // 计算属性自动缓存 const filtered = computed(() => { return items.value.filter(item => item.active) }) const sorted = computed(() => { return filtered.value.sort((a, b) => a.value - b.value) }) return { sorted } } } // 2. v-once/v-memo <template> <!-- 只渲染一次 --> <Logo v-once /> <!-- 按条件记忆 --> <div v-for="item in list" :key="item.id" v-memo="[item.id, item.selected]"> {{ item.text }} </div> </template> // 3. watchEffect优化 watchEffect((onCleanup) => { const timer = setInterval(() => { updateData() }, 1000) onCleanup(() => { clearInterval(timer) // 清理副作用 }) }) // 4. shallowRef/shallowReactive // 大对象优化 const state = shallowReactive({ // 只顶层是响应式的 items: largeItemsArray }) // 只需要重新赋值时使用 const data = shallowRef(null) 5.3 资源优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 // ========== 图片优化 ========== // 1. 响应式图片 <picture> <source media="(min-width: 1024px)" srcSet="image-large.webp" type="image/webp" /> <source media="(min-width: 768px)" srcSet="image-medium.webp" type="image/webp" /> <source srcSet="image-small.webp" type="image/webp" /> <img src="image-fallback.jpg" alt="Description" loading="lazy" /> </picture> // 2. 懒加载图片 import { lazyload } from '@utils/lazyload' function ImageWithLazy({ src, alt }) { const imgRef = useRef() const [isLoaded, setIsLoaded] = useState(false) useEffect(() => { const observer = new IntersectionObserver( (entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target img.src = img.dataset.src observer.unobserve(img) } }) }, { rootMargin: '50px' } ) if (imgRef.current) { observer.observe(imgRef.current) } return () => observer.disconnect() }, []) return ( <img ref={imgRef} data-src={src} alt={alt} onLoad={() => setIsLoaded(true)} style={{ opacity: isLoaded ? 1 : 0 }} /> ) } // 3. 图片组件封装 function OptimizedImage({ src, alt, width, height, priority = false }) { const [imageSrc, setImageSrc] = useState(null) useEffect(() => { const load = async () => { // 使用WebP转换服务 const webpSrc = await convertToWebP(src, width) setImageSrc(webpSrc) } if (priority) { load() } else { const observer = new IntersectionObserver((entries) => { if (entries[0].isIntersecting) { load() observer.disconnect() } }) // ... observe logic } }, [src, width, priority]) return <img src={imageSrc} alt={alt} loading={!priority ? 'lazy' : 'eager'} /> } // ========== 字体优化 ========== // 1. 字体预加载 <link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossOrigin="anonymous" /> // 2. 字体显示策略 @font-face { font-family: 'CustomFont'; src: url('/fonts/custom.woff2') format('woff2'); font-display: swap; /* 立即显示后备字体 */ /* font-display: optional; 短暂等待后使用后备字体 */ /* font-display: fallback; 短暂等待,隐藏短时间 */ } // 3. 字体子集化 // 只包含使用的字符 // 使用fonttools或在线工具生成subset // ========== 第三方资源优化 ========== // 动态加载重型库 const loadGoogleMaps = () => { return new Promise((resolve) => { if (window.google) { resolve(window.google) return } const script = document.createElement('script') script.src = `https://maps.googleapis.com/maps/api/js?key=${API_KEY}` script.async = true script.onload = () => resolve(window.google) document.head.appendChild(script) }) } // 使用场景 function MapComponent() { const [map, setMap] = useState(null) useEffect(() => { let mounted = true loadGoogleMaps().then(google => { if (mounted) { setMap(new google.maps.Map(/* ... */)) } }) return () => { mounted = false } }, []) return <div ref={mapRef} /> } // ========== 缓存策略 ========== // Service Worker缓存 // sw.js const CACHE_NAME = 'app-v1' const STATIC_CACHE = [ '/', '/styles/main.css', '/scripts/main.js' ] self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME).then((cache) => { return cache.addAll(STATIC_CACHE) }) ) }) self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request).then((response) => { return response || fetch(event.request) }) ) }) // 网络优先策略 async function networkFirst(request) { try { const response = await fetch(request) const cache = await caches.open(CACHE_NAME) cache.put(request, response.clone()) return response } catch { return caches.match(request) } } // 缓存优先策略 async function cacheFirst(request) { const cached = await caches.match(request) if (cached) return cached const response = await fetch(request) const cache = await caches.open(CACHE_NAME) cache.put(request, response.clone()) return response } // 过期策略 async function staleWhileRevalidate(request) { const cache = await caches.open(CACHE_NAME) const cached = await cache.match(request) const fetchPromise = fetch(request).then((response) => { cache.put(request, response.clone()) return response }) return cached || fetchPromise } 六、构建优化 6.1 Webpack优化配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 // webpack.config.js const path = require('path') const TerserPlugin = require('terser-webpack-plugin') const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') module.exports = { // ========== 1. 构建模式 ========== mode: 'production', // ========== 2. 代码分割 ========== optimization: { splitChunks: { chunks: 'all', cacheGroups: { // 框架代码单独打包 framework: { test: /[\\/]node_modules[\\/](react|react-dom|vue)[\\/]/, name: 'framework', priority: 40 }, // UI库单独打包 ui: { test: /[\\/]node_modules[\\/](@mui|@ant-design|element-plus)[\\/]/, name: 'ui', priority: 30 }, // 工具库 lib: { test: /[\\/]node_modules[\\/](lodash|axios|dayjs)[\\/]/, name: 'lib', priority: 20 }, // 公共代码 commons: { minChunks: 2, priority: 10, reuseExistingChunk: true } } }, // 运行时代码单独提取 runtimeChunk: 'single', // 压缩配置 minimize: true, minimizer: [ new TerserPlugin({ terserOptions: { parse: { ecma: 8 }, compress: { ecma: 5, warnings: false, comparisons: false, inline: 2, drop_console: true }, mangle: { safari10: true }, output: { ecma: 5, comments: false, ascii_only: true } } }), new CssMinimizerPlugin() ] }, // ========== 3. 模块解析 ========== resolve: { // 路径别名 alias: { '@': path.resolve(__dirname, 'src'), '@components': path.resolve(__dirname, 'src/components'), '@utils': path.resolve(__dirname, 'src/utils') }, // 扩展名 extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue', '.json'], // 模块查找路径 modules: ['node_modules', path.resolve(__dirname, 'src')] }, // ========== 4. 缓存配置 ========== cache: { type: 'filesystem', buildDependencies: { config: [__filename] } }, // ========== 5. 输出配置 ========== output: { path: path.resolve(__dirname, 'dist'), filename: 'js/[name].[contenthash:8].js', chunkFilename: 'js/[name].[contenthash:8].chunk.js', // 资源文件名 assetModuleFilename: 'assets/[name].[hash:8][ext]' }, // ========== 6. 性能优化 ========== performance: { hints: 'warning', maxAssetSize: 244 * 1024, // 244KB maxEntrypointSize: 244 * 1024 } } 6.2 Vite优化配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 // vite.config.ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { visualizer } from 'rollup-plugin-visualizer' import viteCompression from 'vite-plugin-compression' export default defineConfig({ plugins: [ vue(), // 构建分析 visualizer({ open: true, gzipSize: true, brotliSize: true }), // Gzip压缩 viteCompression({ algorithm: 'gzip', ext: '.gz' }), // Brotli压缩 viteCompression({ algorithm: 'brotliCompress', ext: '.br' }) ], build: { // 产物目录 outDir: 'dist', // 静态资源目录 assetsDir: 'assets', // 生成source map sourcemap: false, // 构建后是否生成 manifest.json manifest: true, // chunk大小警告阈值 chunkSizeWarningLimit: 1000, // 代码分割 rollupOptions: { output: { // 手动分包 manualChunks: { 'vue-vendor': ['vue', 'vue-router', 'pinia'], 'ui-lib': ['element-plus'], 'utils': ['axios', 'lodash-es', 'dayjs'] }, // 文件命名 chunkFileNames: 'js/[name]-[hash].js', entryFileNames: 'js/[name]-[hash].js', assetFileNames: '[ext]/[name]-[hash].[ext]' } }, // 压缩 minify: 'terser', terserOptions: { compress: { drop_console: true, drop_debugger: true } } }, // 依赖优化 optimizeDeps: { include: ['vue', 'vue-router', 'pinia'], exclude: ['some-large-dep'] }, // CSS配置 css: { modules: { localsConvention: 'camelCase' }, preprocessorOptions: { scss: { additionalData: `@import "@/styles/variables.scss";` } } }, // 开发服务器 server: { port: 3000, open: true, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } } }) 七、监控与调试 7.1 性能监控 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 // ========== Core Web Vitals监控 ========== // utils/performanceMonitor.ts interface PerformanceMetrics { FCP: number // First Contentful Paint LCP: number // Largest Contentful Paint FID: number // First Input Delay CLS: number // Cumulative Layout Shift TTFB: number // Time to First Byte } export class PerformanceMonitor { private metrics: Partial<PerformanceMetrics> = {} async collectMetrics(): Promise<PerformanceMetrics> { // 等待页面加载完成 await new Promise(resolve => window.addEventListener('load', resolve)) // FCP const fcpEntry = performance.getEntriesByName('first-contentful-paint')[0] as any this.metrics.FCP = fcpEntry?.startTime || 0 // LCP this.metrics.LCP = await this.getLCP() // FID this.metrics.FID = await this.getFID() // CLS this.metrics.CLS = await this.getCLS() // TTFB const navigation = performance.getEntriesByType('navigation')[0] as any this.metrics.TTFB = navigation?.responseStart || 0 return this.metrics as PerformanceMetrics } private getLCP(): Promise<number> { return new Promise(resolve => { new PerformanceObserver((list) => { const entries = list.getEntries() const lastEntry = entries[entries.length - 1] as any resolve(lastEntry?.startTime || 0) }).observe({ entryTypes: ['largest-contentful-paint'] }) }) } private getFID(): Promise<number> { return new Promise(resolve => { new PerformanceObserver((list) => { const firstInput = list.getEntries()[0] as any resolve(firstInput?.processingStart - firstInput?.startTime || 0) }).observe({ entryTypes: ['first-input'] }) }) } private getCLS(): Promise<number> { return new Promise(resolve => { let clsValue = 0 new PerformanceObserver((list) => { for (const entry of list.getEntries() as any[]) { if (!entry.hadRecentInput) { clsValue += entry.value } } resolve(clsValue) }).observe({ entryTypes: ['layout-shift'] }) }) } reportToAnalytics(metrics: PerformanceMetrics) { // 发送到分析平台 analytics.track('page_performance', { fcp: metrics.FCP, lcp: metrics.LCP, fid: metrics.FID, cls: metrics.CLS, ttfb: metrics.TTFB, url: window.location.href, userAgent: navigator.userAgent }) } } // ========== 错误监控 ========== // utils/errorTracker.ts export class ErrorTracker { private errors: Error[] = [] init() { // 全局错误捕获 window.addEventListener('error', (event) => { this.captureError(event.error || new Error(event.message)) }) // Promise拒绝捕获 window.addEventListener('unhandledrejection', (event) => { this.captureError(event.reason) }) // Vue错误处理 if (typeof app !== 'undefined' && app.config) { app.config.errorHandler = (err, instance, info) => { this.captureError(err, { componentName: instance?.$options?.name, lifecycle: info }) } } } captureError(error: Error, context?: any) { const errorInfo = { message: error.message, stack: error.stack, timestamp: Date.now(), url: window.location.href, userAgent: navigator.userAgent, context } this.errors.push(error as any) // 发送到错误追踪服务 this.sendToService(errorInfo) } private sendToService(errorInfo: any) { // 发送到Sentry、自建服务等 fetch('/api/errors', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(errorInfo) }).catch(console.error) } } // ========== 用户行为追踪 ========== // utils/analytics.ts export class UserBehaviorTracker { private events: any[] = [] trackPageView() { this.trackEvent('page_view', { url: window.location.href, referrer: document.referrer, title: document.title }) } trackClick(element: HTMLElement) { this.trackEvent('click', { tagName: element.tagName, id: element.id, className: element.className, text: element.textContent?.substring(0, 50) }) } trackScroll(depth: number) { this.trackEvent('scroll', { scrollDepth: depth, pageHeight: document.body.scrollHeight }) } trackEngagement(duration: number) { this.trackEvent('engagement', { duration, interactions: this.events.length }) } private trackEvent(type: string, data: any) { const event = { type, data, timestamp: Date.now() } this.events.push(event) this.sendEvent(event) } private sendEvent(event: any) { // 批量发送或实时发送 if (this.events.length >= 10) { this.flush() } } flush() { if (this.events.length === 0) return fetch('/api/analytics/events', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ events: this.events }) }).then(() => { this.events = [] }).catch(console.error) } } 7.2 调试工具 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 // ========== Vue DevTools集成 ========== // 开发环境启用调试功能 if (import.meta.env.DEV) { app.config.devtools = true // 添加组件名称便于调试 app.component('UserProfile', UserProfile) } // ========== React DevTools ========== // 使用React Developer Tools Profiler import { Profiler } from 'react' function onRenderCallback( id, phase, actualDuration, baseDuration, startTime, commitTime ) { console.log({ id, phase, actualDuration, baseDuration, startTime, commitTime }) } <Profiler id="UserProfile" onRender={onRenderCallback}> <UserProfile /> </Profiler> // ========== 自定义调试工具 ========== // utils/debug.ts export const debug = { log: (...args: any[]) => { if (import.meta.env.DEV) { console.log('[DEBUG]', ...args) } }, group: (label: string, fn: () => void) => { if (import.meta.env.DEV) { console.group(label) fn() console.groupEnd() } }, time: (label: string) => { if (import.meta.env.DEV) { console.time(label) } }, timeEnd: (label: string) => { if (import.meta.env.DEV) { console.timeEnd(label) } }, track: (name: string, value: any) => { if (import.meta.env.DEV) { console.log(`[TRACK] ${name}:`, value) } } } // 使用示例 debug.time('dataFetch') fetchData().then(data => { debug.track('fetchedData', data) debug.timeEnd('dataFetch') }) 总结 构建现代前端架构需要综合考虑多个维度: ...

WebAssembly性能优化实践:突破Web应用性能瓶颈

深入探讨WebAssembly的性能优化技巧,从内存管理到SIMD优化,帮助开发者构建高性能的Web应用。

前端性能优化完全指南:从加载到渲染的全方位优化

深入探讨前端性能优化的核心技术,包括资源加载优化、渲染性能优化、网络优化和JavaScript性能优化,帮助你打造秒开的Web应用。

后端性能优化实战:从诊断到优化的完整方法论

深入剖析后端性能优化的全流程,包括性能诊断、数据库优化、缓存策略、并发处理、异步编程等实战技巧,帮助你构建高性能的后端系统。

Web性能监控与诊断实战:从Core Web Vitals到性能优化

引言 Web性能直接影响用户体验和业务转化。现代Web性能监控已经从简单的页面加载时间,发展到精细化的用户体验指标体系。本文将深入探讨Web性能监控的完整体系,从指标定义到采集分析,再到优化实践。 一、Core Web Vitals详解 1.1 LCP(最大内容绘制) 定义与标准 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 // LCP测量页面主要内容加载完成的时间 // 良好:≤2.5秒 // 需改进:2.5-4秒 // 差:>4秒 // 使用Performance Observer测量LCP function measureLCP() { return new Promise<PerformanceEntry>((resolve) => { new PerformanceObserver((list) => { const entries = list.getEntries() const lastEntry = entries[entries.length - 1] resolve(lastEntry) }).observe({ entryTypes: ['largest-contentful-paint'] }) }) } // 使用web-vitals库 import { onLCP } from 'web-vitals' onLCP((metric) => { console.log('LCP:', metric.value) // 上报数据到分析平台 sendToAnalytics({ metric: 'LCP', value: metric.value, rating: metric.rating, // 'good' | 'needs-improvement' | 'poor' }) }) LCP优化策略 ...

2025年前端性能优化终极指南:从Core Web Vitals到用户体验优化

深入探讨2025年前端性能优化的最新技术和最佳实践,包括Core Web Vitals优化、代码分割、懒加载、缓存策略和现代Web性能工具的使用。

CDN加速优化完全指南:从基础原理到高级配置实战

全面解析CDN加速技术的核心原理、配置方法和优化策略,包括缓存策略、边缘计算、安全防护和性能监控,帮助开发者构建高性能的全球内容分发网络。