// 使用React.lazy進(jìn)行路由級代碼分割
import { lazy, Suspense } from 'react';
const CkgdList = lazy(() => import('./components/ckfp/ckgd/ckgd'));
const CkgdDetail = lazy(() => import('./components/ckfp/ckgd/detail'));
const App = () => (
<Router>
<Suspense fallback={<div>加載中...</div>}>
<Switch>
<Route path="/ckgd/list" component={CkgdList} />
<Route path="/ckgd/detail/:id" component={CkgdDetail} />
</Switch>
</Suspense>
</Router>
);
// 動(dòng)態(tài)導入大型組件
const HeavyComponent = lazy(() => import('./HeavyComponent'));
// 按需加載第三方庫
const loadChartLibrary = () => import('echarts').then(module => module.default);
const ChartComponent = () => {
const [chart, setChart] = useState(null);
useEffect(() => {
loadChartLibrary().then(echarts => {
setChart(echarts);
});
}, []);
if (!chart) return <div>加載圖表庫...</div>;
return <div ref={chartRef} />;
};
// 使用React.memo避免不必要的重渲染
const ExpensiveComponent = React.memo(({ data, onUpdate }) => {
// 組件實(shí)現
return (
<div>
{data.map(item => (
<ExpensiveItem key={item.id} item={item} />
))}
</div>
);
}, (prevProps, nextProps) => {
// 自定義比較函數
return prevProps.data === nextProps.data &&
prevProps.onUpdate === nextProps.onUpdate;
});
// 子組件優(yōu)化
const ExpensiveItem = React.memo(({ item }) => {
return <div>{item.name}</div>;
});
// 使用useMemo緩存計算結果
const ExpensiveCalculation = ({ data }) => {
const calculatedData = useMemo(() => {
return data.map(item => ({
...item,
calculatedValue: heavyCalculation(item)
}));
}, [data]); // 只有當data變化時(shí)重新計算
return <div>{calculatedData}</div>;
};
// 使用useCallback緩存函數
const DataTable = ({ data, onRowClick }) => {
const handleRowClick = useCallback((rowData) => {
onRowClick(rowData);
}, [onRowClick]);
return (
<table>
{data.map(row => (
<TableRow key={row.id} data={row} onClick={handleRowClick} />
))}
</table>
);
};
// 大數據量列表使用虛擬滾動(dòng)
import { FixedSizeList as List } from 'react-window';
const VirtualizedList = ({ items }) => {
const Row = ({ index, style }) => (
<div style={style}>
{items[index].name}
</div>
);
return (
<List
height={400}
itemCount={items.length}
itemSize={35}
>
{Row}
</List>
);
};
// 實(shí)現請求緩存
const requestCache = new Map();
export const cachedRequest = async (key, requestFn) => {
if (requestCache.has(key)) {
return requestCache.get(key);
}
const result = await requestFn();
requestCache.set(key, result);
// 設置緩存過(guò)期時(shí)間
setTimeout(() => {
requestCache.delete(key);
}, 5 * 60 * 1000); // 5分鐘過(guò)期
return result;
};
// 使用示例
const getCkgdList = () => {
return cachedRequest('ckgd_list', () =>
post(allUrl.ckfpCkgd.list, {}, {
header: allUrl.header,
condition: {}
})
);
};
// 防止重復請求
const pendingRequests = new Map();
export const deduplicatedRequest = async (key, requestFn) => {
if (pendingRequests.has(key)) {
return pendingRequests.get(key);
}
const requestPromise = requestFn();
pendingRequests.set(key, requestPromise);
try {
const result = await requestPromise;
return result;
} finally {
pendingRequests.delete(key);
}
};
// 圖片懶加載
const LazyImage = ({ src, alt, width, height }) => {
const [isLoaded, setIsLoaded] = useState(false);
const [imageSrc, setImageSrc] = useState('');
useEffect(() => {
const img = new Image();
img.src = src;
img.onload = () => {
setImageSrc(src);
setIsLoaded(true);
};
}, [src]);
return (
<div>
{!isLoaded && <div>加載中...</div>}
<img
src={imageSrc}
alt={alt}
width={width}
height={height}
style={{ display: isLoaded ? 'block' : 'none' }}
/>
</div>
);
};
// 使用WebP格式(如果支持)
const OptimizedImage = ({ src, alt, fallback }) => {
const [useWebP, setUseWebP] = useState(false);
useEffect(() => {
// 檢測瀏覽器是否支持WebP
const canvas = document.createElement('canvas');
if (canvas.getContext && canvas.getContext('2d')) {
setUseWebP(canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0);
}
}, []);
const imageSrc = useWebP ? `${src}.webp` : fallback || src;
return <img src={imageSrc} alt={alt} />;
};
// 字體加載優(yōu)化
export const loadFonts = () => {
// 使用字體顯示策略
const font = new FontFace('CustomFont', 'url(/fonts/custom.woff2)');
return font.load().then(loadedFont => {
document.fonts.add(loadedFont);
}).catch(error => {
console.error('字體加載失敗:', error);
});
};
// CSS中的字體優(yōu)化
const fontStyles = `
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2'),
url('/fonts/custom.woff') format('woff');
font-display: swap; /* 使用交換策略 */
}
body {
font-family: 'CustomFont', sans-serif;
}
`;
// webpack.config.js 優(yōu)化配置
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
common: {
name: 'common',
minChunks: 2,
chunks: 'all',
enforce: true
}
}
}
},
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000
}
};
// 使用webpack-bundle-analyzer分析包大小
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: 'bundle-report.html'
})
]
};
// 性能指標監控
export const monitorPerformance = () => {
// 監控關(guān)鍵性能指標
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`${entry.name}: ${entry.duration}ms`);
}
});
observer.observe({ entryTypes: ['measure', 'navigation', 'resource'] });
// 監控長(cháng)任務(wù)
if ('PerformanceObserver' in window) {
const longTaskObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 50) {
console.warn('長(cháng)任務(wù) detected:', entry);
}
}
});
longTaskObserver.observe({ entryTypes: ['longtask'] });
}
};
// 錯誤監控
export const setupErrorMonitoring = () => {
window.addEventListener('error', (event) => {
console.error('全局錯誤:', event.error);
// 發(fā)送錯誤報告
reportError(event.error);
});
window.addEventListener('unhandledrejection', (event) => {
console.error('未處理的Promise拒絕:', event.reason);
reportError(event.reason);
});
};
這些性能優(yōu)化策略可以幫助提升應用的加載速度、運行效率和用戶(hù)體驗。