> For the complete documentation index, see [llms.txt](https://doc.velneo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://doc.velneo.com/38/velneo-vclient-web/como-incrustar-una-aplicacion-de-velneo-web-en-un-div-de-una-pagina-html.md).

# Cómo incrustar una aplicación de Velneo Web en un DIV de una página html

En primer lugar, necesitamos el paquete **velneo-web-assets.zip** con los binarios de Velneo Web (si eres suscriptor, puedes solicitarlo a soporte de Velneo). El paquete contiene:

* Un directorio con el número de la versión (por ejemplo, `38.0.0`) con los ficheros de Velneo vClient Web: `vClient.wasm.br`, `vClient.js.br`, `vClient.html.br`, `wasm-bridge.js.br` y `qtloader.js.br`.
* El directorio **wasmDiv**, con un ejemplo listo para usar: `config.json`, `js/app.js` y `README.md`.

{% hint style="danger" %}
No poner directamente en producción sin antes leer detenidamente esta documentación.
{% endhint %}

{% hint style="warning" %}
Este procedimiento es válido a partir de la versión 38. El ejemplo de versiones anteriores, basado en `qtloader.js` y `app.js`, no funciona con Velneo vClient Web 38.
{% endhint %}

## Pasos para la instalación

### Ajuste de rutas

Copiaremos en nuestro servidor web los ficheros del directorio **wasmDiv** y el directorio de la versión tal cual viene en el paquete, sin renombrarlo ni reorganizarlo. Por ejemplo:

```
/tu-web/
├── index.html          tu página
├── config.json
├── js/app.js
└── 38.0.0/
    ├── vClient.wasm.br
    ├── vClient.js.br
    ├── vClient.html.br
    ├── wasm-bridge.js.br
    └── qtloader.js.br
```

Donde **index.html** es la página web donde queremos incluir Velneo vClient Web.

### Contenido de la página

En nuestra página debemos añadir dos elementos y cargar dos scripts:

```html
<!-- Donde se dibuja la aplicación y donde se muestran los mensajes de estado -->
<div id="screen" style="width: 100%; height: 100vh;"></div>
<div id="qtstatus"></div>

<!-- Primero el bridge, cargado desde el directorio de la versión -->
<script src="38.0.0/wasm-bridge.js"></script>
<script src="js/app.js"></script>
```

* El elemento **screen** es donde se dibuja la aplicación, y **qtstatus**, donde se muestran los mensajes de estado. Si en nuestra página tienen otros identificadores, debemos cambiarlos en las variables `ID_CONTENEDOR` e `ID_ESTADO` de **app.js**.
* El atributo `src` de **wasm-bridge.js** indica dónde están los ficheros de la aplicación: los busca en su mismo directorio. No hay que configurar ninguna otra ruta.
* **wasm-bridge.js** debe cargarse con una etiqueta `<script>` normal, sin `async` ni `defer`.

Cuando actualicemos a una nueva versión, basta con copiar el nuevo directorio de la versión y cambiar el `src` de **wasm-bridge.js**.

### Ajuste de parámetros

Los datos de conexión se indican en el fichero **config.json**:

```json
{
    "servidor": "cX.velneo.com",
    "puertoWebsockets": "699",
    "instancia": "ID_INSTANCIA_APP_WEB",
    "usuario": "CAMBIAME",
    "password": "CAMBIAME"
}
```

* **servidor**: nombre del servidor de Velneo.
* **puertoWebsockets**: puerto de Velneo vServer más 9. Por ejemplo, si Velneo vServer escucha en el 690, se indicará 699.
* **instancia**: identificador de la instancia a la que se conecta.
* **usuario** y **password**: credenciales de acceso.

El fichero **app.js** lee esta configuración y arranca la aplicación; no hace falta modificarlo.

{% hint style="warning" %}
**config.json** se sirve al navegador como cualquier otro fichero, por lo que cualquiera que visite la página puede leer las credenciales. Úsalo así solo para pruebas o con un usuario con permisos mínimos. En producción, genera la configuración desde el servidor (por ejemplo, con PHP o Node) con las credenciales del usuario que ha iniciado sesión en tu web.
{% endhint %}

También es posible enviar valores a la instancia que se carga añadiendo a la lista `args` de **app.js** un nuevo elemento con el parámetro `/userParam`. Lo que enviemos ahí, ya sea un JSON, un base64 o un token JWT, llega a la instancia y puede procesarse en el `onInit`. El uso de un token JWT como parámetro en web permite gestionar la autenticación de usuarios: recibiendo la información del usuario en la aplicación, podremos gestionar lo que necesitemos para identificarlo.

{% hint style="info" %}
Esto es para tu propia página, donde los argumentos los escribes tú. En las páginas que no editas —Velneo vClient Web, la vLanzadera o la que sirve Velneo vServer— el mismo valor se pasa en la dirección con [appArgs](/38/velneo-vclient-web.md#estructura-de-la-url-para-ejecutar-aplicaciones-web).
{% endhint %}

### Ajustes del servidor web

Sin estos dos ajustes, la aplicación no arranca.

**1. Cabeceras de aislamiento.** Velneo vClient Web necesita `SharedArrayBuffer`, y los navegadores solo lo permiten si el servidor envía estas cabeceras:

```
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

Con `require-corp`, las imágenes, fuentes o scripts que la página cargue desde otro dominio dejarán de funcionar, salvo que ese dominio lo permita expresamente.

**2. Servir los ficheros .br.** Los ficheros de la aplicación vienen comprimidos en formato [brotli](https://es.wikipedia.org/wiki/Brotli), con la extensión `.br` en el nombre. El servidor web debe responder a la petición del fichero sin `.br` sirviendo el `.br` con la cabecera de codificación correspondiente. En Apache:

```apache
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTP:Accept-Encoding} br
    RewriteCond %{REQUEST_FILENAME}.br -s
    RewriteRule ^(.*)$ $1.br [QSA]
</IfModule>

<IfModule mod_headers.c>
    Header set Content-Encoding br "expr=%{REQUEST_URI} =~ /\.br$/"
    Header append Vary Accept-Encoding
</IfModule>

AddType application/wasm .wasm
```

En nginx, se consigue con `brotli_static on;` en el bloque que sirve el directorio de la versión.

Si el servidor web no puede hacerlo, se pueden descomprimir los ficheros y quitarles la extensión `.br`: la aplicación funciona igual, pero la descarga es mayor.

## Si no arranca

Abriremos las herramientas de desarrollo del navegador y revisaremos la consola y la pestaña **Red**:

* **SharedArrayBuffer is not defined**: faltan las cabeceras de aislamiento.
* **404 de vClient.js o vClient.wasm**: el servidor no resuelve los ficheros `.br`, o el directorio de la versión no está donde apunta el `src` de **wasm-bridge.js**.
* **Error de configuración**: **config.json** no existe en la raíz o tiene un error de sintaxis.
* **No se encontró el elemento "screen"**: en la página falta el `<div id="screen">`, o tiene otro identificador y no se ha cambiado en **app.js**.
* **Faltan datos por rellenar en config.json**: los datos indicados siguen con el valor `CAMBIAME` del ejemplo.
* **Se queda cargando y no conecta**: revisa en **config.json** los datos **servidor**, **puertoWebsockets** e **instancia**.
* **wasmBridge is not defined**: no se ha cargado **wasm-bridge.js**; revisa el `src` de la etiqueta `<script>` y que no lleve `async` ni `defer`.
