Skip to content

Más allá de la velocidad

ViteConf 2023

¡Mira la repetición!

Migración desde v4

Soporte de Node.js

Vite ya no es compatible con Node.js 14/16/17/19, versiones que alcanzaron su final de soporte. Ahora se requiere Node.js 18/20+.

Rollup 4

Vite ahora está usando Rollup 4, que también trae consigo sus cambios importantes, en particular:

  • Se ha cambiado el nombre de importar aserciones (propiedad assertions) a importar atributos (propiedad attributes).
  • Los complementos de Acorn ya no son compatibles.
  • Para los complementos de Vite, la opción this.resolve skipSelf ahora es true por defecto.
  • Para los complementos de Vite, this.parse ahora solo soporta la opción allowReturnOutsideFunction por ahora.

Lee los cambios importantes completos en las notas de la versión de Rollup para conocer los cambios relacionados con la compilación en build.rollupOptions.

Si estás utilizando TypeScript, asegúrate de configurar moduleResolution: 'bundler' (o node16/nodenext) ya que Rollup 4 lo requiere. O puedes configurar skipLibCheck: true en su lugar.

API de Node para la compilación CJS de Vite, ahora obsoleta

La API de Node para la compilación CJS de Vite ahora está en desuso. Al llamar a require('vite'), ahora se registra una advertencia de obsolescencia. En su lugar, debes actualizar tus archivos o frameworks para importar la compilación ESM de Vite.

En un proyecto básico de Vite, asegúrate que:

  1. El contenido del archivo vite.config.js utiliza la sintaxis ESM.
  2. El archivo package.json más cercano tiene "type": "module", o usa la extensión .mjs/.mts, por ejemplo, vite.config.mjs o vite.config.mts.

Para otros proyectos, existen algunos enfoques generales:

  • Configura ESM como predeterminado, optar por CJS si es necesario: Agrega "type": "module" en el package.json del proyecto. Todos los archivos *.js ahora se interpretan como ESM y deben utilizar la sintaxis de ESM. Puedes cambiar el nombre de un archivo con la extensión .cjs para seguir usando CJS.
  • Mantén CJS como predeterminado, optar por ESM si es necesario: Si el package.json del proyecto no tiene "type": "module", todos los archivos *.js se interpretan como CJS. Puedes cambiar el nombre de un archivo con la extensión .mjs para usar ESM en su lugar.
  • Importar Vite dinámicamente: Si necesitas seguir usando CJS, puedes importar Vite dinámicamente usando import('vite') en su lugar. Esto requiere que tu código esté escrito en un contexto "asíncrono", pero aún así debería ser manejable ya que la API de Vite es en su mayoría asíncrona.

Consulta la guía de solución de problemas para obtener más información.

Reelaborada la estrategia de reemplazo de define e import.meta.env.*

En Vite 4, las funciones define e import.meta.env.* utilizan diferentes estrategias de reemplazo en desarrollo y compilación:

  • En desarrollo, ambas funciones se inyectan como variables globales en globalThis e import.meta respectivamente.
  • En la compilación, ambas funciones se reemplazan estáticamente con una expresión regular.

Esto da como resultado una inconsistencia en el desarrollo y la compilación al intentar acceder a las variables y, a veces, incluso provoca compilaciones fallidas. Por ejemplo:

js
// vite.config.js
export default defineConfig({
  define: {
    __APP_VERSION__: JSON.stringify('1.0.0'),
  },
})
js
const data = { __APP_VERSION__ }
// dev: { __APP_VERSION__: "1.0.0" } ✅
// build: { "1.0.0" } ❌

const docs = 'Me gusta import.meta.env.MODE'
// dev: "Me gusta import.meta.env.MODE" ✅
// build: "Me gusta "production"" ❌

Vite 5 soluciona este problema usando esbuild para manejar los reemplazos en las compilaciones, alineándose con el comportamiento de desarrollo.

Este cambio no debería afectar a la mayoría de las configuraciones, de hecho ya está documentado que los valores define deben seguir la sintaxis de esbuild:

Para ser coherente con el comportamiento de esbuild, las expresiones deben ser un objeto JSON (null, Boolean, number, string, array, o object) o un único identificador.

Sin embargo, si prefieres que se sigan reemplazado valores estáticamente de forma directa, puedes usar @rollup/plugin-replace.

Cambios generales

El valor de los módulos externalizados SSR ahora coincide con producción

En Vite 4, los módulos externalizados de SSR están empaquetados con el manejo .default y .__esModule para una mejor interoperabilidad, pero no coinciden con el comportamiento en producción cuando se cargan mediante el entorno de ejecución (por ejemplo, Node.js), lo que genera dificultades para depurar inconsistencias. Por defecto, todas las dependencias directas del proyecto están externalizadas por SSR.

Vite 5 ahora elimina el manejo de .default y .__esModule para que coincida con el comportamiento de producción. En la práctica, esto no debería afectar las dependencias empaquetadas correctamente, pero si encuentras nuevos problemas al cargar módulos, puedes probar estas reescrituras:

js
// Antes:
import { foo } from 'bar'

// Después:
import _bar from 'bar'
const { foo } = _bar
js
// Antes:
import foo from 'bar'

// Después:
import * as _foo from 'bar'
const foo = _foo.default

Ten en cuenta que estos cambios coinciden con el comportamiento de Node.js, por lo que también puedes ejecutar las importaciones en Node.js para probarlo. Si prefieres seguir con el comportamiento anterior, puedes configurar legacy.proxySsrExternalModules en true.

worker.plugins ahora es una función

En Vite 4, worker.plugins aceptaba una serie de complementos ((Plugin | Plugin[])[]). Desde Vite 5, debe configurarse como una función que devuelve una serie de complementos (() => (Plugin | Plugin[])[]). Este cambio es necesario para que las compilaciones paralelas de workers se ejecuten de manera más consistente y predecible.

Habilitado que las rutas que contienen . recurran a index.html

En Vite 4, acceder a una ruta en dev que contenía . no recurría a index.html incluso si appType estaba configurado en 'spa' (predeterminado). Desde Vite 5, recurrirá a index.html.

Ten en cuenta que el navegador ya no mostrará un mensaje de error 404 en la consola si apuntas la ruta de la imagen a un archivo inexistente (por ejemplo, <img src="./file-does-not-exist.png">).

Alineado el comportamiento de servido HTML para desarrollo y vista previa

En Vite 4, los servidores de desarrollo y vista previa sirven HTML según su estructura de directorio y barra diagonal de manera diferente. Esto provoca inconsistencias al probar la aplicación creada. Vite 5 se refactoriza en un solo comportamiento como se muestra a continuación, dada la siguiente estructura de archivos:

├── index.html
├── file.html
└── dir
    └── index.html
SolicitudAntes (desarrollo)Después (vista previa)Después (desarrollo y vista previa)
/dir/index.html/dir/index.html/dir/index.html/dir/index.html
/dir/index.html (redirección SPA)/dir/index.html/index.html (redirección SPA)
/dir//dir/index.html/dir/index.html/dir/index.html
/file.html/file.html/file.html/file.html
/file/index.html (redirección SPA)/file.html/file.html
/file//index.html (redirección SPA)/file.html/index.html (redirección SPA)

Los archivos de manifiesto ahora se generan en el directorio .vite por defecto

En Vite 4, los archivos de manifiesto (build.manifest y build.ssrManifest) se generaban en la raíz de build.outDir por defecto.

A partir de Vite 5, se generarán en el directorio .vite en build.outDir por defecto. Este cambio ayuda a eliminar el conflicto de archivos públicos con los mismos nombres de los archivos de manifiesto cuando se copian en build.outDir.

Los archivos CSS correspondientes no se listan como entrada de nivel superior en el archivo manifest.json

En Vite 4, el archivo CSS correspondiente a un punto de entrada de JavaScript también se listaba como una entrada de nivel superior en el archivo de manifiesto (build.manifest). Estas entradas se agregaban involuntariamente y solo funcionaban para casos simples.

En Vite 5, los archivos CSS correspondientes solo se pueden encontrar dentro de la sección del archivo JavaScript de entrada. Cuando se inyecta el archivo JS, los archivos CSS correspondientes deben ser inyectados. Cuando el CSS debe ser inyectado por separado, debe agregarse como una entrada separada.

Los accesos directos de CLI requieren una pulsación adicional de "Intro"

Los atajos del CLI, como r para reiniciar el servidor de desarrollo, ahora requieren presionar un Enter adicional para activar el atajo. Por ejemplo, r + Enter para reiniciar el servidor de desarrollo.

Este cambio evita que Vite absorba y controle accesos directos específicos del sistema operativo, lo que permite una mejor compatibilidad al combinar el servidor de desarrollo de Vite con otros procesos y evita las advertencias anteriores.

Actualizado el comportamiento de TypeScript experimentalDecorators y useDefineForClassFields

Vite 5 usa esbuild 0.19 y elimina la capa de compatibilidad para esbuild 0.18, lo que cambia la forma en que se manejan experimentalDecorators y useDefineForClassFields.

  • experimentalDecorators no está habilitado por defecto

    Debes configurar compilerOptions.experimentalDecorators en true en tsconfig.json para usar los decoradores.

  • Los valores por defecto de useDefineForClassFields dependen del valor target de TypeScript

    Si target no es ESNext o ES2022 o más reciente, o si no hay un archivo tsconfig.json, useDefineForClassFields por defecto será false, lo que puede ser problemático con el valor por defecto de esbuild.target de ESNext. Puede transpilarse a bloques de inicialización estáticos que pueden no ser compatibles con tu navegador.

    Como tal, se recomienda configurar target en ESNext o ES2022 o más reciente, o configurar useDefineForClassFields en true explícitamente en el tsconfig.json.

jsonc
{
  "compilerOptions": {
    // Configurar en true si deseas usar decoradores
    "experimentalDecorators": true,
    // Configurar en true si ves errores de análisis en tu navegador
    "useDefineForClassFields": true
  }
}

Eliminada los indicadores --https y https: true

El indicador --https configura server.https: true y preview.https: true internamente. Esta configuración estaba destinada a usarse junto con la función de generación automática de certificación https que se eliminó en Vite 3. Esto indica que dicha configuración ya no es útil, ya que iniciará un servidor HTTPS de Vite sin un certificado.

Si usas @vitejs/plugin-basic-ssl o vite-plugin-mkcert, estas configurarán https internamente, por lo que puedes eliminar --https, server.https: true y preview.https: true.

Eliminadas las APIs resolvePackageEntry y resolvePackageData

Las APIs resolvePackageEntry y resolvePackageData se eliminan ya que exponían componentes internos de Vite y bloqueaban posibles optimizaciones de Vite 4.3 en el pasado. Estas APIs se pueden reemplazar con paquetes de terceros, por ejemplo:

  • resolvePackageEntry: import.meta.resolve o el paquete import-meta-resolve.
  • resolvePackageData: igual que arriba, rastreando el directorio del paquete para obtener la ruta raíz de package.json. O utiliza el paquete de la comunidad vitefu.
js
import { resolve } from 'import-meta-env'
import { findDepPkgJsonPath } from 'vitefu'
import fs from 'node:fs'

const pkg = 'my-lib'
const basedir = process.cwd()

// `resolvePackageEntry`:
const packageEntry = resolve(pkg, basedir)

// `resolvePackageData`:
const packageJsonPath = findDepPkgJsonPath(pkg, basedir)
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))

APIs obsoletas eliminadas

  • Exportaciones predeterminadas de archivos CSS (por ejemplo, import style from './foo.css'): usa la consulta ?inline en su lugar
  • import.meta.globEager: usa import.meta.glob('*', { eager: true }) en su lugar
  • ssr.format: 'cjs' y legacy.buildSsrCjsExternalHeuristics (#13816)
  • server.middlewareMode: 'ssr' y server.middlewareMode: 'html': Usa appType + server.middlewareMode: true en su lugar (#8452)

Avanzado

Hay algunos cambios que solo afectan a los creadores de complementos/herramientas.

También hay otros cambios importantes que sólo afectan a unos pocos usuarios.

Migración desde v3

Consulta primero la Guía de migración desde v3 para ver los cambios necesarios para migrar tu aplicación a Vite v4, y luego continúa con los cambios en esta página.

Publicado bajo licencia MIT. (31993f54)