智能预加载:基于用户行为和路由预测
核心概念
智能预加载通过分析用户行为模式、路由关系和页面重要性,在用户实际访问前预先加载资源,显著提升用户体验。
实现架构
1. 行为数据收集层
class UserBehaviorTracker {
constructor() {
this.sessionData = {
clickPaths: [],
hoverDurations: new Map(),
scrollDepth: new Map(),
visitFrequency: new Map(),
sessionStart: Date.now()
}
this.setupTracking()
}
setupTracking() {
// 链接悬停跟踪
this.trackLinkHovers()
// 点击流分析
this.trackClicks()
// 滚动深度监控
this.trackScrollBehavior()
// 页面停留时间
this.trackPageStayTime()
}
trackLinkHovers() {
document.addEventListener('mouseover', (e) => {
const link = e.target.closest('a[href]')
if (link && this.isInternalLink(link.href)) {
const hoverStart = Date.now()
const routePath = this.extractRoutePath(link.href)
link.addEventListener('mouseleave', () => {
const duration = Date.now() - hoverStart
this.recordHoverDuration(routePath, duration)
}, { once: true })
}
})
}
trackClicks() {
document.addEventListener('click', (e) => {
const link = e.target.closest('a[href]')
if (link && this.isInternalLink(link.href)) {
const routePath = this.extractRoutePath(link.href)
this.recordClickPath(routePath)
}
})
}
recordHoverDuration(routePath, duration) {
const current = this.sessionData.hoverDurations.get(routePath) || []
current.push(duration)
this.sessionData.hoverDurations.set(routePath, current.slice(-10)) // 保留最近10次
}
recordClickPath(routePath) {
this.sessionData.clickPaths.push({
path: routePath,
timestamp: Date.now()
})
}
}
2. 预测引擎
class RoutePredictor {
constructor(behaviorTracker) {
this.tracker = behaviorTracker
this.routeGraph = new Map() // 路由关系图
this.predictionWeights = {
hoverDuration: 0.3,
clickFrequency: 0.4,
routeProximity: 0.2,
timeContext: 0.1
}
}
// 构建路由关系图
buildRouteGraph(routes) {
routes.forEach(route => {
this.routeGraph.set(route.path, {
...route,
connections: new Map(),
importance: this.calculateRouteImportance(route)
})
})
}
// 预测下一个可能访问的路由
predictNextRoutes(currentRoute, limit = 3) {
const predictions = new Map()
// 基于点击流分析
const clickBased = this.predictFromClickPatterns(currentRoute)
// 基于悬停行为
const hoverBased = this.predictFromHoverBehavior(currentRoute)
// 基于路由关系
const routeBased = this.predictFromRouteRelations(currentRoute)
// 基于时间上下文
const timeBased = this.predictFromTimeContext(currentRoute)
// 合并预测结果
this.mergePredictions(predictions, clickBased, this.predictionWeights.clickFrequency)
this.mergePredictions(predictions, hoverBased, this.predictionWeights.hoverDuration)
this.mergePredictions(predictions, routeBased, this.predictionWeights.routeProximity)
this.mergePredictions(predictions, timeBased, this.predictionWeights.timeContext)
// 排序并返回Top N
return Array.from(predictions.entries())
.sort(([, a], [, b]) => b - a)
.slice(0, limit)
.map(([route]) => route)
}
predictFromHoverBehavior(currentRoute) {
const predictions = new Map()
const hoverData = this.tracker.sessionData.hoverDurations
for (const [route, durations] of hoverData) {
if (route !== currentRoute) {
const avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length
const score = this.normalizeHoverScore(avgDuration)
predictions.set(route, score)
}
}
return predictions
}
predictFromClickPatterns(currentRoute) {
const predictions = new Map()
const clickPaths = this.tracker.sessionData.clickPaths
const recentClicks = clickPaths.filter(click =>
Date.now() - click.timestamp < 30 * 60 * 1000 // 30分钟内
)
// 分析点击序列模式
const transitionCounts = new Map()
for (let i = 0; i < recentClicks.length - 1; i++) {
const from = recentClicks[i].path
const to = recentClicks[i + 1].path
const key = `${from}->${to}`
transitionCounts.set(key, (transitionCounts.get(key) || 0) + 1)
}
// 计算从当前路由出发的概率
for (const [transition, count] of transitionCounts) {
const [from, to] = transition.split('->')
if (from === currentRoute && to !== currentRoute) {
predictions.set(to, count / recentClicks.length)
}
}
return predictions
}
normalizeHoverScore(duration) {
// 悬停时间越长,点击可能性越大
return Math.min(duration / 1000, 1) // 归一化到0-1
}
}
3. 预加载控制器
class SmartPreloader {
constructor(predictor, router) {
this.predictor = predictor
this.router = router
this.preloadQueue = new Set()
this.maxConcurrent = 2
this.currentPreloads = 0
this.setupPreloadTriggers()
}
setupPreloadTriggers() {
// 路由变化时预测
this.router.afterEach((to, from) => {
this.schedulePreload(to.path)
})
// 用户空闲时预加载
this.setupIdlePreloading()
// 网络空闲时预加载
this.setupNetworkAwarePreloading()
}
async schedulePreload(currentRoute) {
const predictedRoutes = this.predictor.predictNextRoutes(currentRoute)
for (const route of predictedRoutes) {
if (!this.preloadQueue.has(route) && this.shouldPreload(route)) {
this.preloadQueue.add(route)
}
}
await this.processPreloadQueue()
}
async processPreloadQueue() {
while (this.preloadQueue.size > 0 && this.currentPreloads < this.maxConcurrent) {
const route = this.preloadQueue.values().next().value
this.preloadQueue.delete(route)
this.currentPreloads++
await this.executePreload(route)
this.currentPreloads--
}
}
async executePreload(routePath) {
try {
// 预加载组件
const route = this.router.resolve(routePath)
if (route.matched.length > 0) {
const components = route.matched.map(match => match.components.default)
await Promise.all(components.map(component => {
if (typeof component === 'function') {
return component() // 触发组件加载
}
}))
}
// 预加载关键数据
await this.preloadRouteData(routePath)
console.log(`✅ 预加载完成: ${routePath}`)
} catch (error) {
console.warn(`预加载失败 ${routePath}:`, error)
}
}
shouldPreload(routePath) {
// 检查路由是否支持预加载
const route = this.router.resolve(routePath)
return route.matched.some(record =>
record.meta?.preload !== false
)
}
setupIdlePreloading() {
if ('requestIdleCallback' in window) {
const idleCallback = () => {
if (this.preloadQueue.size > 0) {
this.processPreloadQueue()
}
requestIdleCallback(idleCallback)
}
requestIdleCallback(idleCallback)
}
}
setupNetworkAwarePreloading() {
// 网络状态感知预加载
if (navigator.connection) {
navigator.connection.addEventListener('change', () => {
const connection = navigator.connection
if (connection.saveData) {
this.maxConcurrent = 0 // 省流量模式禁用预加载
} else if (connection.effectiveType.includes('2g')) {
this.maxConcurrent = 1 // 2G网络限制并发
} else {
this.maxConcurrent = 2 // 正常网络
}
})
}
}
}
4. Vue路由集成
// vue-router配置
const router = new VueRouter({
routes: [
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue'),
meta: {
preload: true,
importance: 0.9,
preloadDependencies: ['/api/user/stats']
}
},
{
path: '/profile',
component: () => import('./views/Profile.vue'),
meta: {
preload: true,
importance: 0.7
}
},
{
path: '/settings',
component: () => import('./views/Settings.vue'),
meta: {
preload: false // 明确不预加载
}
}
]
})
// 主应用集成
const behaviorTracker = new UserBehaviorTracker()
const predictor = new RoutePredictor(behaviorTracker)
const preloader = new SmartPreloader(predictor, router)
// Vue插件形式
const SmartPreloadPlugin = {
install(Vue, { router }) {
const tracker = new UserBehaviorTracker()
const predictor = new RoutePredictor(tracker)
const preloader = new SmartPreloader(predictor, router)
Vue.prototype.$preloader = preloader
Vue.prototype.$behaviorTracker = tracker
}
}
Vue.use(SmartPreloadPlugin, { router })
5. 高级特性
// 基于机器学习的行为预测
class MLPredictor extends RoutePredictor {
async trainModel() {
// 使用历史数据训练预测模型
const trainingData = this.collectTrainingData()
const model = await this.trainRandomForest(trainingData)
this.predictionModel = model
}
predictNextRoutes(currentRoute) {
if (this.predictionModel) {
return this.mlPredict(currentRoute)
}
return super.predictNextRoutes(currentRoute)
}
mlPredict(currentRoute) {
const features = this.extractFeatures(currentRoute)
return this.predictionModel.predict(features)
}
}
// 渐进式预加载策略
class ProgressivePreloader extends SmartPreloader {
getPreloadPriority(routePath) {
const route = this.router.resolve(routePath)
const basePriority = route.meta?.importance || 0.5
// 根据用户行为调整优先级
const behaviorBoost = this.calculateBehaviorBoost(routePath)
const contextBoost = this.calculateContextBoost(routePath)
return basePriority + behaviorBoost + contextBoost
}
calculateBehaviorBoost(routePath) {
const hoverData = this.predictor.tracker.sessionData.hoverDurations.get(routePath)
if (!hoverData) return 0
const avgHover = hoverData.reduce((a, b) => a + b, 0) / hoverData.length
return Math.min(avgHover / 2000, 0.3) // 最大提升30%
}
}
性能优化策略
- 智能节流:避免过度预加载
- 内存管理:限制缓存大小
- 网络感知:根据网络条件调整策略
- 优先级队列:重要路由优先加载
- 缓存复用:充分利用浏览器缓存
监控和调优
class PreloadMonitor {
constructor(preloader) {
this.preloader = preloader
this.metrics = {
preloadHits: 0,
preloadMisses: 0,
timeSaved: 0
}
this.setupMonitoring()
}
setupMonitoring() {
// 监控预加载命中率
this.router.afterEach((to) => {
if (this.preloader.wasPreloaded(to.path)) {
this.metrics.preloadHits++
console.log(`🎯 预加载命中: ${to.path}`)
} else {
this.metrics.preloadMisses++
}
})
}
getHitRate() {
const total = this.metrics.preloadHits + this.metrics.preloadMisses
return total > 0 ? this.metrics.preloadHits / total : 0
}
}
这种智能预加载系统能够显著提升应用性能,通过学习和适应用户行为模式,在用户实际需要之前提前加载资源,创造无缝的用户体验。
挣钱养家

浙公网安备 33010602011771号