vite y deno: un experimento
Tags: javascript, vite, deno, spanish
Published: 2021-03-04 14:58:27

---
title: vite y deno: un experimento
published: true
description: vite y deno juntos ¿por qué no?
tags: #javascript #vite #deno #spanish
---

Escuchen, escuchen. [vite](https://vitejs.dev/) es un servidor de desarrollo (y algo así como un empaquetador, lo que llaman bundler) y [deno](https://deno.land/) es un entorno de ejecución que quiere actuar como un navegador web. Vamos. ¿No lo ven?

## Breve repaso

Vamos a presentar rápidamente estas herramientas, para que todos estemos al tanto.

### vite

En su página oficial lo describen como una "Herramienta Frontend de Próxima Generación." Es así porque en realidad hace un par de cosas. Tiene incorporado un servidor de desarrollo que toma ventaja de los modulos que ahora son nativos en javascript (ES modules) para ofrecer recargas rápidas e inicios instantaneos. Una de las cosas que lo hacen tan rápido es que en lugar de procesar toda tu aplicación lo que hace es lidiar con un archivo a la vez, y sólo cuando es necesario. Por defecto es capaz de procesar typescript, jsx y modulos de css, así pueden empezar crear inmediatamente. vite también puede empaquetar toda tu aplicación para su uso en "producción" si así lo desean.

### deno

`deno` es un entorno de ejecución seguro para JavaScript y TypeScript. En otras palabras, puede ejecutar javascript y typescript sin necesidad de un navegador web. Se dice que es seguro porque el código lo ejecuta en un ambiente limitado donde no tiene acceso a tu sistema. Si quieren activar ciertas funcionalidades tienen que dar permiso explícito. Lo otro que hace a `deno` interesante es que viene con un empaquetador, un formateador, un "linter," un servidor de lenguage, y otras herramientas. Esta cosa es un ambiente de desarrollo.

## ¿Por qué quiero usarlos en conjunto?

Por la manera en la que `deno` maneja el código de terceros. Verán, cuando quieren utilizar alguna librería tienen que hacerlo de la misma manera que lo harían en un navegador web, usando ES modules con una url (*guiño*). Algo así.

```js
import * as R from 'https://cdn.skypack.dev/ramda@0.27.1';
```

Esto es completamente aceptable... hasta que no lo es.

Para un script que sólo necesita un archivo es perfecto. Para proyectos más complejos hay una convención en la que ponen todas sus dependencias en un archivo llamado `deps.ts`, no es lo mejor del mundo, pero está bien. También está una funcionalidad experimental llamada [import-maps](https://deno.land/manual@v1.7.5/linking_to_external_code/import_maps#import-maps), esto mejoraría mucho el panorama.

> A partir de la versión 1.8.0 de `deno` los import-maps ya son considerados estables. [Notas del lanzamiento](https://deno.land/posts/v1.8#import-maps-are-now-stable).

En fin, quiero trabajar con esto.

```js
import * as R from 'ramda';
```

Y quiero instalar esa cosa, `ramda`, usando un manejador de dependencias "real." En la actualidad eso significa usar [npm](https://www.npmjs.com) (en deno esto casi un pecado). El problema es que `deno` no le gusta `npm`.

## vite al rescate

Digamos que queremos usar `ramda`. De nuevo, queremos usar `npm` para instalarlo, entonces lo que hacemos es esto.

```sh
npm install ramda@0.27.1
```

Ahora creamos un script, lo llamaremos `main.js`.

```js
import * as R from 'ramda';

const increment = R.map(x => x + 1);

console.log(increment([1, 2, 3]));
```

Miren qué bonito. Eso es lo que queremos. Ahora es momento de instalar `vite`.

```
npm install -D vite@2.0.4
```

Primero hagamos una prueba. Vamos a crear un archivo html, `index.html`.

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <script type="module" src="/main.js"></script>
</body>
</html>
```

Usamos `vite`.

```sh
npx vite
```

Si todo salió bien deberían tener esto en sus pantallas.

```
vite v2.0.4 dev server running at:

> Local:    http://localhost:3000/
> Network:  http://192.168.0.000:3000/

ready in 347ms.
```

Ahora si visitan `http://localhost:3000/` y luego revisan en la consola del navegador deberían tener esto.

```js
[ 2, 3, 4 ]
```

Bien. Genial. ¿Ahora cómo llevamos eso a `deno`? Mencioné que `deno` quiere actuar como un navegador. ¿Saben qué hace un navegador? Ejecuta código que viene de una url.

Pero esperen un segundo. Antes de que hagan cualquier cosa, sólo en caso de que no quieran "contaminar" el caché global que `deno` usa en su sistema, les sugiero que cambien la variable de entorno `DENO_DIR`. En su terminal hagan esto.

```sh
export DENO_DIR="$PWD/.cache"
```

> Me disculpo con los usuarios de windows, no conozco el equivalente de esto en `cmd` o `powershell`.

¿En dónde estábamos? Usando `deno`. Esto es lo que haremos, en lugar de usar el archivo `main.js` que está en nuestro directorio lo que hacemos es usar `main.js` que `vite` está sirviendo.

```sh
deno run "http://localhost:3000/main.js"
```

`deno` debería mostrarles.

```
Download http://localhost:3000/main.js
Download http://localhost:3000/node_modules/.vite/ramda.js?v=2e8a2ea4
[ 2, 3, 4 ]
```

¡Funciona! Hemos usado exitosamente una librería que viene de npm en `deno`. Es todo un logro. Pero no celebremos mucho aún. Ahora sólo por diversión, ejecuten ese comando otra vez.

```
[ 2, 3, 4 ]
```

Debió mostrarle eso, y sólo eso. No apareció nada de "download http://...". Todo está bien. Ahora bien cambien algo en `main.js`.

```diff
  import * as R from 'ramda';

  const increment = R.map(x => x + 1);
-
- console.log(increment([1, 2, 3]));
+ console.log('hello');
```

Ejecútenlo nuevamente.

¿Les apareció el texto `hello`? Apuesto a que no, y ahora quieren saber la razón.

Es porque `deno` está tomando `main.js` de un servidor (localhost) está descargando el código en su caché (la carpeta DENO_DIR), y no intentará descargarlo otra vez a menos que la url cambie. ¿Cómo resolvemos esto? Sólo se me ocurre esto.

```sh
deno run "http://localhost:3000/main.js?t=$RANDOM"
```

Aquí estoy usando un parámetro `t` para añadir un número aleatorio a la url, esto técnicamante crea una url nueva cada vez que ejecutamos el comando.

Este es el mismo método que usa `vite` para invalidar el caché de un navegador. 

Si fingimos que tenemos un archivo llamado `other.js` y lo usamos en `main.js`.

```js
import { other } from './other.js';
```

Cuando cambiemos algo en `other.js` `vite` va a añadir una estampa de tiempo en la url del archivo. Entonces, cuando se produce un cambio `deno` les mostrará algo como esto.

```
Download http://localhost:3000/other.js?t=1614653342379
```

Y ahí lo tienen, un ambiente de desarrollo con `vite` y `deno`.

## ¿Qué hacemos después?

Ya sé, ya sé, en algún momento van a querer usar esta "aplicación" que estamos desarrollando sin tener que depender de `vite`. La solución parece ser simple. En este caso usamos el comando `deno bundle`, lo que hará será tomar todo el código necesario para la aplicación y lo colocará en un solo archivo.

```sh
deno bundle "http://localhost:3000/main.js?t=$RANDOM" dist.js
```

Ahora si ejecutan `dist.js` deberían obtener los resultados esperados.

```sh
deno run dist.js
```

## Tengan presente

Sólo en caso de que no lo sepan. Incluso si pueden descargan cualquier librería desde `npm` no significa que va funcionar en `deno`. A veces esa librería que quieren usar no es compatible.

## Conclusión

Este pequeño experimento funciona, o al menos en los ejemplos triviales que hice. No recomiendo que empiecen a desarrollar aplicaciones para producción con esta combinación, aún no. Para proyectos personales y otros experimentos es perfectamente aceptable.