
Plugin Bundle Size
Shrink a Grafana app plugin’s render-blocking `module.js` and lazy-load feature code so Grafana starts faster after you ship the plugin.
Overview
Plugin-bundle-size is an agent skill for the Build phase that optimizes Grafana app plugin JavaScript bundles using React.lazy, Suspense, and webpack code splitting to shrink `module.js` and improve initial load.
Install
npx skills add https://github.com/grafana/skills --skill plugin-bundle-sizeWhat is this skill?
- Drives `module.js` toward under ~200 KB as a lazy-wrapper-only entry with feature code loaded on demand
- Targets ~15–25 total JS chunks—enough splitting without 50+ micro-chunk over-engineering
- Applies a risk-ordered plan: Safe Priority 1 `module.tsx` lazy wrappers (often 90%+ `module.js` reduction), then route-l
- Uses `React.lazy`, `Suspense`, and webpack code splitting patterns suited to Grafana app plugins
- Maps each splitting opportunity to a risk level so you ship optimizations in the safest order first
- Target `module.js` under ~200 KB with lazy-loaded wrappers only
- Aim for ~15–25 total JS chunks for a well-split plugin
- Priority 1 `module.tsx` lazy wrappers can drop `module.js` size by 90%+ with very low risk
Adoption & trust: 696 installs on skills.sh; 143 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Grafana app plugin ships a huge `module.js` that blocks Grafana startup, so users wait on JavaScript you could have loaded only when they open a route or extension.
Who is it for?
Indie developers shipping or refactoring Grafana app plugins who see large `module.js` in webpack stats or hear that the plugin slows Grafana’s initial load.
Skip if: Projects that are not Grafana app plugins, teams with no React/webpack frontend, or plugins already meeting the ~200 KB lazy-entry pattern with healthy chunk counts—skip generic “delete npm packages” tuning instead.
When should I use this skill?
User asks to reduce Grafana plugin bundle size, optimize module.js, add code splitting, improve initial plugin load, split chunks, lazy-load plugin pages, or implement Suspense in a Grafana app plugin—including phrases l
What do I get? / Deliverables
You end up with a thin lazy-loaded `module.js`, on-demand feature chunks in the ~15–25 range, and a repeatable splitting order that cuts initial payload without rewriting plugin behavior.
- Refactored lazy `module.tsx` entry and route-level `React.lazy` boundaries
- Webpack chunk layout aligned to the ~15–25 chunk guidance
- Smaller initial `module.js` payload suitable for faster Grafana startup
Recommended Skills
Journey fit
Bundle splitting and `React.lazy` wiring happen while you implement or refactor the Grafana app plugin UI and routes—not as a separate launch or ops playbook. The skill targets frontend entry points (`module.tsx`), route-level chunks, and extension lazy boundaries—classic frontend build-time architecture for Grafana plugins.
How it compares
Grafana-plugin-specific lazy-entry and chunk-count targets—not generic React performance tips with no `module.tsx` or extension priorities.
Common Questions / FAQ
Who is plugin-bundle-size for?
Solo and indie builders working on Grafana app plugins who need to reduce `module.js`, add code splitting, or lazy-load pages and extensions without guessing webpack structure.
When should I use plugin-bundle-size?
Use it during Build when `module.js` is too large, initial plugin load feels slow, you are adding routes or extensions, or you need Suspense and `React.lazy` patterns for a Grafana plugin codebase.
Is plugin-bundle-size safe to install?
Treat it like any third-party agent skill: review the Security Audits panel on this Prism page and your org’s policies before letting an agent edit webpack and React entry files in your repo.
SKILL.md
READMESKILL.md - Plugin Bundle Size
# Grafana plugin bundle size optimisation `module.js` is the render-blocking entry point for every Grafana app plugin. The smaller it is, the less impact the plugin has on Grafana's overall startup time. A well-split plugin should have a `module.js` under ~200 KB that contains nothing but lazy-loaded wrappers — all feature code loads on demand. **Target:** ~15–25 JS chunks total. Fewer means too little splitting; far more (50+) means over-engineering. ## Risk levels Not all splitting opportunities carry the same risk. Apply them in this order: | Level | What | Risk | Impact | |---|---|---|---| | **Safe** | `module.tsx` lazy wrappers (Priority 1) | Very low — no behaviour change | Highest — module.js drops 90%+ | | **Safe** | Route-level `lazy()` (Priority 2) | Low — each route is self-contained | High — one chunk per route | | **Safe** | Extension `lazy()` (Priority 3) | Low — extensions are isolated | Medium — independent chunk per extension | | **Moderate** | Component registries / tab panels (Priority 4) | Medium — verify Suspense placement | Medium — splits heavy pages further | | **Do not touch** | Vendor libraries (`@grafana/scenes`, `@reduxjs/toolkit`) | N/A | N/A — webpack splits these automatically | | **Do not touch** | Shared utility components (Markdown, Spinner) used across many files | High churn, many callsites | Low — already in shared vendor chunks | When in doubt, stop after Priority 2. Routes alone typically reduce `module.js` by 95%+. --- ## Step 1: Add bundle size CI reporting (recommended) Add the `grafana/plugin-actions/bundle-size` action to get automatic bundle size comparison comments on every PR. This posts a table showing entry point size changes, file count diffs, and total bundle impact. **Root-level plugins** (plugin at repo root): ```yaml # .github/workflows/bundle-size.yml name: Bundle Size on: pull_request: push: branches: [main] workflow_dispatch: jobs: bundle-size: runs-on: ubuntu-latest permissions: contents: write id-token: write pull-requests: write actions: read steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: .nvmrc - name: Install and build run: yarn install - name: Bundle Size uses: grafana/plugin-actions/bundle-size@a66a1c96cdbb176f9cccf10cf23593e250db7cce # bundle-size/v1.1.0 ``` **Subdirectory plugins** (e.g. `plugin/` in a monorepo): The action's install step runs at the repo root and cannot find `yarn.lock` in a subdirectory. Work around this by installing deps yourself and symlinking to root: ```yaml jobs: bundle-size: runs-on: ubuntu-latest permissions: contents: write id-token: write pull-requests: write actions: read steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: ./plugin/.nvmrc - name: Install dependencies working-directory: ./plugin run: yarn install - name: Symlink plugin to root for bundle-size action run: | ln -s plugin/yarn.lock yarn.lock ln -s plugin/package.json package.json ln -s plugin/.yarnrc.yml .yarnrc.yml ln -s plugin/node_modules node_modules - name: Bundle Size uses: grafana/plugin-actions/bundle-size@a