npm package: @shardev/mod-vite-plugin
Description: laravel modules plugin for Vite.
Author: shardevcom
Latest version: 2.0.0

# 📦 @shardev/mod-vite-plugin

Un plugin de Vite para proyectos Laravel que extiende la funcionalidad estándar para soportar la compilación automática de múltiples módulos y paquetes de React/Vue/JS/TS, ideal para estructuras de monorepos o proyectos complejos.

Basado y extendido del Laravel Vite Plugin.

## ✨ Características

- Detección Automática de Módulos: Escanea y compila automáticamente los puntos de entrada (ej. main.tsx, index.ts) definidos por patrones de glob configurables.

- Soporte para Múltiples Aplicaciones: Compila múltiples aplicaciones frontend (ej. website, admin) en un solo proceso de Vite.

- Compilación de Paquetes/Componentes: Integra módulos de librerías o componentes reutilizables (ej. authentication, dashboard) como entradas compilables.

- Salidas Organizadas: Genera los assets compilados en subcarpetas dedicadas dentro de public/build (ej. public/build/website/, public/build/authentication/).

- Funcionalidad Base de Laravel Vite Plugin: Hereda todas las características del plugin original, incluyendo detección de Valet/Herd TLS, refresco de Blade, hot-reloading, etc.

## 🚀 Instalación
```bash 
    npm install -D @vitejs/mod-vite-plugin
```    

## ⚙️ Configuración

Configura el plugin en tu archivo vite.config.ts principal. Al importarlo, la ruta será relativa a su ubicación dentro de tu proyecto.
TypeScript
```tsx
// vite.config.ts
import {defineConfig} from 'vite';
import react from '@vitejs/plugin-react';
// IMPORTANTE: La ruta aquí debe coincidir con la ubicación real de tu plugin.
import laravel from './plugins/mod-vite-plugin';
import path from 'path';

export default defineConfig({
    plugins: [
        react(), // O @vitejs/plugin-vue para Vue, etc.
        laravel({
            // Define aquí tus puntos de entrada y patrones de descubrimiento
            input: {
                // Rutas explícitas o patrones de glob para las aplicaciones principales
                mainEntries: [
                    'resources/react/website/main.tsx',
                    'resources/react/admin/main.tsx',
                    // Si tienes más aplicaciones principales:
                    // 'resources/js/app.ts',
                ],
                // Patrones de glob para descubrir automáticamente módulos/paquetes en otras ubicaciones
                moduleDiscoveryGlobs: [
                    'packages/shardevcom/*/src/main.tsx', // Tus paquetes de vendor
                    'src/features/*/index.ts', // Ejemplo: si tus características son módulos en 'src/features'
                    'app/Modules/*/resources/app.js', // Ejemplo: si usas una estructura de módulos de Laravel
                ],
            },
            publicDirectory: 'public',
            buildDirectory: 'build', // Donde se guardarán los assets compilados (ej. public/build/website/, public/build/admin/)
            refresh: [ // Configuración para full page reload en cambios de archivos Blade/PHP
                'resources/views/**',
                'app/Http/Livewire/**',
                'app/View/Components/**', 
                // Agrega rutas adicionales que deban activar un refresco completo del navegador
            ],
            // ... otras configuraciones del Laravel Vite Plugin si las necesitas
        }),
    ],
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './resources/js'), // Alias común para 'resources/js'
            // Puedes añadir más alias si lo deseas para tus paquetes, ej:
            // '@my-components': path.resolve(__dirname, './packages/my-components/src'),
        },
    },
// Otras configuraciones de Vite según sea necesario
});
```

### Propiedades de input

El objeto input en la configuración del plugin puede contener las siguientes propiedades:

- mainEntries: string | string[]: Define explícitamente las rutas a tus puntos de entrada principales (aplicaciones frontend completas) o patrones de glob para encontrarlos. Estos generalmente corresponden a tus vistas Blade principales (ej. website.blade.php, admin.blade.php).

Ejemplos:

    'resources/react/website/main.tsx'

    ['resources/react/website/main.tsx', 'resources/react/admin/main.tsx']

    'resources/js/**/*.ts' (para encontrar todos los archivos .ts en resources/js y subcarpetas)

- moduleDiscoveryGlobs: string[]: Un array de patrones de glob para descubrir automáticamente los puntos de entrada de tus módulos o paquetes reutilizables en cualquier parte del proyecto. El plugin generará nombres de salida basados en el nombre de la carpeta que contiene el archivo de entrada.

Ejemplos:

    ['packages/my-vendor/*/src/main.tsx'] (para estructuras de paquete como la tuya)

    ['src/shared-components/*/index.ts'] (para componentes compartidos)

    ['modules/*/app.js'] (para módulos dentro de una carpeta modules)

### 📦 Estructura de Proyecto Soportada

Este plugin está diseñado para trabajar eficientemente con una estructura de monorepo como la siguiente:

```
project/
├── resources/
│   ├── react/
│   │   ├── website/        # Módulo principal de la web
│   │   │   └── main.tsx    # Punto de entrada de la aplicación web
│   │   └── admin/          # Módulo principal del panel de administración
│   │       └── main.tsx    # Punto de entrada de la aplicación admin
│   │
│   └── views/
│       ├── website.blade.php  # Vistas de Laravel para el frontend
│       └── admin.blade.php    # Vistas de Laravel para el admin
│
├── packages/
│   └── shardevcom/
│       ├── authentication/   # Paquete/Módulo de autenticación
│       │   ├── src/
│       │   │   └── main.tsx  # Punto de entrada (exporta componentes, no monta app)
│       │   └── (otros archivos, ej: components/, context/, utils/)
│       └── dashboard/        # Paquete/Módulo de dashboard
│           ├── src/
│           │   └── main.tsx  # Punto de entrada
│           └── (otros archivos)
│   └── another-vendor/
│       └── my-awesome-lib/
│           └── src/
│               └── index.ts  # Otro módulo/paquete
│
├── public/
│   └── build/                # Directorio de salida de los assets compilados
│       ├── admin/            # Assets de la aplicación 'admin'
│       │   └── main-[hash].js
│       ├── website/          # Assets de la aplicación 'website'
│       │   └── main-[hash].js
│       ├── authentication/   # Assets del módulo 'authentication'
│       │   └── main-[hash].js
│       └── dashboard/        # Assets del módulo 'dashboard'
│           └── main-[hash].js
│           └── assets/
│               └── image-[hash].png
│
├── package.json              # Package.json principal del proyecto (usar Workspaces)
└── vite.config.ts            # Configuración principal de Vite
```
main.tsx para Componentes/Paquetes (ej. packages/shardevcom/authentication/src/main.tsx)

Para un paquete o módulo que exporta componentes o funcionalidades reusables, el main.tsx no debe contener ReactDOM.createRoot().render(). En su lugar, simplemente exporta lo que el paquete ofrece:
TypeScript

```tsx
// packages/shardevcom/authentication/src/main.tsx

export { default as LoginForm } from './components/LoginForm';
export { default as RegisterForm } from './components/RegisterForm';
export { AuthProvider, useAuth } from './context/AuthContext';
export { login, logout, checkAuthStatus } from './utils/authService';

// Opcional: Si quieres un componente principal que agrupe la lógica para fácil testing aislado
// export { default as AuthenticationModule } from './views/AuthenticationModule';
```

### 🌐 Uso en Vistas Blade

Para incluir los assets compilados en tus vistas Blade de Laravel, usa el helper @vite apuntando a la entrada original de tu módulo:

```BLADE
{{-- resources/views/website.blade.php --}}
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My Website</title>
    @vite('resources/react/website/main.tsx') {{-- Apunta a la entrada original --}}
</head>
<body>
    <div id="app"></div>
</body>
</html>
```

```BLADE
{{-- resources/views/admin.blade.php --}}
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Admin Panel</title>
    @vite('resources/react/admin/main.tsx') {{-- Apunta a la entrada original --}}
</head>
<body>
    <div id="admin-app"></div>
</body>
</html>
```

El helper @vite se encarga de leer el manifest.json (generado por el plugin) y de obtener la ruta correcta al archivo compilado, incluso si está en una subcarpeta (ej. public/build/website/main-[hash].js).

### ⚙️ Workspaces (Recomendado para Monorepos)

Para gestionar las dependencias de tus módulos/paquetes de forma eficiente en un monorepo, se recomienda encarecidamente usar Workspaces (disponibles en npm, Yarn y pnpm).

En project/package.json

```JSON
{
  "name": "my-laravel-monorepo",
  "version": "1.0.0",
  "private": true,
  "workspaces": [
    "packages/*/*",
    // Para tus vendors y paquetes (ej. packages/shardevcom/authentication)
    "resources/react/*"
    // Para tus aplicaciones principales (website, admin)
    // Agrega cualquier otra carpeta que contenga package.json de módulos/paquetes
  ],
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    // Dependencias compartidas que quieras "hoistear" al nivel raíz
  },
  "devDependencies": {
    "vite": "^5.0.0",
    "@vitejs/plugin-react": "^4.0.0",
    "glob": "^10.0.0",
    "picocolors": "^1.0.0",
    "vite-plugin-full-reload": "^1.0.0",
    // Otras devDependencies para todo el proyecto
  },
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  }
}
```
En packages/shardevcom/authentication/package.json (o cualquier otro módulo/paquete):

```JSON
    {
      "name": "@shardevcom/authentication",
      "version": "1.0.0",
      "private": true, // Si este paquete no se va a publicar individualmente
      "main": "src/main.tsx",
      "dependencies": {
        "axios": "^1.6.4",
        "formik": "^2.4.5"
        // Dependencias específicas de este módulo (no necesita react, vite, etc., si ya están en el raíz)
      }
    }
```
Después de configurar los workspaces, ejecuta npm install (o yarn install / pnpm install) en la raíz del proyecto. El gestor de paquetes se encargará de instalar todas las dependencias y hacer el "hoisting" necesario.

### 🧪 Desarrollo y Pruebas Individuales de Módulos

Si deseas desarrollar o probar un módulo/paquete de forma aislada (ej. packages/shardevcom/authentication), puedes darle su propio vite.config.ts y package.json dentro de su carpeta.

Crea packages/shardevcom/authentication/package.json:

```JSON
{
  "name": "@shardevcom/authentication",
  "version": "1.0.0",
  "main": "src/main.tsx",
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  },
  "devDependencies": {
    "vite": "^5.0.0",
    "@vitejs/plugin-react": "^4.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}
```

Crea packages/shardevcom/authentication/vite.config.ts:

```TypeScript
import {defineConfig} from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
    plugins: [react()],
    build: {
        outDir: 'dist', // Salida específica para este módulo individual
        lib: {
            entry: path.resolve(__dirname, 'src/main.tsx'),
            name: 'AuthenticationModule',
            fileName: (format) => `authentication.${format}.js`,
        },
        rollupOptions: {
            external: ['react', 'react-dom'],
            output: {globals: {react: 'React', 'react-dom': 'ReactDOM'}},
        },
    },
    server: {
        port: 3001, // Puerto diferente para evitar conflictos
    }
});
```

Crea packages/shardevcom/authentication/index.html (para probar):

```HTML
<!DOCTYPE html>
<html>
<body>
<div id="authentication-root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
```

Para probarlo de forma aislada:

```Bash
  cd packages/shardevcom/authentication
  npm install # Si no usas workspaces, o si hay dependencias específicas
  npm run dev
```
Esto levantará un servidor de desarrollo solo para el módulo de autenticación.