Vite Plugin
Guide to using the devCssBundle Vite plugin for cross-origin CSS loading.
Overview
The devCssBundle plugin solves a specific problem in the Easy.M development environment:
The Problem:
- The shell runs in Docker at
localhost:3000 - Your app's Vite dev server runs at
localhost:5173 - Vite normally injects CSS via JavaScript
- Cross-origin restrictions prevent this from working
The Solution:
- Collect all CSS from loaded modules
- Serve bundled CSS at a predictable endpoint
- Shell loads CSS via standard
<link>tag
Installation
The plugin is included in @easy/dev-kit:
import { devCssBundle } from '@easy/dev-kit/vite-plugin'
Basic Usage
Add the plugin to your vite.config.ts:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { devCssBundle } from '@easy/dev-kit/vite-plugin'
export default defineConfig({
plugins: [
vue(),
devCssBundle(),
],
})
Configuration Options
interface DevCssBundleOptions {
/**
* The endpoint path where bundled CSS will be served.
* @default '/__dev_styles.css'
*/
endpoint?: string
/**
* The Vite dev server port. Used to generate absolute asset URLs.
* @default 5173
*/
port?: number
}
Custom Endpoint
devCssBundle({
endpoint: '/app-styles.css',
})
Custom Port
devCssBundle({
port: 5174,
})
Required Server Configuration
For the plugin to work with Docker, you must configure Vite's server settings:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { devCssBundle } from '@easy/dev-kit/vite-plugin'
export default defineConfig({
plugins: [
vue(),
devCssBundle(),
],
server: {
// REQUIRED: Bind to all interfaces for Docker access
host: '0.0.0.0',
// REQUIRED: Allow Docker to connect via host.docker.internal
allowedHosts: ['host.docker.internal'],
// Optional: Explicit port
port: 5173,
},
})
Why These Settings?
| Setting | Purpose |
|---|---|
host: '0.0.0.0' | Binds Vite to all network interfaces, not just localhost |
allowedHosts | Vite 5+ blocks requests from unknown hosts for security |
Without these settings, Docker containers cannot reach the Vite server.
How It Works
CSS Collection
The plugin intercepts CSS from multiple sources:
.cssfiles - Plain CSS imports.postcssfiles - PostCSS processed files- Vue SFC
<style>blocks - Component styles
CSS Transformation
Vite transforms CSS into JavaScript modules. The plugin extracts CSS from these patterns:
// Pattern 1: Vite's internal format
const __vite__css = "..."
// Pattern 2: Named export
const css = "..."
// Pattern 3: Default export
export default "..."
Asset URL Rewriting
The plugin rewrites relative asset URLs to absolute URLs:
/* Input */
background: url('/src/assets/bg.png');
/* Output */
background: url('http://localhost:5173/src/assets/bg.png');
Complete Example
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
import { devCssBundle } from '@easy/dev-kit/vite-plugin'
import { resolve } from 'path'
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('ez-'),
},
},
}),
VueI18nPlugin({ include: resolve(__dirname, './src/locales/**') }),
devCssBundle(),
],
server: {
host: '0.0.0.0',
allowedHosts: ['host.docker.internal'],
port: 5173,
cors: true,
},
resolve: {
alias: {
'@': resolve(__dirname, './src'),
},
},
})
Verifying the Plugin
Check CSS Endpoint
With your Vite dev server running:
curl http://localhost:5173/__dev_styles.css
You should see bundled CSS output.
Check Console Output
The plugin logs when active:
[easy-dev-css-bundle] CSS bundle endpoint ready at /__dev_styles.css
[easy-dev] Asset intercepted: /path/to/image.svg -> http://localhost:5173/src/assets/image.svg
Check Network Tab
In browser DevTools, you should see:
- Request to
/__dev_styles.cssreturning 200 - CSS content with all component styles bundled
Troubleshooting
CSS Not Loading
Symptom: Styles missing in the app
Check:
- Plugin is in your vite.config.ts
- Vite server is running
host: '0.0.0.0'is setallowedHostsincludeshost.docker.internal
Blocked Host Error
Symptom:
Blocked request. This host ("host.docker.internal") is not allowed.
Solution: Add to allowedHosts:
server: {
allowedHosts: ['host.docker.internal'],
}
Assets Not Loading
Symptom: Images return 404
Check:
- Shell has proxy route for
/src/*(built into shell v2) - Asset paths are correct
- Vite server is accessible from Docker
CORS Errors
Symptom: Cross-origin request blocked
Solution: Add CORS headers:
server: {
cors: true,
headers: {
'Access-Control-Allow-Origin': '*',
},
}
Plugin Internals
Module Structure
devCssBundle()
├── configResolved() → Store root path
├── load() → Intercept asset imports, return absolute URLs
└── configureServer() → Add middleware for CSS endpoint
CSS Endpoint Middleware
The middleware:
- Iterates all modules in Vite's module graph
- Filters for CSS/style modules
- Transforms each module to extract CSS
- Concatenates with source comments
- Returns with CORS headers
Next Steps
- App Setup - Complete setup guide
- Configuration - devkit.config.ts reference