Vue.js 3 runtime core library providing foundational APIs for building custom renderers and managing reactive component systems
—
Vue provides advanced hydration strategies for selective server-side rendering and client-side hydration, enabling performance optimizations for different content types.
Hydrate components when the browser is idle, reducing impact on initial page load.
/**
* Hydrates component when browser is idle
* @param timeout - Maximum time to wait before forcing hydration (ms)
* @returns Hydration strategy function
*/
function hydrateOnIdle(timeout?: number): HydrationStrategy;Usage Examples:
import { defineAsyncComponent, hydrateOnIdle } from "@vue/runtime-core";
// Hydrate when browser is idle
const IdleComponent = defineAsyncComponent({
loader: () => import('./HeavyComponent.vue'),
hydrate: hydrateOnIdle(1000) // Force hydration after 1 second if not idle
});
// Multiple components with idle hydration
const Dashboard = defineComponent({
components: {
Analytics: defineAsyncComponent({
loader: () => import('./Analytics.vue'),
hydrate: hydrateOnIdle()
}),
Charts: defineAsyncComponent({
loader: () => import('./Charts.vue'),
hydrate: hydrateOnIdle(2000)
})
}
});Hydrate components when they become visible in the viewport.
/**
* Hydrates component when it becomes visible
* @param options - Intersection observer options
* @returns Hydration strategy function
*/
function hydrateOnVisible(options?: IntersectionObserverInit): HydrationStrategy;Usage Examples:
import { defineAsyncComponent, hydrateOnVisible } from "@vue/runtime-core";
// Hydrate when component becomes visible
const LazyImage = defineAsyncComponent({
loader: () => import('./LazyImage.vue'),
hydrate: hydrateOnVisible()
});
// Hydrate with custom intersection options
const BelowFoldContent = defineAsyncComponent({
loader: () => import('./BelowFoldContent.vue'),
hydrate: hydrateOnVisible({
rootMargin: '100px', // Hydrate 100px before entering viewport
threshold: 0.1 // Hydrate when 10% visible
})
});
// Multiple visibility thresholds
const ProgressiveImage = defineAsyncComponent({
loader: () => import('./ProgressiveImage.vue'),
hydrate: hydrateOnVisible({
threshold: [0, 0.25, 0.5, 0.75, 1] // Multiple visibility levels
})
});Hydrate components based on CSS media query conditions.
/**
* Hydrates component when media query matches
* @param query - CSS media query string
* @returns Hydration strategy function
*/
function hydrateOnMediaQuery(query: string): HydrationStrategy;Usage Examples:
import { defineAsyncComponent, hydrateOnMediaQuery } from "@vue/runtime-core";
// Hydrate only on desktop
const DesktopWidget = defineAsyncComponent({
loader: () => import('./DesktopWidget.vue'),
hydrate: hydrateOnMediaQuery('(min-width: 1024px)')
});
// Hydrate only on mobile
const MobileMenu = defineAsyncComponent({
loader: () => import('./MobileMenu.vue'),
hydrate: hydrateOnMediaQuery('(max-width: 768px)')
});
// Hydrate based on orientation
const LandscapeFeature = defineAsyncComponent({
loader: () => import('./LandscapeFeature.vue'),
hydrate: hydrateOnMediaQuery('(orientation: landscape)')
});
// Hydrate based on reduced motion preference
const AnimatedComponent = defineAsyncComponent({
loader: () => import('./AnimatedComponent.vue'),
hydrate: hydrateOnMediaQuery('(prefers-reduced-motion: no-preference)')
});
// Complex media queries
const HighResComponent = defineAsyncComponent({
loader: () => import('./HighResComponent.vue'),
hydrate: hydrateOnMediaQuery('(min-resolution: 192dpi) and (min-width: 1200px)')
});Hydrate components when user interacts with them.
/**
* Hydrates component on user interaction
* @param events - Event name or array of event names to listen for
* @returns Hydration strategy function
*/
function hydrateOnInteraction(events: string | string[]): HydrationStrategy;Usage Examples:
import { defineAsyncComponent, hydrateOnInteraction } from "@vue/runtime-core";
// Hydrate on click
const InteractiveWidget = defineAsyncComponent({
loader: () => import('./InteractiveWidget.vue'),
hydrate: hydrateOnInteraction('click')
});
// Hydrate on multiple events
const HoverCard = defineAsyncComponent({
loader: () => import('./HoverCard.vue'),
hydrate: hydrateOnInteraction(['mouseenter', 'focus'])
});
// Hydrate on touch or mouse events
const TouchComponent = defineAsyncComponent({
loader: () => import('./TouchComponent.vue'),
hydrate: hydrateOnInteraction(['touchstart', 'mousedown'])
});
// Form field hydration
const RichTextEditor = defineAsyncComponent({
loader: () => import('./RichTextEditor.vue'),
hydrate: hydrateOnInteraction(['focus', 'click', 'keydown'])
});Create complex hydration logic by combining multiple strategies.
import { defineAsyncComponent, hydrateOnIdle, hydrateOnVisible, hydrateOnMediaQuery, hydrateOnInteraction } from "@vue/runtime-core";
// Custom combined strategy
function createHybridStrategy(): HydrationStrategy {
return (hydrate, forEachElement) => {
let hydrated = false;
const doHydrate = () => {
if (!hydrated) {
hydrated = true;
hydrate();
}
};
// Hydrate on idle OR visibility OR interaction
const idleStrategy = hydrateOnIdle(2000);
const visibleStrategy = hydrateOnVisible({ threshold: 0.5 });
const interactionStrategy = hydrateOnInteraction(['click', 'focus']);
// Apply all strategies
idleStrategy(doHydrate, forEachElement);
visibleStrategy(doHydrate, forEachElement);
interactionStrategy(doHydrate, forEachElement);
};
}
// Usage
const HybridComponent = defineAsyncComponent({
loader: () => import('./HybridComponent.vue'),
hydrate: createHybridStrategy()
});
// Progressive hydration based on device capabilities
function createAdaptiveStrategy(): HydrationStrategy {
return (hydrate, forEachElement) => {
// Fast devices: hydrate immediately when visible
if (navigator.hardwareConcurrency > 4) {
hydrateOnVisible()(hydrate, forEachElement);
}
// Slow devices: hydrate only on interaction
else {
hydrateOnInteraction('click')(hydrate, forEachElement);
}
};
}
const AdaptiveComponent = defineAsyncComponent({
loader: () => import('./AdaptiveComponent.vue'),
hydrate: createAdaptiveStrategy()
});// Conditional hydration based on feature detection
const AdvancedChart = defineAsyncComponent({
loader: () => import('./AdvancedChart.vue'),
hydrate: (() => {
// Only hydrate if Canvas is supported
if (typeof HTMLCanvasElement !== 'undefined') {
return hydrateOnVisible();
}
// Fallback: never hydrate (static content only)
return () => {};
})()
});
// Time-based hydration
function hydrateAfterDelay(delay: number): HydrationStrategy {
return (hydrate) => {
setTimeout(hydrate, delay);
};
}
const DelayedComponent = defineAsyncComponent({
loader: () => import('./DelayedComponent.vue'),
hydrate: hydrateAfterDelay(5000) // Hydrate after 5 seconds
});
// Hydrate based on network conditions
function hydrateOnGoodConnection(): HydrationStrategy {
return (hydrate) => {
const connection = (navigator as any).connection;
if (connection && connection.effectiveType === '4g') {
hydrateOnIdle()(hydrate, () => {});
} else {
hydrateOnInteraction('click')(hydrate, () => {});
}
};
}
const NetworkAwareComponent = defineAsyncComponent({
loader: () => import('./NetworkAwareComponent.vue'),
hydrate: hydrateOnGoodConnection()
});/**
* Hydration strategy function type
*/
interface HydrationStrategy {
(hydrate: () => void, forEachElement: (cb: (el: Element) => void) => void): void;
}
/**
* Factory function for creating hydration strategies
*/
interface HydrationStrategyFactory<T extends any[] = any[]> {
(...args: T): HydrationStrategy;
}
/**
* Intersection observer options for visibility-based hydration
*/
interface IntersectionObserverInit {
root?: Element | Document | null;
rootMargin?: string;
threshold?: number | number[];
}hydrateOnIdle: Best for non-critical components that don't need immediate interactivityhydrateOnVisible: Ideal for below-the-fold content and imageshydrateOnMediaQuery: Perfect for responsive components that only work on certain device typeshydrateOnInteraction: Excellent for interactive widgets that users might not engage withconst App = defineComponent({
components: {
// Critical: Hydrate immediately
Header: defineComponent(/* immediate hydration */),
Navigation: defineComponent(/* immediate hydration */),
// Important: Hydrate when visible
Hero: defineAsyncComponent({
loader: () => import('./Hero.vue'),
hydrate: hydrateOnVisible({ threshold: 0.1 })
}),
// Secondary: Hydrate when idle
Sidebar: defineAsyncComponent({
loader: () => import('./Sidebar.vue'),
hydrate: hydrateOnIdle(1000)
}),
// Interactive: Hydrate on interaction
ContactForm: defineAsyncComponent({
loader: () => import('./ContactForm.vue'),
hydrate: hydrateOnInteraction(['focus', 'click'])
}),
// Conditional: Hydrate based on device
MobileMenu: defineAsyncComponent({
loader: () => import('./MobileMenu.vue'),
hydrate: hydrateOnMediaQuery('(max-width: 768px)')
})
}
});Install with Tessl CLI
npx tessl i tessl/npm-vue--runtime-core