agentsclimarketplace

React vite performance

Skill fabioc-aloha/Alex_Skill_Mall/plugins/platform-tooling/react-vite-performance

284 curated plugins for AI assistants across 16 categories: security, Azure, documentation, code quality, cloud infrastructure, and more. Works with GitHub Copilot. Drop into .github/skills/local/ and go.

Install
npx -y skills add fabioc-aloha/Alex_Skill_Mall --skill react-vite-performance

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

React + Vite performance optimization — code splitting, lazy loading, bundle analysis, Web Vitals, and modern React patterns for fast web applications

SKILL.md

7.2 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it

React + Vite Performance Optimization

Fast by default, optimized by design — sub-300KB bundles and sub-2s load times.

Targets: React 19+ / Vite 6+ | Last validated: April 2026

Performance Targets

MetricTargetTool
Initial JS (gzipped)< 300 KBrollup-plugin-visualizer
First Contentful Paint< 1.5sLighthouse
Time to Interactive< 3sLighthouse
Largest Contentful Paint< 2.5sWeb Vitals
Cumulative Layout Shift< 0.1Web Vitals

Vite Build Configuration

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  build: {
    target: 'esnext',
    minify: 'esbuild',
    sourcemap: true,
    rollupOptions: {
      output: {
        manualChunks: {
          'react-vendor': ['react', 'react-dom', 'react-router-dom'],
          'ui': ['@headlessui/react', '@heroicons/react'],
          // Group large dependencies into separate chunks
        },
      },
    },
    chunkSizeWarningLimit: 500,
  },
  optimizeDeps: {
    include: ['react', 'react-dom', 'react-router-dom'],
  },
});

Bundle Analysis

npm install -D rollup-plugin-visualizer
// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer';

plugins: [
  react(),
  visualizer({ filename: 'dist/stats.html', gzipSize: true }),
]

Code Splitting

Route-Based Splitting

import { lazy, Suspense } from 'react';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
    children: [
      { path: 'dashboard', element: <Dashboard /> },
      { path: 'settings', element: <Settings /> },
    ],
  },
]);

function App() {
  return (
    <Suspense fallback={<LoadingSpinner />}>
      <RouterProvider router={router} />
    </Suspense>
  );
}

Component-Based Splitting

const Chart = lazy(() => import('./components/Chart'));

function Dashboard() {
  return (
    <Suspense fallback={<ChartSkeleton />}>
      <Chart data={data} />
    </Suspense>
  );
}

Preloading on Hover

function NavLink({ to, loader, children }) {
  const preload = () => loader(); // e.g., () => import('./pages/Settings')

  return (
    <Link to={to} onMouseEnter={preload} onFocus={preload}>
      {children}
    </Link>
  );
}

Modern React Patterns

Compiler-Friendly Code (React 19+)

React 19's compiler auto-memoizes. Write straightforward components:

// ✅ Let the compiler optimize
function UserCard({ user }: { user: User }) {
  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  );
}

// ❌ Avoid manual memoization the compiler handles
const UserCard = React.memo(({ user }) => { ... });

Vite setup — install babel-plugin-react-compiler and add to vite.config.ts:

// vite.config.ts
import react from '@vitejs/plugin-react';
export default defineConfig({
  plugins: [
    react({ babel: { plugins: ['babel-plugin-react-compiler'] } }),
  ],
});

use() Hook for Data Loading

import { use, Suspense } from 'react';

function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
  const user = use(userPromise);
  return <div>{user.name}</div>;
}

function App() {
  const userPromise = fetchUser(userId);
  return (
    <Suspense fallback={<UserSkeleton />}>
      <UserProfile userPromise={userPromise} />
    </Suspense>
  );
}

useTransition for Non-Urgent Updates

import { useState, useTransition } from 'react';

function SearchableList({ items }: { items: Item[] }) {
  const [query, setQuery] = useState('');
  const [filtered, setFiltered] = useState(items);
  const [isPending, startTransition] = useTransition();

  const handleSearch = (value: string) => {
    setQuery(value); // Urgent: update input immediately
    startTransition(() => {
      setFiltered(items.filter(item =>
        item.name.toLowerCase().includes(value.toLowerCase())
      ));
    });
  };

  return (
    <>
      <input value={query} onChange={e => handleSearch(e.target.value)} />
      {isPending && <Spinner />}
      <List items={filtered} />
    </>
  );
}

TanStack Query Optimization

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000,    // 5 minutes
      gcTime: 30 * 60 * 1000,      // 30 minutes
      refetchOnWindowFocus: false,
      retry: 1,
    },
  },
});

Optimistic Updates

const updateUser = useMutation({
  mutationFn: (data: UserUpdate) => api.updateUser(data),
  onMutate: async (newData) => {
    await queryClient.cancelQueries({ queryKey: ['user'] });
    const previous = queryClient.getQueryData(['user']);
    queryClient.setQueryData(['user'], old => ({ ...old, ...newData }));
    return { previous };
  },
  onError: (_err, _new, context) => {
    queryClient.setQueryData(['user'], context?.previous);
  },
  onSettled: () => {
    queryClient.invalidateQueries({ queryKey: ['user'] });
  },
});

Asset Optimization

Images

// Non-critical images: lazy load
<img src={src} alt={alt} loading="lazy" decoding="async" fetchpriority="low" />

// LCP image: load immediately
<img src={src} alt={alt} fetchpriority="high" />

Fonts

@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-var.woff2') format('woff2-variations');
  font-display: swap;
  font-weight: 100 900;
}
<link rel="preload" href="/fonts/Inter-var.woff2" as="font" type="font/woff2" crossorigin>

Web Vitals Monitoring

INP replaced FID as a Core Web Vital in March 2024. INP measures overall responsiveness (all interactions), not just the first one.

import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals';

function reportMetric(metric: Metric) {
  analytics.track('web-vitals', {
    name: metric.name,
    value: metric.value,
    rating: metric.rating,
  });
}

onCLS(reportMetric);
onINP(reportMetric);   // Interaction to Next Paint (replaced FID)
onLCP(reportMetric);
onFCP(reportMetric);
onTTFB(reportMetric);

Performance Checklist

Build

  • Manual chunks for large vendor libs
  • Tree shaking enabled (ESM imports)
  • Dependency pre-bundling configured
  • Bundle size tracked in CI

Runtime

  • Routes lazy-loaded with Suspense
  • Heavy components split into separate chunks
  • useTransition for non-urgent state updates
  • Virtual scrolling for long lists
  • Debounce expensive operations

Assets

  • Images: WebP, lazy loading, responsive sizes
  • Fonts: font-display: swap, preload critical
  • Brotli/gzip compression enabled
  • Critical CSS inlined

Keep looking

Skills are one crate of 327,069. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.