根因:主包 2MB 全量组件注入导致 DevTools 渲染引擎内存渐增, 叠加离线时固定 3s 抑制期后的请求洪泛。 修复: - app.config.ts 添加 lazyCodeLoading: requiredComponents 主包 2.0MB→766KB,taro.js 526→131KB,vendors.js 230→28KB - request.ts 离线抑制改为指数退避(3s→6s→12s→30s cap) 后端不可达时自动延长抑制,防止请求风暴 - SegmentTabs Tab 接口改为 readonly,修复 TS 编译错误 - AbortController polyfill 补齐小程序运行时缺失 - 健康首页/设备同步/健康档案/报告/设置页 UI 重构 - 文章页公开端点适配游客访问 - 健康首页 Swiper 间隔优化 4s→5s,动画 500→300ms
70 lines
2.1 KiB
TypeScript
70 lines
2.1 KiB
TypeScript
import './utils/crypto-polyfill';
|
|
import './utils/abort-controller-polyfill';
|
|
import { useEffect, useRef, PropsWithChildren } from 'react';
|
|
import { useDidShow, useDidHide } from '@tarojs/taro';
|
|
import ErrorBoundary from './components/ErrorBoundary';
|
|
import { flushEvents } from './services/analytics';
|
|
import { useAuthStore } from './stores/auth';
|
|
import { useUIStore } from './stores/ui';
|
|
import { useAlertPolling } from './hooks/useAlertPolling';
|
|
import { migrateLegacyStorage } from './utils/secure-storage';
|
|
import './app.scss';
|
|
|
|
function App({ children }: PropsWithChildren<Record<string, unknown>>) {
|
|
const restoreAuth = useAuthStore((s) => s.restore);
|
|
const restoreUI = useUIStore((s) => s.restore);
|
|
|
|
// useDidShow 在首次 mount 时也会触发,不需要 useEffect 重复调用
|
|
useDidShow(() => {
|
|
migrateLegacyStorage();
|
|
restoreAuth();
|
|
restoreUI();
|
|
});
|
|
|
|
// 告警轮询:登录态下自动监听 critical 告警
|
|
useAlertPolling();
|
|
|
|
// 暴露全局 bridge 供 MCP/自动化测试调用(仅 dev 模式)
|
|
useEffect(() => {
|
|
if (process.env.NODE_ENV === 'production') return;
|
|
(globalThis as Record<string, unknown>).__hms = {
|
|
restoreAuth: () => { restoreAuth(); return useAuthStore.getState(); },
|
|
restoreUI,
|
|
getAuthState: () => useAuthStore.getState(),
|
|
};
|
|
return () => { delete (globalThis as Record<string, unknown>).__hms; };
|
|
}, []);
|
|
|
|
// Analytics 定时器:仅在页面可见时运行,后台时暂停以节省资源
|
|
const analyticsTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
|
|
const startAnalyticsTimer = () => {
|
|
if (analyticsTimerRef.current) return;
|
|
analyticsTimerRef.current = setInterval(flushEvents, 30000);
|
|
};
|
|
|
|
const stopAnalyticsTimer = () => {
|
|
if (analyticsTimerRef.current) {
|
|
clearInterval(analyticsTimerRef.current);
|
|
analyticsTimerRef.current = null;
|
|
}
|
|
};
|
|
|
|
useDidShow(() => {
|
|
startAnalyticsTimer();
|
|
});
|
|
|
|
useDidHide(() => {
|
|
stopAnalyticsTimer();
|
|
flushEvents();
|
|
});
|
|
|
|
useEffect(() => {
|
|
return () => { stopAnalyticsTimer(); };
|
|
}, []);
|
|
|
|
return <ErrorBoundary>{children}</ErrorBoundary>;
|
|
}
|
|
|
|
export default App;
|