Integración con Vite

Las aplicaciones JavaScript modernas requieren herramientas de construcción sofisticadas. Nette Assets proporciona una integración de primera clase con Vite, la herramienta de construcción frontend de próxima generación. Obtenga un desarrollo ultrarrápido con Hot Module Replacement (HMR) y construcciones de producción optimizadas sin problemas de configuración.

  • Cero configuración – puente automático entre Vite y las plantillas PHP
  • Gestión completa de dependencias – una etiqueta maneja todos los assets
  • Hot Module Replacement – actualizaciones instantáneas de JavaScript y CSS
  • Construcciones de producción optimizadas – división de código y tree shaking

Nette Assets se integra perfectamente con Vite, por lo que obtiene todos estos beneficios mientras escribe sus plantillas como de costumbre.

Configurando Vite

Vamos a configurar Vite paso a paso. No se preocupe si es nuevo en las herramientas de construcción, ¡lo explicaremos todo!

Paso 1: Instalar Vite

Primero, instale Vite y el plugin de Nette en su proyecto:

npm install -D vite @nette/vite-plugin

Esto instala Vite y un plugin especial que ayuda a Vite a funcionar perfectamente con Nette.

Paso 2: Estructura del Proyecto

El enfoque estándar es colocar los archivos de assets fuente en una carpeta assets/ en la raíz de su proyecto, y las versiones compiladas en www/assets/:

web-project/
├── assets/                   ← archivos fuente (SCSS, TypeScript, imágenes fuente)
│   ├── public/               ← archivos estáticos (copiados tal cual)
│   │   └── favicon.ico
│   ├── images/
│   │   └── logo.png
│   ├── app.js                ← punto de entrada principal
│   └── style.css             ← sus estilos
└── www/                      ← directorio público (document root)
	├── assets/               ← los archivos compilados irán aquí
	└── index.php

La carpeta assets/ contiene sus archivos fuente, el código que usted escribe. Vite procesará estos archivos y colocará las versiones compiladas en www/assets/.

Paso 3: Configurar Vite

Cree un archivo vite.config.ts en la raíz de su proyecto. Este archivo le dice a Vite dónde encontrar sus archivos fuente y dónde colocar los compilados.

El plugin Nette Vite viene con valores predeterminados inteligentes que simplifican la configuración. Asume que sus archivos fuente front-end están en el directorio assets/ (opción root) y los archivos compilados van a www/assets/ (opción outDir). Solo necesita especificar el punto de entrada:

import { defineConfig } from 'vite';
import nette from '@nette/vite-plugin';

export default defineConfig({
	plugins: [
		nette({
			entry: 'app.js',
		}),
	],
});

Si desea especificar otro nombre de directorio para construir sus assets, deberá cambiar algunas opciones:

export default defineConfig({
	root: 'assets', // directorio raíz de los assets fuente

	build: {
		outDir: '../www/assets',  // dónde van los archivos compilados
	},

	// ... otra configuración ...
});

La ruta outDir se considera relativa a root, por eso hay ../ al principio.

Paso 4: Configurar Nette

Informe a Nette Assets sobre Vite en su common.neon:

assets:
	mapping:
		default:
			type: vite      # le dice a Nette que use ViteMapper
			path: assets

Paso 5: Añadir scripts

Añada estos scripts a su package.json:

{
	"scripts": {
		"dev": "vite",
		"build": "vite build"
	}
}

Ahora puede:

  • npm run dev – iniciar el servidor de desarrollo con recarga en caliente
  • npm run build – crear archivos de producción optimizados

Puntos de Entrada

Un punto de entrada es el archivo principal donde comienza su aplicación. Desde este archivo, importa otros archivos (CSS, módulos JavaScript, imágenes), creando un árbol de dependencias. Vite sigue estas importaciones y agrupa todo.

Ejemplo de punto de entrada assets/app.js:

// Importar estilos
import './style.css'

// Importar módulos JavaScript
import netteForms from 'nette-forms';
import naja from 'naja';

// Inicializar su aplicación
netteForms.initOnLoad();
naja.initialize();

En la plantilla puede insertar un punto de entrada de la siguiente manera:

{asset 'app.js'}

Nette Assets genera automáticamente todas las etiquetas HTML necesarias: JavaScript, CSS y cualquier otra dependencia.

Múltiples Puntos de Entrada

Las aplicaciones más grandes a menudo necesitan puntos de entrada separados:

export default defineConfig({
	plugins: [
		nette({
			entry: [
				'app.js',      // páginas públicas
				'admin.js',    // panel de administración
			],
		}),
	],
});

Úselos en diferentes plantillas:

{* En páginas públicas *}
{asset 'app.js'}

{* En el panel de administración *}
{asset 'admin.js'}

Importante: Archivos Fuente vs Compilados

Es crucial entender que en producción solo se puede cargar:

  1. Puntos de entrada definidos en entry
  2. Archivos del directorio assets/public/

Usted no puede cargar usando {asset} archivos arbitrarios de assets/ – solo assets referenciados por archivos JavaScript o CSS. Si su archivo no es referenciado en ningún lugar, no se compilará. Si desea que Vite sea consciente de otros assets, puede moverlos a la carpeta pública.

Tenga en cuenta que, por defecto, Vite incrustará todos los assets de menos de 4KB, por lo que no podrá referenciar estos archivos directamente. (Consulte la documentación de Vite).

{* ✓ Esto funciona - es un punto de entrada *}
{asset 'app.js'}

{* ✓ Esto funciona - está en assets/public/ *}
{asset 'favicon.ico'}

{* ✗ Esto no funcionará - archivo aleatorio en assets/ *}
{asset 'components/button.js'}

Modo de Desarrollo

El modo de desarrollo es completamente opcional, pero proporciona beneficios significativos cuando está habilitado. La principal ventaja es el Hot Module Replacement (HMR): vea los cambios instantáneamente sin perder el estado de la aplicación, lo que hace que la experiencia de desarrollo sea mucho más fluida y rápida.

Vite es una herramienta de construcción moderna que hace que el desarrollo sea increíblemente rápido. A diferencia de los bundlers tradicionales, Vite sirve su código directamente al navegador durante el desarrollo, lo que significa un inicio instantáneo del servidor sin importar cuán grande sea su proyecto y actualizaciones ultrarrápidas.

Iniciando el Servidor de Desarrollo

Ejecute el servidor de desarrollo:

npm run dev

Verá:

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose

Mantenga esta terminal abierta mientras desarrolla.

El plugin Nette Vite detecta automáticamente cuándo:

  1. El servidor de desarrollo de Vite está ejecutándose
  2. Su aplicación Nette está en modo depuración

Cuando se cumplen ambas condiciones, Nette Assets carga los archivos desde el servidor de desarrollo de Vite en lugar del directorio compilado:

{asset 'app.js'}
{* En desarrollo: <script src="http://localhost:5173/app.js" type="module"></script> *}
{* En producción: <script src="/assets/app-4a8f9c7.js" type="module"></script> *}

No se necesita configuración, ¡simplemente funciona!

Trabajando en Diferentes Dominios

Si su servidor de desarrollo se ejecuta en algo diferente a localhost (como myapp.local), podría encontrarse con problemas de CORS (Cross-Origin Resource Sharing). CORS es una característica de seguridad en los navegadores web que bloquea las solicitudes entre diferentes dominios por defecto. Cuando su aplicación PHP se ejecuta en myapp.local pero Vite se ejecuta en localhost:5173, el navegador los ve como dominios diferentes y bloquea las solicitudes.

Tiene dos opciones para resolver esto:

Opción 1: Configurar CORS

La solución más sencilla es permitir solicitudes de origen cruzado desde su aplicación PHP:

export default defineConfig({
	// ... otra configuración ...

	server: {
		cors: {
			origin: 'http://myapp.local',  // la URL de su aplicación PHP
		},
	},
});

Opción 2: Ejecutar Vite en su dominio

La otra solución es hacer que Vite se ejecute en el mismo dominio que su aplicación PHP.

export default defineConfig({
	// ... otra configuración ...

	server: {
		host: 'myapp.local',  // igual que su aplicación PHP
	},
});

De hecho, incluso en este caso, necesita configurar CORS porque el servidor de desarrollo se ejecuta en el mismo nombre de host pero en un puerto diferente. Sin embargo, en este caso, CORS se configura automáticamente por el plugin Nette Vite.

Desarrollo HTTPS

Si desarrolla en HTTPS, necesita certificados para su servidor de desarrollo Vite. La forma más sencilla es usar un plugin que genere certificados automáticamente:

npm install -D vite-plugin-mkcert

Así es como se configura en vite.config.ts:

import mkcert from 'vite-plugin-mkcert';

export default defineConfig({
	// ... otra configuración ...

	plugins: [
		mkcert(),  // genera certificados automáticamente y habilita https
		nette(),
	],
});

Tenga en cuenta que si está utilizando la configuración de CORS (Opción 1 de arriba), necesita actualizar la URL de origen para usar https:// en lugar de http://.

Construcciones de Producción

Cree archivos de producción optimizados:

npm run build

Vite hará lo siguiente:

  • Minificará todo el JavaScript y CSS
  • Dividirá el código en trozos óptimos
  • Generará nombres de archivo con hash para la eliminación de caché
  • Creará un archivo manifest para Nette Assets

Ejemplo de salida:

www/assets/
├── app-4f3a2b1c.js       # Su JavaScript principal (minificado)
├── app-7d8e9f2a.css      # CSS extraído (minificado)
├── vendor-8c4b5e6d.js    # Dependencias compartidas
└── .vite/
	└── manifest.json     # Mapeo para Nette Assets

Los nombres de archivo con hash garantizan que los navegadores siempre carguen la última versión.

Carpeta Pública

Los archivos en el directorio assets/public/ se copian a la salida sin procesar:

assets/
├── public/
│   ├── favicon.ico
│   ├── robots.txt
│   └── images/
│       └── og-image.jpg
├── app.js
└── style.css

Referéncielos normalmente:

{* Estos archivos se copian tal cual *}
<link rel="icon" href={asset 'favicon.ico'}>
<meta property="og:image" content={asset 'images/og-image.jpg'}>

Para archivos públicos, puede usar las características de FilesystemMapper:

assets:
	mapping:
		default:
			type: vite
			path: assets
			extension: [webp, jpg, png]  # Probar WebP primero
			versioning: true             # Añadir eliminación de caché

En la configuración vite.config.ts puede cambiar la carpeta pública usando la opción publicDir.

Importaciones Dinámicas

Vite divide automáticamente el código para una carga óptima. Las importaciones dinámicas le permiten cargar código solo cuando realmente se necesita, reduciendo el tamaño inicial del paquete:

// Cargar componentes pesados bajo demanda
button.addEventListener('click', async () => {
	let { Chart } = await import('./components/chart.js')
	new Chart(data)
})

Las importaciones dinámicas crean fragmentos separados que se cargan solo cuando son necesarios. Esto se llama “división de código” y es una de las características más potentes de Vite. Cuando utiliza importaciones dinámicas, Vite crea automáticamente archivos JavaScript separados para cada módulo importado dinámicamente.

La etiqueta {asset 'app.js'} no precarga automáticamente estos fragmentos dinámicos. Este es un comportamiento intencional, no queremos descargar código que quizás nunca se use. Los fragmentos se descargan solo cuando se ejecuta la importación dinámica.

Sin embargo, si sabe que ciertas importaciones dinámicas son críticas y se necesitarán pronto, puede precargarlas:

{* Punto de entrada principal *}
{asset 'app.js'}

{* Precargar importaciones dinámicas críticas *}
{preload 'components/chart.js'}

Esto le dice al navegador que descargue el componente del gráfico en segundo plano, para que esté listo inmediatamente cuando sea necesario.

Soporte de TypeScript

TypeScript funciona de forma inmediata:

// assets/main.ts
interface User {
	name: string
	email: string
}

export function greetUser(user: User): void {
	console.log(`Hello, ${user.name}!`)
}

Referencie los archivos TypeScript normalmente:

{asset 'main.ts'}

Para un soporte completo de TypeScript, instálelo:

npm install -D typescript

Configuración Adicional de Vite

Aquí tiene algunas opciones de configuración útiles de Vite con explicaciones detalladas:

export default defineConfig({
	// Directorio raíz que contiene los assets fuente
	root: 'assets',

	// Carpeta cuyo contenido se copia al directorio de salida tal cual
	// Por defecto: 'public' (relativo a 'root')
	publicDir: 'public',

	build: {
		// Dónde colocar los archivos compilados (relativo a 'root')
		outDir: '../www/assets',

		// ¿Vaciar el directorio de salida antes de construir?
		// Útil para eliminar archivos antiguos de construcciones anteriores
		emptyOutDir: true,

		// Subdirectorio dentro de outDir para los fragmentos y assets generados
		// Esto ayuda a organizar la estructura de salida
		assetsDir: 'static',

		rollupOptions: {
			// Punto(s) de entrada - puede ser un solo archivo o un array de archivos
			// Cada punto de entrada se convierte en un paquete separado
			input: [
				'app.js',      // aplicación principal
				'admin.js',    // panel de administración
			],
		},
	},

	server: {
		// Host al que enlazar el servidor de desarrollo
		// Usar '0.0.0.0' para exponer a la red
		host: 'localhost',

		// Puerto para el servidor de desarrollo
		port: 5173,

		// Configuración CORS para solicitudes de origen cruzado
		cors: {
			origin: 'http://myapp.local',
		},
	},

	css: {
		// Habilitar mapas de origen CSS en desarrollo
		devSourcemap: true,
	},

	plugins: [
		nette(),
	],
});

¡Eso es todo! Ahora tiene un sistema de construcción moderno integrado con Nette Assets.

versión: 1.0