Lazy Loading & IntersectionObserver
Relevant source files
The following files were used as context for generating this wiki page:
The vitepress-plugin-chartjs implements a performance-oriented architecture that defers the initialization and rendering of Chart.js instances until they are required. This "Lazy Loading" mechanism ensures that documentation pages with multiple heavy charts remain performant and responsive by only consuming browser resources for charts currently visible to the user.
This functionality is primarily driven by the browser's IntersectionObserver API, which monitors the visibility of chart containers within the viewport. By decoupling data resolution (which happens at build time) from canvas rendering (which happens at runtime), the plugin minimizes the initial execution thread load during page navigation.
Sources: README.md:14, src/VpChart.vue:104-124, src/markdown/index.ts:169-173
Architecture and Data Flow
The lazy loading system relies on a "Data-First" architecture. All parsing, validation, and file I/O for chart configurations are performed during the build process. The result is injected into the Vue component as a pre-computed data object, which sits dormant until the IntersectionObserver triggers the initialization.
The diagram shows the lifecycle of a chart from build-time resolution to runtime lazy initialization.
Sources: src/markdown/index.ts:169-181, src/VpChart.vue:104-118
Implementation Details
IntersectionObserver Configuration
The VpChart.vue component utilizes the onMounted lifecycle hook to establish a visibility observer. This observer is configured with a rootMargin to provide a buffer, ensuring charts begin rendering slightly before they enter the user's direct view.
| Parameter | Value | Description |
|---|---|---|
rootMargin | 100px | Pre-loads the chart when it is within 100px of the viewport. |
threshold | 0 | Triggers as soon as a single pixel of the chart becomes visible. |
Sources: src/VpChart.vue:104-124
Placeholder State
Before the chart is visible, the component renders a lightweight placeholder. This prevents layout shifts by maintaining the intended chart height while displaying a "Loading chart..." message.
<template>
<div ref="wrapperRef" class="vp-chart-wrapper" :style="{ height: height }">
<canvas v-show="isVisible" ref="canvasRef" :id="id"></canvas>
<div v-show="!isVisible" class="vp-chart-placeholder">
<span>Loading chart...</span>
</div>
</div>
</template>
Sources: src/VpChart.vue:2-9
Lifecycle Sequence
When a chart container enters the viewport, the plugin follows a strict sequence to transition from placeholder to active canvas.
The sequence illustrates the transition from a dormant state to an active Chart.js instance.
Sources: src/VpChart.vue:104-124, src/VpChart.vue:81-102
Error Handling and Fallbacks
The plugin provides robust fallbacks for environments where IntersectionObserver is unavailable, such as Server-Side Rendering (SSR) or legacy browsers.
- SSR Safety: During the VitePress build process, the component checks if
windoworIntersectionObserveris defined. If not, it defaults to a visible state logic that doesn't attempt runtime DOM manipulation until the client hydrates. - Immediate Loading Fallback: If
IntersectionObserveris missing in the client browser, the component immediately setsisVisibletotrueand initializes the chart on the next tick. - HMR Support: During development, the component explicitly destroys old
Chartinstances in theinitChartfunction to prevent memory leaks and canvas collisions during Hot Module Replacement.
Sources: src/VpChart.vue:84-88, src/VpChart.vue:120-123, src/VpChart.vue:127-134
Component Properties
The lazy loading behavior is influenced by the following properties passed to the VpChart component from the markdown renderer:
| Property | Type | Default | Description |
|---|---|---|---|
id | String | Required | Unique identifier for the canvas element. |
data | Object | {} | The pre-parsed Chart.js configuration resolved at build time. |
height | String | '400px' | Controls the height of both the placeholder and the final rendered chart. |
Sources: src/VpChart.vue:23-37, src/markdown/index.ts:203-206
Conclusion
Lazy loading via IntersectionObserver is a core performance feature of vitepress-plugin-chartjs. By delaying the execution of Chart.js until visibility, it significantly reduces the JavaScript execution cost of loading documentation pages, particularly those containing complex visualizations or data-heavy external configurations.
Sources: README.md:14, example/index.md:27