# primer on vite plugins Vite is a build tool + development server for web apps. It uses native ES modules in development (no bundling) and Rollup for production builds. Vite offers **[plugins](https://vite.dev/guide/using-plugins)** (based on Rollup's [plugin](https://rollupjs.org/plugin-development/#plugins-overview) interface): objects defined that allow one to customise Vite's behaviour by, for example, transpiling code before bundling, or finding third-party modules in your node_modules folder. Plugins are injected into the `vite.config.ts` file. A simple, yet critical detail here is that ordering the plugins in the array affect the way in which they are executed. So if one were to write a custom plugin, and place it before the `react()` plugin, as so: ```ts= plugins: [ customPlugin(), react() ], ``` -- the custom plugin is compiled first. The only way around this is to "[enforce](https://vite.dev/guide/using-plugins#enforcing-plugin-ordering)" the same, which requires one to specify whether the plugin is to run pre core Vite plugins, after, or post Vite build plugins. It is invoked as so: ```ts plugins: [ { ...image(), enforce: 'pre', }, ], ``` To understand how plugins work in practice, I wrote a [simple plugin](https://gist.github.com/ultraviolet10/e140612cb4c4e74224fd0d6c67c30445) that logs every lifecycle hook Vite calls during development and build. It implements 11 major lifecycle hooks and logs them with: - execution order (numbered sequence) - timing - data such as file path, modes, etc. The hooks implemented are as follows: (vite-Specific Hooks) - `config` - Modify Vite config before resolution - `configResolved` - Access final resolved config - `configureServer` - Add dev server middleware - `transformIndexHtml` - Transform the HTML entry point - `handleHotUpdate` - Custom HMR handling (rollup Hooks ~ *universal*): - `options` - Receive Rollup options - `buildStart` - Build initialization - `resolveId` - Resolve module imports - `load` - Load module content - `transform` - Transform module code - `buildEnd` - Build completion - `closeBundle` - Final cleanup To actually study these in action, we simply run `bun run dev` and `bun run build`, which reveals important differences: **Development mode**: - Files are transferred on-demand when requested - `handleHotUpdate` emits when you edit files - No `closeBundle`, since nothing is written to disk ![Screenshot 2026-01-05 at 7.31.13 PM](https://hackmd.io/_uploads/HyoB4BK4Zl.png) **Build mode**: - All files processed upfront - `closeBundle` fires after writing the `dist/` folder - No dev server hooks ![Screenshot 2026-01-05 at 7.35.30 PM](https://hackmd.io/_uploads/BkIEHHFNZx.png) This plugin is just an example to understand how to build more performant plugins that transform code, add routes, inject scripts, or customize the dev server. ---- until the next one! :wave: