DEV Community

Alex Spinov
Alex Spinov

Posted on

Vite Has a Free Plugin API That Most Frontend Developers Ignore

Vite is the default build tool for React, Vue, Svelte, and Solid. But its plugin API — built on Rollup — gives you superpowers most developers never touch.

Writing a Vite Plugin

// vite.config.ts
import { defineConfig, Plugin } from "vite";

function myPlugin(): Plugin {
  return {
    name: "my-plugin",
    // Transform any file
    transform(code, id) {
      if (id.endsWith(".md")) {
        return `export default ${JSON.stringify(markdownToHtml(code))}`;
      }
    },
    // Add virtual modules
    resolveId(id) {
      if (id === "virtual:build-info") return "\0virtual:build-info";
    },
    load(id) {
      if (id === "\0virtual:build-info") {
        return `export const buildTime = "${new Date().toISOString()}";`;
      }
    },
    // Hook into dev server
    configureServer(server) {
      server.middlewares.use("/api/health", (req, res) => {
        res.end(JSON.stringify({ status: "ok" }));
      });
    }
  };
}

export default defineConfig({ plugins: [myPlugin()] });
Enter fullscreen mode Exit fullscreen mode

HMR API: Hot Module Replacement

// In your module
if (import.meta.hot) {
  import.meta.hot.accept((newModule) => {
    // Handle the updated module
    updateComponent(newModule.default);
  });

  // Custom HMR events
  import.meta.hot.on("special-update", (data) => {
    console.log("Custom update:", data);
  });

  // Cleanup on dispose
  import.meta.hot.dispose(() => {
    clearInterval(myTimer);
  });
}
Enter fullscreen mode Exit fullscreen mode

Environment API (Vite 6+)

// vite.config.ts
export default defineConfig({
  environments: {
    client: {
      build: { outDir: "dist/client" }
    },
    ssr: {
      build: { outDir: "dist/server" }
    },
    worker: {
      build: { outDir: "dist/worker" }
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

Glob Import API

// Import all markdown files
const modules = import.meta.glob("./posts/*.md");

// Eager loading with type safety
const posts = import.meta.glob<{ title: string; date: string }>("./posts/*.md", {
  eager: true,
  import: "frontmatter"
});

// Dynamic patterns
const components = import.meta.glob("./components/**/index.tsx");
for (const [path, loader] of Object.entries(components)) {
  const mod = await loader();
}
Enter fullscreen mode Exit fullscreen mode

CSS Modules API

// Automatic CSS modules
import styles from "./Component.module.css";
// styles.container, styles.title — fully typed

// CSS-in-JS via plugin
import { css } from "vite-plugin-css-in-js";
const className = css`
  color: blue;
  &:hover { color: red; }
`;
Enter fullscreen mode Exit fullscreen mode

SSR API

import { createServer } from "vite";

const vite = await createServer({ server: { middlewareMode: true } });

app.use(vite.middlewares);
app.get("*", async (req, res) => {
  const { render } = await vite.ssrLoadModule("/src/entry-server.tsx");
  const html = await render(req.url);
  res.send(html);
});
Enter fullscreen mode Exit fullscreen mode

Building dev tools? My Apify scraping tools can feed data into your Vite-powered dashboards.

Custom tooling solution? Email spinov001@gmail.com

Top comments (0)