Heavy third-party libraries are loaded with dynamic import() inside the components that use them — they never enter your initial bundle.
The pattern
Components that wrap a large library import it lazily inside a useEffect, initialize it against a ref, and tear it down on unmount. Because the import is dynamic, the library is code-split into its own chunk and only downloaded when the component actually mounts. Here is the shape, from Chart:
useEffect(() => {
let cancelled = false
const canvas = canvasRef.current
if (!canvas) return
const init = async () => {
const Chart = (await import('chart.js/auto')).default
if (cancelled || !canvasRef.current) return
chartRef.current = new Chart(canvas, { type, data, options })
}
init().catch(err => console.error(err))
return () => {
cancelled = true
chartRef.current?.destroy()
chartRef.current = null
}
}, [type])If you write your own plugin-backed component, follow the same rules: guard against the effect being cleaned up before the dynamic import resolves, and destroy the instance on unmount.
Install matrix
Each plugin-backed component needs its library's CSS, which you load once (CDN or a bundler import). Libraries marked Required are listed as external in the build, so you must install the npm package for the JavaScript to resolve. Libraries marked Bundled ship inside @adminlte/react's code-split chunks — installing them is optional for the JS, but you still need their CSS.
| Component(s) | npm package | JS install | CSS to load |
|---|---|---|---|
| Chart, SparklineChart | chart.js | Required | — |
| WorldMap | jsvectormap | Bundled | jsvectormap/dist/jsvectormap.min.css |
| useSortable | sortablejs | Bundled | — |
| Datatable | tabulator-tables | Required | tabulator-tables/dist/css/tabulator_bootstrap5.min.css |
| Editor | quill | Required | quill/dist/quill.snow.css |
| InputFlatpickr | flatpickr | Required | flatpickr/dist/flatpickr.min.css |
| InputTomSelect | tom-select | Required | tom-select/dist/css/tom-select.bootstrap5.min.css |
Loading plugin CSS
Load only the stylesheets for the components you use. From a CDN in your root layout:
<head>
{/* Tabulator (datatable) — Bootstrap 5 theme */}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/tabulator_bootstrap5.min.css" />
{/* jsVectorMap (world map) */}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/jsvectormap.min.css" />
</head>Or import them through your bundler:
import 'jsvectormap/dist/jsvectormap.css'
import 'quill/dist/quill.snow.css'
import 'flatpickr/dist/flatpickr.min.css'Recommended extras
AdminLTE's sidebar uses OverlayScrollbars for its custom scrollbar. It is optional — the sidebar still scrolls without it — but loading it matches the AdminLTE look:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/styles/overlayscrollbars.min.css" />
{/* ...at end of <body>: */}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/browser/overlayscrollbars.browser.es6.min.js" />