Usando AssetMapper con las librerías JS en Symfony

Symfony AssetMApper
Solucionex
09
Feb 24

👋 Introducción

AssetMapper es el nuevo componente Symfony que llega para hacernos la vida más fácil a la hora de trabajar con CSS y Javascript moderno sin necesidad de hacer uso de herramientas de precompilación. Ya en un artículo anterior comentábamos este nuevo componente, novedad de la versión 6.3 del framework. A día de hoy, con la llegada de la nueva versión 6.4 y 7, se afianza como la opción por defecto del framework a la hora de trabajar con Javascript y CSS. Pero... ¿Hasta dónde llega?

Una de las características que nos promete1 es la posibilidad de trabajar en nuestras plantillas Twig, gracias también al componente Symfony UX, con las diferentes librerías Javascript modernas del mercado: React, Vue y Svelte. Veámos un ejemplo:

(1) Tanto en la documentación oficial como en la de cada componente UX de integración con las librerías en cuestión, hacen mención a que pese a que se puede utilizar con AssetMapper, recomiendan hacer uso de WebpackEncore para un mejor desempeño.

 

✍️ Ejemplos de uso

 

🇻 AssetMapper con Vue

Por el momento, AssetMapper no nos permite utilizar los single-file componentes (.vue), sin embargo podemos hacer uso de la librería utilizando archivos puramente Javascript como el del siguiente ejemplo.

 

Lógica del componente

import { ref, computed } from 'vue';
import PackageList from "../components/PackageList.js";
export default {
    components: {
        PackageList
    },
    props: ['packages'],
    setup(props) {
        const search = ref('');
        const filteredPackages = computed(() => {
            return props.packages.filter(
                uxPackage => uxPackage.humanName.toLowerCase().includes(search.value.toLowerCase())
            );
        });
        return {
            search,
            filteredPackages
        }
    },
    template: `
        <div>
            <input
                v-model="search"
                class="form-control"
                type="search"
                placeholder="This search is built in Vue.js!"
            />
            <div class="mt-3">
                <PackageList :packages="filteredPackages" />
            </div>
        </div>
    `
};
 

Integración en Twig

{% extends 'packageBase.html.twig' %}
{% block importmap %}
    {{ importmap('app-vue') }}
{% endblock %}
{% block package_header %}
    {% component PackageHeader with {
        package: 'vue',
        eyebrowText: 'Vue.js Component Rendering'
    } %}
        {% block title_header %}
            Render Vue.js from <em>inside Twig</em>
        {% endblock %}
        {% block sub_content %}
            Built a Vue.js component? Render it quickly &amp; easily in Twig <em>and</em> pass in dynamic props.
        {% endblock %}
    {% endcomponent %}
{% endblock %}
{% block code_block_left %}
    <twig:CodeBlock filename="templates/ux_packages/vue.html.twig" height="350px"/>
{% endblock %}
{% block code_block_right %}
    <twig:CodeBlock
        filename="assets/vue/controllers/PackageSearch.js"
        height="350px"
        language="html"
    />
{% endblock %}
{% block demo_title %}UX Vue.js{% endblock %}
{% block demo_content %}
    <div {{ vue_component('PackageSearch', {
        packages: packagesData
    }) }}>
        Loading... <i class="fas fa-cog fa-spin fa-3x"></i>
    </div>
{% endblock %}

 

🇸 AssetMapper con Svelte

En el caso de Svelte, si tenemos posibilidad de utilizar los archivos .svelte, saliéndonos del proceso estándar del componente y haciendo uso de la librería que nos permite compilar estos archivos a Javascript puro y utilizar la librería de la siguiente manera:

 

Lógica del componente

<script>
    import PackageList from '../components/PackageList.js';
    export let packages = [];
    let search = '';
    $: filteredPackages = packages.filter(
        uxPackage => uxPackage.humanName.toLowerCase().includes(search.toLowerCase())
    );
</script>
<div>
    <input
        bind:value={search}
        class='form-control'
        type='search'
        placeholder='This search is built in Svelte!'
    />
    <div class='mt-3'>
        <PackageList packages={filteredPackages} />
    </div>
</div>
 

Integración con Twig

{% extends 'base.html.twig' %}
{% block body %}
    <div {{ svelte_component('PackageSearch', {
        packages: packagesData,
    }) }}>
        Loading... <i class="fas fa-cog fa-spin fa-3x"></i>
    </div>
{% endblock %}

 

🇷 AssetMapper con React transpilando JSX

En este caso, si queremos utilizar el formato .jsx, deberemos de instalar algunos paquete para la transpilación en archivos Javascript puros. En su defecto, podemos utilizar React de la siguiente forma:

 

Lógica del componente

import React, { Component } from 'react';
import PackageList from '../components/PackageList.js';
export default class extends Component {
    constructor() {
      super();
      this.state = {
        search: ''
      }
    }
    render() {
        return (
            <div>
                <input
                    type="search"
                    placeholder="This search is built in React!"
                    className="form-control"
                    value={this.state.search}
                    onChange={(event) => this.setState({search: event.target.value})}
                />
                <div className="mt-3">
                    <PackageList packages={this.filteredPackages()} />
                </div>
            </div>
        );
    }
    filteredPackages() {
        if (!this.state.search) {
            return this.props.packages;
        }
        return this.props.packages.filter((uxPackage) => {
            return uxPackage.humanName.toLowerCase().includes(this.state.search.toLowerCase())
        });
    }
}
 

Integración con Twig

{% extends 'base.html.twig' %}
{% block body %}
   <div {{ react_component('PackageSearch', {
       packages: packagesData
   }) }}>
       Loading... <i class="fas fa-cog fa-spin fa-3x"></i>
   </div>
{% endblock %}

 

 

🔗 Enlaces interesantes:

Imagen de portada generada con ChatGPT gracias a la tecnologías Dall-e 3

symfony