igniteui-wc-optimize-bundle-size — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited igniteui-wc-optimize-bundle-size (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill helps users minimize their application's bundle size when using Ignite UI Web Components by importing only the components they need and following best practices for tree-shaking.
defineAllComponents()// DON'T DO THIS - imports ALL components (~500KB+)
import { defineAllComponents } from 'igniteui-webcomponents';
defineAllComponents();Impact: Includes all 60+ components whether you use them or not.
// DO THIS - import only what you need
import {
defineComponents,
IgcButtonComponent,
IgcInputComponent,
IgcCardComponent
} from 'igniteui-webcomponents';
defineComponents(IgcButtonComponent, IgcInputComponent, IgcCardComponent);Impact: Bundle includes only 3 components and their dependencies.
If you're using React, consider using the `igniteui-react` package instead of igniteui-webcomponents. It provides the same components with React-friendly wrappers and typically results in better tree-shaking:
npm install igniteui-reactimport { IgrButton, IgrInput, IgrCard } from 'igniteui-react';
// No need to call defineComponents - components register automatically
function MyComponent() {
return (
<div>
<IgrButton variant="contained">Click me</IgrButton>
<IgrInput label="Name" />
<IgrCard>Content</IgrCard>
</div>
);
}Benefits for bundle size:
For more details, see the igniteui-wc-integrate-with-framework skill.
Installation:
npm install --save-dev webpack-bundle-analyzerConfiguration (`webpack.config.js`):
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: 'bundle-report.html'
})
]
};Run analysis:
npm run build
# Open bundle-report.html to see what's includedInstallation:
npm install --save-dev rollup-plugin-visualizerConfiguration (`vite.config.ts`):
import { defineConfig } from 'vite';
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
plugins: [
visualizer({
open: true,
gzipSize: true,
brotliSize: true,
})
]
});Run analysis:
npm run build
# Opens stats.html automaticallyInstallation:
npm install --save-dev source-map-explorerPackage.json:
{
"scripts": {
"analyze": "source-map-explorer 'dist/**/*.js'"
}
}Run:
npm run build
npm run analyzeSearch your codebase for component usage:
# Search for component tags in templates
grep -r "igc-" src/ --include="*.html" --include="*.tsx" --include="*.vue"
# List unique components
grep -roh "igc-[a-z-]*" src/ | sort | uniqCheck what you're importing vs what you're using:
// Find in your code
import {
defineComponents,
IgcButtonComponent,
IgcInputComponent,
IgcCardComponent,
IgcSelectComponent, // ← Are you using this?
IgcComboComponent, // ← Are you using this?
} from 'igniteui-webcomponents';Remove components you're not using:
// Before: 5 components imported
import {
defineComponents,
IgcButtonComponent,
IgcInputComponent,
IgcCardComponent,
IgcSelectComponent,
IgcComboComponent,
} from 'igniteui-webcomponents';
defineComponents(
IgcButtonComponent,
IgcInputComponent,
IgcCardComponent,
IgcSelectComponent,
IgcComboComponent
);
// After: Only 3 components needed
import {
defineComponents,
IgcButtonComponent,
IgcInputComponent,
IgcCardComponent,
} from 'igniteui-webcomponents';
defineComponents(IgcButtonComponent, IgcInputComponent, IgcCardComponent);Load components only when needed to reduce initial bundle size.
// Load immediately (increases initial bundle)
import { defineComponents, IgcDialogComponent } from 'igniteui-webcomponents';
defineComponents(IgcDialogComponent);
// Lazy load (smaller initial bundle)
async function showDialog() {
const { defineComponents, IgcDialogComponent } = await import('igniteui-webcomponents');
defineComponents(IgcDialogComponent);
const dialog = document.createElement('igc-dialog');
// ... use dialog
}import React, { lazy, Suspense, useState } from 'react';
// Lazy load the dialog component
const IgrDialog = lazy(() =>
import('igniteui-react').then(module => ({ default: module.IgrDialog }))
);
function MyComponent() {
const [showDialog, setShowDialog] = useState(false);
return (
<>
<button onClick={() => setShowDialog(true)}>Open Dialog</button>
{showDialog && (
<Suspense fallback={<div>Loading...</div>}>
<IgrDialog open>
<h2>Dialog Content</h2>
</IgrDialog>
</Suspense>
)}
</>
);
}import React, { useState } from 'react';
// Lazy load component registration
const lazyLoadDialog = async () => {
const { defineComponents, IgcDialogComponent } = await import('igniteui-webcomponents');
defineComponents(IgcDialogComponent);
};
function MyComponent() {
const [dialogReady, setDialogReady] = useState(false);
const openDialog = async () => {
if (!dialogReady) {
await lazyLoadDialog();
setDialogReady(true);
}
// Show dialog
};
return (
<button onClick={openDialog}>Open Dialog</button>
);
}<script setup lang="ts">
import { ref } from 'vue';
const dialogReady = ref(false);
async function openDialog() {
if (!dialogReady.value) {
const { defineComponents, IgcDialogComponent } = await import('igniteui-webcomponents');
defineComponents(IgcDialogComponent);
dialogReady.value = true;
}
// Show dialog
}
</script>
<template>
<button @click="openDialog">Open Dialog</button>
<igc-dialog v-if="dialogReady" open>
<h2>Dialog Content</h2>
</igc-dialog>
</template>import { Component } from '@angular/core';
@Component({
selector: 'app-my-component',
template: `
<button (click)="openDialog()">Open Dialog</button>
<igc-dialog *ngIf="dialogReady" [open]="true">
<h2>Dialog Content</h2>
</igc-dialog>
`
})
export class MyComponent {
dialogReady = false;
async openDialog() {
if (!this.dialogReady) {
const { defineComponents, IgcDialogComponent } = await import('igniteui-webcomponents');
defineComponents(IgcDialogComponent);
this.dialogReady = true;
}
}
}Load components only for specific routes.
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { lazy, Suspense } from 'react';
// Lazy load route components
const HomePage = lazy(() => import('./pages/Home'));
const DashboardPage = lazy(() => import('./pages/Dashboard'));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/dashboard" element={<DashboardPage />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}In route component (`pages/Dashboard.tsx`):
import { IgrCard, IgrButton } from 'igniteui-react';
function Dashboard() {
return (
<div>
<IgrCard>
<h2>Dashboard</h2>
<p>Dashboard content here</p>
</IgrCard>
</div>
);
}// router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/',
component: () => import('../views/Home.vue') // Lazy load
},
{
path: '/dashboard',
component: () => import('../views/Dashboard.vue') // Lazy load
}
];
export default createRouter({
history: createWebHistory(),
routes
});In route component (`views/Dashboard.vue`):
<script setup lang="ts">
import { onMounted } from 'vue';
onMounted(async () => {
// Load components only for this route
const { defineComponents, IgcCardComponent } = await import('igniteui-webcomponents');
defineComponents(IgcCardComponent);
});
</script>// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: 'dashboard',
loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule)
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
build: {
// Enable minification
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // Remove console.logs
drop_debugger: true
}
},
// Optimize chunk splitting
rollupOptions: {
output: {
manualChunks: {
// Separate vendor chunks
'vendor': ['igniteui-webcomponents'],
}
}
},
// Set chunk size warning limit
chunkSizeWarningLimit: 600,
},
// Optimize deps
optimizeDeps: {
include: ['igniteui-webcomponents']
}
});// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
},
igniteui: {
test: /[\\/]node_modules[\\/]igniteui-webcomponents[\\/]/,
name: 'igniteui',
priority: 20,
}
}
},
minimize: true,
},
// Tree shaking
mode: 'production',
};Here's what you can expect in terms of bundle size:
| Import Strategy | Approximate Size (gzipped) | Components Included |
|---|---|---|
defineAllComponents() | ~500KB+ | All 60+ components |
10 components via defineComponents() | ~150-200KB | 10 components + deps |
5 components via defineComponents() | ~100-150KB | 5 components + deps |
3 components via defineComponents() | ~80-120KB | 3 components + deps |
1 component via defineComponents() | ~50-80KB | 1 component + deps |
Note: Sizes vary based on which components you import (some have more dependencies than others).
Investigate:
igniteui-react instead of igniteui-webcomponentsSolutions:
// Review your imports - are you using all of these?
import {
defineComponents,
IgcButtonComponent,
IgcInputComponent,
IgcSelectComponent,
IgcComboComponent,
IgcDatePickerComponent
} from 'igniteui-webcomponents';
// Consider lazy loading components you don't need immediately
async function loadDialog() {
const { defineComponents, IgcDialogComponent } = await import('igniteui-webcomponents');
defineComponents(IgcDialogComponent);
}Cause: Forgot to import a component you're using
Solution:
// Error: <igc-button> not working
// You're using igc-button but didn't import it
import { defineComponents, IgcButtonComponent } from 'igniteui-webcomponents';
defineComponents(IgcButtonComponent); // Add thisSolution: Update type imports:
// Import types separately if needed
import type { IgcButtonComponent } from 'igniteui-webcomponents';Using bundlesize (for any build tool):
npm install --save-dev bundlesizePackage.json:
{
"scripts": {
"test:size": "bundlesize"
},
"bundlesize": [
{
"path": "./dist/**/*.js",
"maxSize": "300 kB"
}
]
}Run in CI:
npm run build
npm run test:sizename: Bundle Size Check
on: [pull_request]
jobs:
size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: npm ci
- run: npm run build
- run: npm run test:sizeAfter optimization, you should see:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.