Skip to main content

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?

SettingPurpose
host: '0.0.0.0'Binds Vite to all network interfaces, not just localhost
allowedHostsVite 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:

  1. .css files - Plain CSS imports
  2. .postcss files - PostCSS processed files
  3. 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.css returning 200
  • CSS content with all component styles bundled

Troubleshooting

CSS Not Loading

Symptom: Styles missing in the app

Check:

  1. Plugin is in your vite.config.ts
  2. Vite server is running
  3. host: '0.0.0.0' is set
  4. allowedHosts includes host.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:

  1. Shell has proxy route for /src/* (built into shell v2)
  2. Asset paths are correct
  3. 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:

  1. Iterates all modules in Vite's module graph
  2. Filters for CSS/style modules
  3. Transforms each module to extract CSS
  4. Concatenates with source comments
  5. Returns with CORS headers

Next Steps