UNPKG

gentelella

Version:

Gentelella Admin is a free to use Bootstrap admin template

811 lines (583 loc) 91.2 kB
<!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <link rel="stylesheet" href="/gentelella/assets/css/just-the-docs-default.css"> <link rel="stylesheet" href="/gentelella/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet"> <style id="jtd-nav-activation"> .site-nav > ul.nav-list:first-child > li:not(:nth-child(5)) > a, .site-nav > ul.nav-list:first-child > li > ul > li a { background-image: none; } .site-nav > ul.nav-list:not(:first-child) a, .site-nav li.external a { background-image: none; } .site-nav > ul.nav-list:first-child > li:nth-child(5) > a { font-weight: 600; text-decoration: none; }.site-nav > ul.nav-list:first-child > li:nth-child(5) > button svg { transform: rotate(-90deg); }.site-nav > ul.nav-list:first-child > li.nav-list-item:nth-child(5) > ul.nav-list { display: block; } </style> <script src="/gentelella/assets/js/vendor/lunr.min.js"></script> <script src="/gentelella/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/gentelella/favicon.ico" type="image/x-icon"> <!-- Begin Jekyll SEO tag v2.8.0 --> <title>Performance Guide | Gentelella Admin Template</title> <meta name="generator" content="Jekyll v3.9.5" /> <meta property="og:title" content="Performance Guide" /> <meta property="og:locale" content="en_US" /> <meta name="description" content="Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations" /> <meta property="og:description" content="Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations" /> <link rel="canonical" href="http://localhost:4000/gentelella/performance/" /> <meta property="og:url" content="http://localhost:4000/gentelella/performance/" /> <meta property="og:site_name" content="Gentelella Admin Template" /> <meta property="og:image" content="http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg" /> <meta property="og:type" content="website" /> <meta name="twitter:card" content="summary_large_image" /> <meta property="twitter:image" content="http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg" /> <meta property="twitter:title" content="Performance Guide" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations","headline":"Performance Guide","image":"http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg","url":"http://localhost:4000/gentelella/performance/"}</script> <!-- End Jekyll SEO tag --> </head> <body> <a class="skip-to-main" href="#main-content">Skip to main content</a> <svg xmlns="http://www.w3.org/2000/svg" class="d-none"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE --> <symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link"> <title id="svg-external-link-title">(external link)</title> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md --> <symbol id="svg-copy" viewBox="0 0 16 16"> <title>Copy</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/> <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/> </svg> </symbol> <symbol id="svg-copied" viewBox="0 0 16 16"> <title>Copied</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16"> <path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/> </svg> </symbol> </svg> <div class="side-bar"> <div class="site-header" role="banner"> <a href="/gentelella/" class="site-title lh-tight"> Gentelella Admin Template </a> <button id="menu-button" class="site-button btn-reset" aria-label="Toggle menu" aria-pressed="false"> <svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg> </button> </div> <nav aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item"><a href="/gentelella/" class="nav-list-link">Gentelella Admin Template Documentation</a></li><li class="nav-list-item"><a href="/gentelella/installation/" class="nav-list-link">Installation Guide</a></li><li class="nav-list-item"><a href="/gentelella/configuration/" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/gentelella/components/" class="nav-list-link">Components Guide</a></li><li class="nav-list-item"><a href="/gentelella/performance/" class="nav-list-link">Performance Guide</a></li><li class="nav-list-item"><a href="/gentelella/deployment/" class="nav-list-link">Deployment Guide</a></li><li class="nav-list-item"><a href="/gentelella/customization/" class="nav-list-link">Customization Guide</a></li><li class="nav-list-item"><a href="/gentelella/api-integration/" class="nav-list-link">API Integration</a></li></ul> </nav> <footer class="site-footer"> This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </footer> </div> <div class="main" id="top"> <div id="main-header" class="main-header"> <div class="search" role="search"> <div class="search-input-wrap"> <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search Gentelella Admin Template" aria-label="Search Gentelella Admin Template" autocomplete="off"> <label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label> </div> <div id="search-results" class="search-results"></div> </div> <nav aria-label="Auxiliary" class="aux-nav"> <ul class="aux-nav-list"> <li class="aux-nav-list-item"> <a href="//github.com/puikinsh/gentelella" class="site-button" > Gentelella on GitHub </a> </li> <li class="aux-nav-list-item"> <a href="//colorlib.com" class="site-button" > Colorlib </a> </li> </ul> </nav> </div> <div class="main-content-wrap"> <div id="main-content" class="main-content"> <main> <h1 class="no_toc" id="performance-optimization"> <a href="#performance-optimization" class="anchor-heading" aria-labelledby="performance-optimization"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Performance Optimization </h1> <p class="fs-6 fw-300">Complete guide to optimizing Gentelella Admin Template for maximum performance</p> <h2 class="no_toc text-delta" id="table-of-contents"> <a href="#table-of-contents" class="anchor-heading" aria-labelledby="table-of-contents"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Table of contents </h2> <ol id="markdown-toc"> <li><a href="#performance-overview" id="markdown-toc-performance-overview">Performance Overview</a> <ol> <li><a href="#performance-metrics" id="markdown-toc-performance-metrics">Performance Metrics</a></li> </ol> </li> <li><a href="#smart-loading-system" id="markdown-toc-smart-loading-system">Smart Loading System</a> <ol> <li><a href="#core-vs-module-architecture" id="markdown-toc-core-vs-module-architecture">Core vs. Module Architecture</a> <ol> <li><a href="#core-bundle-79kb---always-loaded" id="markdown-toc-core-bundle-79kb---always-loaded">Core Bundle (79KB) - Always Loaded</a></li> <li><a href="#conditional-modules---loaded-on-demand" id="markdown-toc-conditional-modules---loaded-on-demand">Conditional Modules - Loaded on Demand</a></li> </ol> </li> <li><a href="#module-loading-strategy" id="markdown-toc-module-loading-strategy">Module Loading Strategy</a></li> </ol> </li> <li><a href="#bundle-optimization" id="markdown-toc-bundle-optimization">Bundle Optimization</a> <ol> <li><a href="#manual-chunk-splitting" id="markdown-toc-manual-chunk-splitting">Manual Chunk Splitting</a></li> <li><a href="#tree-shaking" id="markdown-toc-tree-shaking">Tree Shaking</a></li> </ol> </li> <li><a href="#asset-optimization" id="markdown-toc-asset-optimization">Asset Optimization</a> <ol> <li><a href="#image-optimization" id="markdown-toc-image-optimization">Image Optimization</a> <ol> <li><a href="#responsive-images" id="markdown-toc-responsive-images">Responsive Images</a></li> <li><a href="#webp-format-with-fallback" id="markdown-toc-webp-format-with-fallback">WebP Format with Fallback</a></li> <li><a href="#lazy-loading" id="markdown-toc-lazy-loading">Lazy Loading</a></li> </ol> </li> <li><a href="#font-optimization" id="markdown-toc-font-optimization">Font Optimization</a> <ol> <li><a href="#font-loading-strategy" id="markdown-toc-font-loading-strategy">Font Loading Strategy</a></li> <li><a href="#subset-fonts" id="markdown-toc-subset-fonts">Subset Fonts</a></li> </ol> </li> </ol> </li> <li><a href="#caching-strategies" id="markdown-toc-caching-strategies">Caching Strategies</a> <ol> <li><a href="#browser-caching" id="markdown-toc-browser-caching">Browser Caching</a> <ol> <li><a href="#vite-asset-hashing" id="markdown-toc-vite-asset-hashing">Vite Asset Hashing</a></li> <li><a href="#service-worker-implementation" id="markdown-toc-service-worker-implementation">Service Worker Implementation</a></li> </ol> </li> <li><a href="#cdn-integration" id="markdown-toc-cdn-integration">CDN Integration</a></li> </ol> </li> <li><a href="#runtime-performance" id="markdown-toc-runtime-performance">Runtime Performance</a> <ol> <li><a href="#efficient-dom-manipulation" id="markdown-toc-efficient-dom-manipulation">Efficient DOM Manipulation</a> <ol> <li><a href="#batch-dom-updates" id="markdown-toc-batch-dom-updates">Batch DOM Updates</a></li> <li><a href="#event-delegation" id="markdown-toc-event-delegation">Event Delegation</a></li> </ol> </li> <li><a href="#memory-management" id="markdown-toc-memory-management">Memory Management</a> <ol> <li><a href="#cleanup-event-listeners" id="markdown-toc-cleanup-event-listeners">Cleanup Event Listeners</a></li> <li><a href="#debounce-expensive-operations" id="markdown-toc-debounce-expensive-operations">Debounce Expensive Operations</a></li> </ol> </li> </ol> </li> <li><a href="#monitoring-and-analysis" id="markdown-toc-monitoring-and-analysis">Monitoring and Analysis</a> <ol> <li><a href="#performance-monitoring" id="markdown-toc-performance-monitoring">Performance Monitoring</a> <ol> <li><a href="#core-web-vitals" id="markdown-toc-core-web-vitals">Core Web Vitals</a></li> <li><a href="#performance-observer" id="markdown-toc-performance-observer">Performance Observer</a></li> </ol> </li> <li><a href="#bundle-analysis" id="markdown-toc-bundle-analysis">Bundle Analysis</a> <ol> <li><a href="#webpack-bundle-analyzer" id="markdown-toc-webpack-bundle-analyzer">Webpack Bundle Analyzer</a></li> <li><a href="#lighthouse-ci" id="markdown-toc-lighthouse-ci">Lighthouse CI</a></li> </ol> </li> </ol> </li> <li><a href="#performance-checklist" id="markdown-toc-performance-checklist">Performance Checklist</a> <ol> <li><a href="#development-phase" id="markdown-toc-development-phase">Development Phase</a></li> <li><a href="#asset-optimization-1" id="markdown-toc-asset-optimization-1">Asset Optimization</a></li> <li><a href="#caching-strategy" id="markdown-toc-caching-strategy">Caching Strategy</a></li> <li><a href="#runtime-performance-1" id="markdown-toc-runtime-performance-1">Runtime Performance</a></li> <li><a href="#monitoring" id="markdown-toc-monitoring">Monitoring</a></li> </ol> </li> <li><a href="#advanced-optimization-techniques" id="markdown-toc-advanced-optimization-techniques">Advanced Optimization Techniques</a> <ol> <li><a href="#preloading-strategies" id="markdown-toc-preloading-strategies">Preloading Strategies</a> <ol> <li><a href="#module-preloading" id="markdown-toc-module-preloading">Module Preloading</a></li> <li><a href="#predictive-loading" id="markdown-toc-predictive-loading">Predictive Loading</a></li> </ol> </li> <li><a href="#critical-path-optimization" id="markdown-toc-critical-path-optimization">Critical Path Optimization</a> <ol> <li><a href="#critical-css-inlining" id="markdown-toc-critical-css-inlining">Critical CSS Inlining</a></li> <li><a href="#resource-hints" id="markdown-toc-resource-hints">Resource Hints</a></li> </ol> </li> </ol> </li> <li><a href="#next-steps" id="markdown-toc-next-steps">Next Steps</a></li> </ol><hr /> <h2 id="performance-overview"> <a href="#performance-overview" class="anchor-heading" aria-labelledby="performance-overview"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Performance Overview </h2> <p>Gentelella v2.0 includes significant performance improvements over the original version:</p> <h3 id="performance-metrics"> <a href="#performance-metrics" class="anchor-heading" aria-labelledby="performance-metrics"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Performance Metrics </h3> <div class="table-wrapper"><table> <thead> <tr> <th>Metric</th> <th>v1.0</th> <th>v2.0</th> <th>Improvement</th> </tr> </thead> <tbody> <tr> <td><strong>Initial Bundle Size</strong></td> <td>779 KB</td> <td>79 KB</td> <td><strong>90% smaller</strong></td> </tr> <tr> <td><strong>Total Page Load</strong></td> <td>1.3 MB</td> <td>770 KB</td> <td><strong>40% reduction</strong></td> </tr> <tr> <td><strong>First Contentful Paint</strong></td> <td>2.1s</td> <td>0.8s</td> <td><strong>62% faster</strong></td> </tr> <tr> <td><strong>Time to Interactive</strong></td> <td>3.5s</td> <td>1.2s</td> <td><strong>66% faster</strong></td> </tr> <tr> <td><strong>Largest Contentful Paint</strong></td> <td>2.8s</td> <td>1.1s</td> <td><strong>61% faster</strong></td> </tr> <tr> <td><strong>Cumulative Layout Shift</strong></td> <td>0.15</td> <td>0.03</td> <td><strong>80% improvement</strong></td> </tr> </tbody> </table></div><hr /> <h2 id="smart-loading-system"> <a href="#smart-loading-system" class="anchor-heading" aria-labelledby="smart-loading-system"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Smart Loading System </h2> <h3 id="core-vs-module-architecture"> <a href="#core-vs-module-architecture" class="anchor-heading" aria-labelledby="core-vs-module-architecture"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Core vs. Module Architecture </h3> <p>The template uses a two-tier loading system:</p> <h4 id="core-bundle-79kb---always-loaded"> <a href="#core-bundle-79kb---always-loaded" class="anchor-heading" aria-labelledby="core-bundle-79kb---always-loaded"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Core Bundle (79KB) - Always Loaded </h4> <p>Essential functionality that every page needs:</p> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/main-core.js</span> <span class="k">import</span> <span class="dl">'</span><span class="s1">bootstrap/dist/js/bootstrap.bundle.min.js</span><span class="dl">'</span><span class="p">;</span> <span class="k">import</span> <span class="dl">'</span><span class="s1">./js/custom.min.js</span><span class="dl">'</span><span class="p">;</span> <span class="c1">// Initialize tooltips and popovers</span> <span class="nb">document</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">DOMContentLoaded</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// Bootstrap components initialization</span> <span class="kd">const</span> <span class="nx">tooltips</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="dl">'</span><span class="s1">[data-bs-toggle="tooltip"]</span><span class="dl">'</span><span class="p">);</span> <span class="nx">tooltips</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">tooltip</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nx">bootstrap</span><span class="p">.</span><span class="nx">Tooltip</span><span class="p">(</span><span class="nx">tooltip</span><span class="p">));</span> <span class="kd">const</span> <span class="nx">popovers</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="dl">'</span><span class="s1">[data-bs-toggle="popover"]</span><span class="dl">'</span><span class="p">);</span> <span class="nx">popovers</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">popover</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nx">bootstrap</span><span class="p">.</span><span class="nx">Popover</span><span class="p">(</span><span class="nx">popover</span><span class="p">));</span> <span class="p">});</span> </code></pre></div></div> <h4 id="conditional-modules---loaded-on-demand"> <a href="#conditional-modules---loaded-on-demand" class="anchor-heading" aria-labelledby="conditional-modules---loaded-on-demand"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Conditional Modules - Loaded on Demand </h4> <p><strong>Charts Module</strong> (219KB)</p> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Only loads when chart elements are detected</span> <span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.chart-container</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">charts</span> <span class="o">=</span> <span class="k">await</span> <span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">./modules/charts.js</span><span class="dl">'</span><span class="p">);</span> <span class="nx">charts</span><span class="p">.</span><span class="nx">initializeCharts</span><span class="p">();</span> <span class="p">}</span> </code></pre></div></div> <p><strong>Forms Module</strong> (200KB)</p> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Only loads on pages with enhanced forms</span> <span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.select2, .datepicker, .form-wizard</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">forms</span> <span class="o">=</span> <span class="k">await</span> <span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">./modules/forms.js</span><span class="dl">'</span><span class="p">);</span> <span class="nx">forms</span><span class="p">.</span><span class="nx">initializeForms</span><span class="p">();</span> <span class="p">}</span> </code></pre></div></div> <p><strong>Tables Module</strong></p> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Only loads when DataTables are needed</span> <span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.datatable</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">tables</span> <span class="o">=</span> <span class="k">await</span> <span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">./modules/tables.js</span><span class="dl">'</span><span class="p">);</span> <span class="nx">tables</span><span class="p">.</span><span class="nx">initializeTables</span><span class="p">();</span> <span class="p">}</span> </code></pre></div></div> <h3 id="module-loading-strategy"> <a href="#module-loading-strategy" class="anchor-heading" aria-labelledby="module-loading-strategy"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Module Loading Strategy </h3> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Smart module detection and loading</span> <span class="k">export</span> <span class="k">async</span> <span class="kd">function</span> <span class="nx">loadRequiredModules</span><span class="p">()</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">modules</span> <span class="o">=</span> <span class="p">[];</span> <span class="c1">// Check for chart requirements</span> <span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">canvas, .morris-chart, .sparkline</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span> <span class="nx">modules</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">./modules/charts.js</span><span class="dl">'</span><span class="p">));</span> <span class="p">}</span> <span class="c1">// Check for form enhancements</span> <span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.select2, .datepicker, .ion-range-slider</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span> <span class="nx">modules</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">./modules/forms.js</span><span class="dl">'</span><span class="p">));</span> <span class="p">}</span> <span class="c1">// Check for table features</span> <span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.datatable, table[data-table]</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span> <span class="nx">modules</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">./modules/tables.js</span><span class="dl">'</span><span class="p">));</span> <span class="p">}</span> <span class="c1">// Check for dashboard widgets</span> <span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.dashboard-widget, .tile_count</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span> <span class="nx">modules</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">./modules/dashboard.js</span><span class="dl">'</span><span class="p">));</span> <span class="p">}</span> <span class="c1">// Load all required modules in parallel</span> <span class="kd">const</span> <span class="nx">loadedModules</span> <span class="o">=</span> <span class="k">await</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span><span class="nx">modules</span><span class="p">);</span> <span class="c1">// Initialize each module</span> <span class="nx">loadedModules</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">module</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="nx">module</span><span class="p">.</span><span class="nx">initialize</span><span class="p">)</span> <span class="p">{</span> <span class="nx">module</span><span class="p">.</span><span class="nx">initialize</span><span class="p">();</span> <span class="p">}</span> <span class="p">});</span> <span class="p">}</span> </code></pre></div></div><hr /> <h2 id="bundle-optimization"> <a href="#bundle-optimization" class="anchor-heading" aria-labelledby="bundle-optimization"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Bundle Optimization </h2> <h3 id="manual-chunk-splitting"> <a href="#manual-chunk-splitting" class="anchor-heading" aria-labelledby="manual-chunk-splitting"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Manual Chunk Splitting </h3> <p>The Vite configuration includes optimized chunk splitting:</p> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// vite.config.js</span> <span class="k">export</span> <span class="k">default</span> <span class="nx">defineConfig</span><span class="p">({</span> <span class="na">build</span><span class="p">:</span> <span class="p">{</span> <span class="na">rollupOptions</span><span class="p">:</span> <span class="p">{</span> <span class="na">output</span><span class="p">:</span> <span class="p">{</span> <span class="na">manualChunks</span><span class="p">:</span> <span class="p">{</span> <span class="c1">// Core vendor libraries (loaded on every page)</span> <span class="dl">'</span><span class="s1">vendor-core</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span> <span class="dl">'</span><span class="s1">bootstrap</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">@popperjs/core</span><span class="dl">'</span> <span class="p">],</span> <span class="c1">// Chart libraries (loaded only when needed)</span> <span class="dl">'</span><span class="s1">vendor-charts</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span> <span class="dl">'</span><span class="s1">chart.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">morris.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">gauge.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">jquery-sparkline</span><span class="dl">'</span> <span class="p">],</span> <span class="c1">// Form enhancement libraries</span> <span class="dl">'</span><span class="s1">vendor-forms</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span> <span class="dl">'</span><span class="s1">select2</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">tempus-dominus</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">ion-rangeslider</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">switchery</span><span class="dl">'</span> <span class="p">],</span> <span class="c1">// Table functionality</span> <span class="dl">'</span><span class="s1">vendor-tables</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span> <span class="dl">'</span><span class="s1">datatables.net</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">datatables.net-bs5</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">datatables.net-responsive</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">datatables.net-buttons</span><span class="dl">'</span> <span class="p">],</span> <span class="c1">// Utility libraries</span> <span class="dl">'</span><span class="s1">vendor-utils</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span> <span class="dl">'</span><span class="s1">dayjs</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">nprogress</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">autosize</span><span class="dl">'</span> <span class="p">]</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> <span class="p">});</span> </code></pre></div></div> <h3 id="tree-shaking"> <a href="#tree-shaking" class="anchor-heading" aria-labelledby="tree-shaking"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Tree Shaking </h3> <p>Import only what you need:</p> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// ❌ Bad - imports entire library</span> <span class="k">import</span> <span class="o">*</span> <span class="k">as</span> <span class="nx">dayjs</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">dayjs</span><span class="dl">'</span><span class="p">;</span> <span class="c1">// ✅ Good - imports only specific functions</span> <span class="k">import</span> <span class="nx">dayjs</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">dayjs</span><span class="dl">'</span><span class="p">;</span> <span class="k">import</span> <span class="nx">customParseFormat</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">dayjs/plugin/customParseFormat</span><span class="dl">'</span><span class="p">;</span> <span class="c1">// ❌ Bad - imports entire Chart.js</span> <span class="k">import</span> <span class="nx">Chart</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">chart.js</span><span class="dl">'</span><span class="p">;</span> <span class="c1">// ✅ Good - imports only needed components</span> <span class="k">import</span> <span class="p">{</span> <span class="nx">Chart</span><span class="p">,</span> <span class="nx">CategoryScale</span><span class="p">,</span> <span class="nx">LinearScale</span><span class="p">,</span> <span class="nx">PointElement</span><span class="p">,</span> <span class="nx">LineElement</span><span class="p">,</span> <span class="nx">Title</span><span class="p">,</span> <span class="nx">Tooltip</span><span class="p">,</span> <span class="nx">Legend</span><span class="p">,</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">chart.js</span><span class="dl">'</span><span class="p">;</span> <span class="nx">Chart</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span> <span class="nx">CategoryScale</span><span class="p">,</span> <span class="nx">LinearScale</span><span class="p">,</span> <span class="nx">PointElement</span><span class="p">,</span> <span class="nx">LineElement</span><span class="p">,</span> <span class="nx">Title</span><span class="p">,</span> <span class="nx">Tooltip</span><span class="p">,</span> <span class="nx">Legend</span> <span class="p">);</span> </code></pre></div></div><hr /> <h2 id="asset-optimization"> <a href="#asset-optimization" class="anchor-heading" aria-labelledby="asset-optimization"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Asset Optimization </h2> <h3 id="image-optimization"> <a href="#image-optimization" class="anchor-heading" aria-labelledby="image-optimization"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Image Optimization </h3> <h4 id="responsive-images"> <a href="#responsive-images" class="anchor-heading" aria-labelledby="responsive-images"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Responsive Images </h4> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Use responsive images with srcset --&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"images/thumb-400.jpg"</span> <span class="na">srcset=</span><span class="s">"images/thumb-400.jpg 400w, images/thumb-800.jpg 800w, images/thumb-1200.jpg 1200w"</span> <span class="na">sizes=</span><span class="s">"(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"</span> <span class="na">alt=</span><span class="s">"Dashboard preview"</span> <span class="na">loading=</span><span class="s">"lazy"</span><span class="nt">&gt;</span> </code></pre></div></div> <h4 id="webp-format-with-fallback"> <a href="#webp-format-with-fallback" class="anchor-heading" aria-labelledby="webp-format-with-fallback"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> WebP Format with Fallback </h4> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;picture&gt;</span> <span class="nt">&lt;source</span> <span class="na">srcset=</span><span class="s">"images/dashboard.webp"</span> <span class="na">type=</span><span class="s">"image/webp"</span><span class="nt">&gt;</span> <span class="nt">&lt;source</span> <span class="na">srcset=</span><span class="s">"images/dashboard.jpg"</span> <span class="na">type=</span><span class="s">"image/jpeg"</span><span class="nt">&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"images/dashboard.jpg"</span> <span class="na">alt=</span><span class="s">"Dashboard"</span> <span class="na">loading=</span><span class="s">"lazy"</span><span class="nt">&gt;</span> <span class="nt">&lt;/picture&gt;</span> </code></pre></div></div> <h4 id="lazy-loading"> <a href="#lazy-loading" class="anchor-heading" aria-labelledby="lazy-loading"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Lazy Loading </h4> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Native lazy loading --&gt;</span> <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"images/placeholder.jpg"</span> <span class="na">data-src=</span><span class="s">"images/actual-image.jpg"</span> <span class="na">loading=</span><span class="s">"lazy"</span> <span class="na">alt=</span><span class="s">"Description"</span><span class="nt">&gt;</span> <span class="c">&lt;!-- Intersection Observer approach --&gt;</span> <span class="nt">&lt;img</span> <span class="na">class=</span><span class="s">"lazy"</span> <span class="na">src=</span><span class="s">"images/placeholder.jpg"</span> <span class="na">data-src=</span><span class="s">"images/actual-image.jpg"</span> <span class="na">alt=</span><span class="s">"Description"</span><span class="nt">&gt;</span> </code></pre></div></div> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Lazy loading implementation</span> <span class="kd">const</span> <span class="nx">imageObserver</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">IntersectionObserver</span><span class="p">((</span><span class="nx">entries</span><span class="p">,</span> <span class="nx">observer</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">entries</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">entry</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="nx">entry</span><span class="p">.</span><span class="nx">isIntersecting</span><span class="p">)</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">entry</span><span class="p">.</span><span class="nx">target</span><span class="p">;</span> <span class="nx">img</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="nx">img</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">src</span><span class="p">;</span> <span class="nx">img</span><span class="p">.</span><span class="nx">classList</span><span class="p">.</span><span class="nx">remove</span><span class="p">(</span><span class="dl">'</span><span class="s1">lazy</span><span class="dl">'</span><span class="p">);</span> <span class="nx">observer</span><span class="p">.</span><span class="nx">unobserve</span><span class="p">(</span><span class="nx">img</span><span class="p">);</span> <span class="p">}</span> <span class="p">});</span> <span class="p">});</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="dl">'</span><span class="s1">img[data-src]</span><span class="dl">'</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">img</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">imageObserver</span><span class="p">.</span><span class="nx">observe</span><span class="p">(</span><span class="nx">img</span><span class="p">);</span> <span class="p">});</span> </code></pre></div></div> <h3 id="font-optimization"> <a href="#font-optimization" class="anchor-heading" aria-labelledby="font-optimization"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Font Optimization </h3> <h4 id="font-loading-strategy"> <a href="#font-loading-strategy" class="anchor-heading" aria-labelledby="font-loading-strategy"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Font Loading Strategy </h4> <div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Preload critical fonts --&gt;</span> <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"preload"</span> <span class="na">href=</span><span class="s">"/fonts/roboto-regular.woff2"</span> <span class="na">as=</span><span class="s">"font"</span> <span class="na">type=</span><span class="s">"font/woff2"</span> <span class="na">crossorigin</span><span class="nt">&gt;</span> <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"preload"</span> <span class="na">href=</span><span class="s">"/fonts/roboto-bold.woff2"</span> <span class="na">as=</span><span class="s">"font"</span> <span class="na">type=</span><span class="s">"font/woff2"</span> <span class="na">crossorigin</span><span class="nt">&gt;</span> <span class="c">&lt;!-- Font display swap for better performance --&gt;</span> <span class="nt">&lt;style&gt;</span> <span class="k">@font-face</span> <span class="p">{</span> <span class="nl">font-family</span><span class="p">:</span> <span class="s2">'Roboto'</span><span class="p">;</span> <span class="nl">src</span><span class="p">:</span> <span class="sx">url('/fonts/roboto-regular.woff2')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'woff2'</span><span class="p">);</span> <span class="py">font-display</span><span class="p">:</span> <span class="n">swap</span><span class="p">;</span> <span class="nl">font-weight</span><span class="p">:</span> <span class="m">400</span><span class="p">;</span> <span class="p">}</span> <span class="nt">&lt;/style&gt;</span> </code></pre></div></div> <h4 id="subset-fonts"> <a href="#subset-fonts" class="anchor-heading" aria-labelledby="subset-fonts"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Subset Fonts </h4> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">/* Load only the characters you need */</span> <span class="k">@import</span> <span class="sx">url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&amp;text=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')</span><span class="p">;</span> </code></pre></div></div><hr /> <h2 id="caching-strategies"> <a href="#caching-strategies" class="anchor-heading" aria-labelledby="caching-strategies"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Caching Strategies </h2> <h3 id="browser-caching"> <a href="#browser-caching" class="anchor-heading" aria-labelledby="browser-caching"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Browser Caching </h3> <h4 id="vite-asset-hashing"> <a href="#vite-asset-hashing" class="anchor-heading" aria-labelledby="vite-asset-hashing"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Vite Asset Hashing </h4> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// vite.config.js</span> <span class="k">export</span> <span class="k">default</span> <span class="nx">defineConfig</span><span class="p">({</span> <span class="na">build</span><span class="p">:</span> <span class="p">{</span> <span class="na">rollupOptions</span><span class="p">:</span> <span class="p">{</span> <span class="na">output</span><span class="p">:</span> <span class="p">{</span> <span class="c1">// Add hash to filenames for cache busting</span> <span class="na">entryFileNames</span><span class="p">:</span> <span class="s2">`assets/[name].[hash].js`</span><span class="p">,</span> <span class="na">chunkFileNames</span><span class="p">:</span> <span class="s2">`assets/[name].[hash].js`</span><span class="p">,</span> <span class="na">assetFileNames</span><span class="p">:</span> <span class="s2">`assets/[name].[hash].[ext]`</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> <span class="p">});</span> </code></pre></div></div> <h4 id="service-worker-implementation"> <a href="#service-worker-implementation" class="anchor-heading" aria-labelledby="service-worker-implementation"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Service Worker Implementation </h4> <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// sw.js - Service Worker for caching</span> <span class="kd">const</span> <span class="nx">CACHE_NAME</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">gentelella-v2.0.0</span><span class="dl">'</span><span class="p">;</span> <span class="kd">const</span> <span class="nx">urlsToCache</span> <span class="o">=</span> <span class="p">[</span> <span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">/assets/vendor-core.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">/assets/main-core.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">/assets/main.css</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">/images/favicon.ico</span><span class="dl">'</span> <span class="p">];</span> <span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">install</span><span class="dl">'</span><span class="p">,</span> <span class="nx">event</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">event</span><span class="p">.</span><span class="nx">waitUntil</span><span class="p">(</span> <span class="nx">caches