ListView JavaScript Performante nel 2026: Windowing, Virtualizzazione e Ottimizzazione delle Prestazioni
Scopri come creare ListView JavaScript ad alte prestazioni con windowing e virtualizzazione. TanStack Virtual, React Virtualized e tecniche avanzate per il 2026.

Le applicazioni web moderne devono spesso visualizzare migliaia o addirittura centinaia di migliaia di record in liste. Che si tratti di cataloghi e-commerce, feed di social media o dashboard amministrative, le prestazioni di una ListView possono influenzare drasticamente l'esperienza utente. Questo articolo esplora le tecniche più recenti per ottimizzare le ListView JavaScript nel 2026.
La virtualizzazione può ridurre il consumo di memoria fino al 95% per liste con oltre 10.000 elementi, garantendo al contempo uno scrolling fluido.
Il Problema delle Liste di Grandi Dimensioni
Quando un'applicazione renderizza una lista con diecimila elementi, il browser crea nodi DOM per ciascuno di essi. Questo comporta problemi significativi:
- Elevato consumo di memoria: Ogni nodo DOM richiede memoria
- Tempo di rendering iniziale lento: Creare migliaia di elementi richiede tempo
- Prestazioni di scrolling scadenti: Il browser deve gestire tutti gli elementi
- Layout thrashing: Ricalcoli frequenti del layout
// Implementazione naive - NON consigliata per liste grandi
function NaiveList({ items }: { items: Item[] }) {
return (
<div className="list-container">
{items.map((item) => (
<div key={item.id} className="list-item">
<h3>{item.title}</h3>
<p>{item.description}</p>
</div>
))}
</div>
);
}Windowing come Soluzione
Il windowing, noto anche come "scrolling virtuale", è una tecnica in cui vengono renderizzati solo gli elementi visibili più un piccolo buffer sopra e sotto. Gli elementi rimanenti vengono creati solo quando necessario.
import { useVirtualizer } from '@tanstack/react-virtual';
function VirtualizedList({ items }: { items: Item[] }) {
const parentRef = useRef<HTMLDivElement>(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 80,
overscan: 5,
});
return (
<div ref={parentRef} className="h-[600px] overflow-auto">
<div
style={{
height: `${virtualizer.getTotalSize()}px`,
width: '100%',
position: 'relative',
}}
>
{virtualizer.getVirtualItems().map((virtualItem) => (
<div
key={virtualItem.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}}
>
<ListItem item={items[virtualItem.index]} />
</div>
))}
</div>
</div>
);
}TanStack Virtual: Lo Standard Moderno
TanStack Virtual (precedentemente React Virtual) si è affermato nel 2026 come la soluzione principale per la virtualizzazione nelle applicazioni React. La libreria offre funzionalità core framework-agnostic con adapter specifici per React, Vue, Solid e altri framework.
import { useVirtualizer, VirtualizerOptions } from '@tanstack/react-virtual';
interface ListProps<T> {
items: T[];
renderItem: (item: T, index: number) => React.ReactNode;
itemHeight?: number | ((index: number) => number);
overscan?: number;
}
function HighPerformanceList<T extends { id: string }>({
items,
renderItem,
itemHeight = 80,
overscan = 10
}: ListProps<T>) {
const parentRef = useRef<HTMLDivElement>(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: typeof itemHeight === 'function'
? itemHeight
: () => itemHeight,
overscan,
measureElement: (element) => element.getBoundingClientRect().height,
});
const virtualItems = virtualizer.getVirtualItems();
return (
<div
ref={parentRef}
className="h-full overflow-auto will-change-transform"
>
<div
className="relative w-full"
style={{ height: `${virtualizer.getTotalSize()}px` }}
>
{virtualItems.map((virtualItem) => (
<div
key={items[virtualItem.index].id}
ref={virtualizer.measureElement}
data-index={virtualItem.index}
className="absolute top-0 left-0 w-full"
style={{
transform: `translateY(${virtualItem.start}px)`,
}}
>
{renderItem(items[virtualItem.index], virtualItem.index)}
</div>
))}
</div>
</div>
);
}Altezze Dinamiche degli Elementi
Una delle sfide maggiori nella virtualizzazione sono le liste con elementi di altezza variabile. TanStack Virtual offre la funzione measureElement che misura la dimensione effettiva di ogni elemento.
function DynamicHeightList({ items }: { items: Post[] }) {
const parentRef = useRef<HTMLDivElement>(null);
const measurementsCache = useRef<Map<string, number>>(new Map());
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: (index) => {
const cached = measurementsCache.current.get(items[index].id);
if (cached) return cached;
// Stima basata sulla lunghezza del contenuto
const contentLength = items[index].content.length;
return Math.max(100, Math.min(400, contentLength * 0.5));
},
measureElement: (element) => {
const height = element.getBoundingClientRect().height;
const id = element.getAttribute('data-id');
if (id) {
measurementsCache.current.set(id, height);
}
return height;
},
overscan: 5,
});
return (
<div ref={parentRef} className="h-screen overflow-auto">
<div
style={{
height: `${virtualizer.getTotalSize()}px`,
position: 'relative',
}}
>
{virtualizer.getVirtualItems().map((virtualItem) => {
const item = items[virtualItem.index];
return (
<div
key={item.id}
ref={virtualizer.measureElement}
data-index={virtualItem.index}
data-id={item.id}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
transform: `translateY(${virtualItem.start}px)`,
}}
>
<PostCard post={item} />
</div>
);
})}
</div>
</div>
);
}Infinite Scrolling con Virtualizzazione
La combinazione di virtualizzazione con infinite scrolling consente il caricamento e la visualizzazione di quantità illimitate di dati con prestazioni ottimali.
import { useInfiniteQuery } from '@tanstack/react-query';
import { useVirtualizer } from '@tanstack/react-virtual';
function InfiniteVirtualList() {
const parentRef = useRef<HTMLDivElement>(null);
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
} = useInfiniteQuery({
queryKey: ['items'],
queryFn: ({ pageParam = 0 }) => fetchItems(pageParam),
getNextPageParam: (lastPage) => lastPage.nextCursor,
initialPageParam: 0,
});
const allItems = useMemo(
() => data?.pages.flatMap((page) => page.items) ?? [],
[data]
);
const virtualizer = useVirtualizer({
count: hasNextPage ? allItems.length + 1 : allItems.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 80,
overscan: 10,
});
const virtualItems = virtualizer.getVirtualItems();
useEffect(() => {
const lastItem = virtualItems[virtualItems.length - 1];
if (!lastItem) return;
if (
lastItem.index >= allItems.length - 1 &&
hasNextPage &&
!isFetchingNextPage
) {
fetchNextPage();
}
}, [virtualItems, allItems.length, hasNextPage, isFetchingNextPage, fetchNextPage]);
return (
<div ref={parentRef} className="h-[600px] overflow-auto">
<div
style={{
height: `${virtualizer.getTotalSize()}px`,
position: 'relative',
}}
>
{virtualItems.map((virtualItem) => {
const isLoader = virtualItem.index >= allItems.length;
return (
<div
key={virtualItem.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}}
>
{isLoader ? (
<div className="flex items-center justify-center h-full">
<Spinner />
</div>
) : (
<ItemRow item={allItems[virtualItem.index]} />
)}
</div>
);
})}
</div>
</div>
);
}Ottimizzazioni delle Prestazioni
Oltre alla virtualizzazione, esistono altre tecniche per migliorare le prestazioni delle ListView.
Memoization degli Elementi della Lista
const MemoizedListItem = memo(
function ListItem({ item }: { item: Item }) {
return (
<div className="p-4 border-b border-gray-200">
<h3 className="font-medium">{item.title}</h3>
<p className="text-gray-600">{item.description}</p>
</div>
);
},
(prevProps, nextProps) => prevProps.item.id === nextProps.item.id
);Ottimizzazioni CSS
.list-container {
contain: strict;
will-change: transform;
}
.list-item {
contain: layout style paint;
content-visibility: auto;
contain-intrinsic-size: 0 80px;
}Content-Visibility per Liste Non Virtualizzate
function OptimizedStaticList({ items }: { items: Item[] }) {
return (
<div className="list-container">
{items.map((item) => (
<div
key={item.id}
className="list-item"
style={{
contentVisibility: 'auto',
containIntrinsicSize: '0 80px',
}}
>
<ListItemContent item={item} />
</div>
))}
</div>
);
}Virtualizzazione Orizzontale e Griglie
TanStack Virtual supporta anche la virtualizzazione orizzontale e griglie bidimensionali.
function VirtualizedGrid({ items, columns = 4 }: { items: Item[]; columns?: number }) {
const parentRef = useRef<HTMLDivElement>(null);
const rows = Math.ceil(items.length / columns);
const rowVirtualizer = useVirtualizer({
count: rows,
getScrollElement: () => parentRef.current,
estimateSize: () => 200,
overscan: 2,
});
const columnVirtualizer = useVirtualizer({
horizontal: true,
count: columns,
getScrollElement: () => parentRef.current,
estimateSize: () => 250,
overscan: 1,
});
return (
<div ref={parentRef} className="h-[600px] overflow-auto">
<div
style={{
height: `${rowVirtualizer.getTotalSize()}px`,
width: `${columnVirtualizer.getTotalSize()}px`,
position: 'relative',
}}
>
{rowVirtualizer.getVirtualItems().map((virtualRow) => (
<Fragment key={virtualRow.key}>
{columnVirtualizer.getVirtualItems().map((virtualColumn) => {
const itemIndex = virtualRow.index * columns + virtualColumn.index;
if (itemIndex >= items.length) return null;
return (
<div
key={virtualColumn.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: `${virtualColumn.size}px`,
height: `${virtualRow.size}px`,
transform: `translateX(${virtualColumn.start}px) translateY(${virtualRow.start}px)`,
}}
>
<GridItem item={items[itemIndex]} />
</div>
);
})}
</Fragment>
))}
</div>
</div>
);
}Pronto a superare i tuoi colloqui su Node.js / NestJS?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
Debugging e Monitoring
Per identificare problemi di prestazioni, è possibile monitorare diverse metriche.
function useVirtualListMetrics(virtualizer: Virtualizer<HTMLDivElement, Element>) {
const [metrics, setMetrics] = useState({
renderedCount: 0,
totalCount: 0,
scrollOffset: 0,
visibleRange: { start: 0, end: 0 },
});
useEffect(() => {
const updateMetrics = () => {
const virtualItems = virtualizer.getVirtualItems();
setMetrics({
renderedCount: virtualItems.length,
totalCount: virtualizer.options.count,
scrollOffset: virtualizer.scrollOffset ?? 0,
visibleRange: {
start: virtualItems[0]?.index ?? 0,
end: virtualItems[virtualItems.length - 1]?.index ?? 0,
},
});
};
updateMetrics();
const unsubscribe = virtualizer.scrollElement?.addEventListener(
'scroll',
updateMetrics
);
return () => {
virtualizer.scrollElement?.removeEventListener('scroll', updateMetrics as any);
};
}, [virtualizer]);
return metrics;
}Conclusione
L'implementazione di ListView performanti in JavaScript nel 2026 richiede una solida comprensione delle tecniche di virtualizzazione. TanStack Virtual offre una soluzione matura e type-safe che si integra perfettamente nelle applicazioni React moderne. Combinando il windowing con memoization, CSS containment e strategie di caricamento intelligenti, è possibile visualizzare in modo fluido anche liste con centinaia di migliaia di elementi. Le tecniche presentate sono essenziali per qualsiasi applicazione web data-intensive e dovrebbero far parte del repertorio standard dello sviluppo frontend moderno.
Sapresti trovare il bug in Node.js / NestJS?
Uno snippet reale, un bug nascosto, un tentativo al giorno. Senza account per provare.

Scritto da
Anthony Fillion-MailletFondatore di SharpSkill
Sviluppatore fullstack da oltre 10 anni. Guida SharpSkill e risponde di tutto ciò che vi viene pubblicato.
Aggiornato il 15 settembre 2026
Condividi
Articoli correlati

NestJS e Redis nel 2026: Caching, Sessioni e Domande per Colloqui Tecnici
Integrazione Redis in NestJS con @nestjs/cache-manager, gestione delle sessioni con connect-redis e domande frequenti nei colloqui per sviluppatori Node.js backend.

High Performance JavaScript ListView nel 2026: Tecniche di Virtualizzazione e Ottimizzazione
Scopri come sviluppare ListView ad alte prestazioni con JavaScript list virtualization e React Virtualized. Deep-dive nelle tecniche di ottimizzazione del rendering.

NestJS e MongoDB nel 2026: Mongoose, Aggregazioni e Domande da Colloquio
Guida pratica a NestJS 12 con MongoDB e Mongoose 9: design degli schema, pipeline di aggregazione, transazioni e domande tecniche per colloqui backend.