Vite Plugin
Enhance your Vite development experience with HMR and style validation
Vite Plugin
The optional @typestyles/vite plugin enhances your development experience with Hot Module Replacement (HMR) and helpful warnings.
Installation
npm install -D @typestyles/vite
# or
pnpm add -D @typestyles/vite
# or
yarn add -D @typestyles/vite
Basic setup
Add the plugin to your vite.config.ts:
import { defineConfig } from 'vite';
import typestyles from '@typestyles/vite';
export default defineConfig({
plugins: [typestyles()],
});
Features
Hot Module Replacement (HMR)
Without the plugin, editing a style file causes a full page reload. With the plugin:
- Style changes apply instantly
- Component state is preserved
- No flicker or re-render cascade
The plugin works by:
- Detecting when a module uses typestyles
- Injecting HMR accept handlers
- Invalidating affected style registrations on file change
- Triggering a targeted update instead of a full reload
Duplicate namespace warnings
The plugin warns you when multiple files use the same namespace:
Style namespace "button" is also used in /path/to/other/file.ts.
Duplicate namespaces cause class name collisions.
This helps catch issues early, since duplicate namespaces can cause unexpected style overwrites.
Configuration
Disable duplicate warnings
If you have a legitimate use case for duplicate namespaces (uncommon), you can disable the warning:
import { defineConfig } from 'vite';
import typestyles from '@typestyles/vite';
export default defineConfig({
plugins: [
typestyles({
warnDuplicates: false,
}),
],
});
How HMR works
When you save a file that imports from typestyles, the plugin:
Extracts namespaces: Parses your code to find all
styles.create(),tokens.create(),createTheme(), andkeyframes.create()callsInjects HMR code: Adds Vite's
import.meta.hothandlers to the moduleOn file change:
- The HMR handler calls
invalidateKeys()fromtypestyles/hmr - Affected styles are removed from the internal registry
- The module re-executes with fresh style definitions
- New CSS is injected, replacing the old rules
- The HMR handler calls
State preserved: React/Vue/Svelte components keep their state since only the module containing styles changed
Example: seeing HMR in action
Create a simple Vite app with typestyles:
// src/tokens.ts
import { tokens } from 'typestyles';
export const color = tokens.create('color', {
primary: '#0066ff',
});
// src/styles.ts
import { styles } from 'typestyles';
import { color } from './tokens';
export const button = styles.create('button', {
base: {
backgroundColor: color.primary,
padding: '8px 16px',
},
});
// src/main.ts
import { button } from './styles';
document.getElementById('app').innerHTML = `
<button class="${button('base')}">Click me</button>
`;
Run the dev server:
npm run dev
Now edit src/tokens.ts and change the primary color. The button updates instantly without a page reload!
Framework integration
The plugin works with any Vite-based framework:
React
npm create vite@latest my-app -- --template react-ts
npm install typestyles @typestyles/vite
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import typestyles from '@typestyles/vite';
export default defineConfig({
plugins: [react(), typestyles()],
});
Vue
npm create vite@latest my-app -- --template vue-ts
npm install typestyles @typestyles/vite
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import typestyles from '@typestyles/vite';
export default defineConfig({
plugins: [vue(), typestyles()],
});
Svelte
npm create vite@latest my-app -- --template svelte-ts
npm install typestyles @typestyles/vite
// vite.config.ts
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import typestyles from '@typestyles/vite';
export default defineConfig({
plugins: [svelte(), typestyles()],
});
SSR with Vite
The plugin is development-only and doesn't affect SSR. For SSR, use collectStyles() from typestyles/server as described in the SSR guide.
Troubleshooting
HMR not working
- Check that the plugin is listed in
vite.config.ts - Ensure your files import from
'typestyles'(not a relative path to the package) - Verify
import.meta.hotis available (dev mode, not production)
Duplicate namespace warnings appearing incorrectly
The detection is regex-based and may have false positives if you:
- Have strings that look like typestyles calls in comments
- Use variable names like
stylesfor other purposes
These are rare and don't affect functionality—just ignore the warning or disable it.
Full reloads still happening
Some changes require a full reload:
- Adding/removing imports that affect the module graph
- Changes to non-typestyles code in the same file
- Type-only changes (TypeScript types don't affect runtime)
Plugin performance
The plugin adds minimal overhead:
- Only transforms files that import from
'typestyles' - Transformation is a simple regex match, not a full AST parse
- No runtime code is added in production builds
Is the plugin required?
No. TypeStyles works perfectly without it. The plugin is purely a development convenience for:
- Faster iteration with HMR
- Early warning about duplicate namespaces
If you prefer full page reloads or use a different bundler, you don't need this plugin.
Future features
Planned enhancements (not yet implemented):
- Dead style detection: Warn when styles are defined but never used
- Build-time extraction: Optionally extract static styles to CSS files for production
- Source maps: Map generated CSS back to your style definitions
Stay tuned to the GitHub repository for updates.