gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
AssetMapper no es gran cosa. Seguro que se viste genial y tiene buenos movimientos de baile, pero en realidad es bastante sencillo. Tiene dos características principales.
Característica número uno: configuramos "rutas" -como el directorio assets/
- y hace públicos los archivos que contiene.
Veámoslo en acción. Si te has descargado el código del curso, deberías tener un directoriotutorial/
con un importante archivo penguin.png
en su interior. Cópialo. Dentro de assets/
, podemos organizar las cosas como queramos. Así que vamos a crear un directorioimages/
y a transportar allí a nuestro pingüino.
Ahora, recuerda, sin la magia de AssetMapper, los únicos archivos a los que nuestro navegador debería poder acceder son los que están dentro del directorio public/
. Así que debería ser imposible añadir una etiqueta img
que cargue nuestro pingüino. Pero... es posible.
Dirígete a, qué tal, templates/base.html.twig
. En cualquier lugar -iré por encima del bloquebody
- añade un img
con src="{{ asset() }}"
pasándole la ruta a nuestro archivo relativa al directorio assets/
. Así que images/penguin.png
.
... lines 1 - 20 | |
<body class="bg-gray-800 text-white"> | |
... lines 22 - 49 | |
<img src="{{ asset('images/penguin.png') }}"> | |
... lines 51 - 69 | |
</body> | |
... lines 71 - 72 |
Ya está. Esto se conoce como la "ruta lógica" al activo. Como hemos apuntado AssetMapper al directorio assets/
, podemos referirnos a cosas dentro de él a través de su ruta relativa a esa raíz.
Y hay una forma estupenda de ver todos los activos que están en las rutas de AssetMapper yendo al terminal y ejecutando:
php bin/console debug:asset
¡Genial! En primer lugar, en la parte superior, muestra las rutas de AssetMapper, incluido el directorio assets/
. Este proyecto también tiene instalado Pagerfanta. Y ya estamos viendo cómo los bundles pueden añadir sus propias rutas AssetMapper para que sus propios archivos estén disponibles públicamente. Esto no será importante para nosotros, pero podríamos dirigir el navegador a cualquier archivo dentro de ese directorio del bundle.
A continuación, vemos nuestro archivo de imagen, nuestro archivo CSS y nuestro archivo JavaScript. Estas son sus rutas en el sistema de archivos y estas son sus rutas lógicas.
La cuestión es que, utilizando la función asset()
y la ruta lógica a un activo, cuando actualizamos... ¡funciona! ¡Woh! Y si inspeccionamos el elemento, ¡mira la URL! ¡Contiene un hash de versión en el medio! En realidad voy a ver la fuente de la página... es un poco más fácil de ver.
Así que no sólo penguin.png
está disponible públicamente, sino que la ruta no es sólopenguin.png
: contiene un hash de versión. Si modificáramos el archivo fuente penguin.png
-por ejemplo, poniéndole una pajarita chula- el hash de la versión cambiaría automáticamente, obligando a cualquiera que utilizara nuestro sitio a descargar el archivo nuevo. ¡Booya!
Así es como se carga app.css
En la parte superior, la etiqueta de enlace utilizaasset('styles/app.css')
, que es la ruta lógica en AssetMapper a ese archivo. Y así también sale con un bonito nombre de archivo versionado.
Vale, pero ¿cómo funciona esto? Si eres como yo, querrás saber cómo se hacen las salchichas. Bueno, en el entorno dev
, funciona gracias a un oyente de eventos del núcleo... básicamente un elegante controlador interno de Symfony.
Por ejemplo, cuando el navegador carga esta imagen, esa petición pasa por Symfony. Ve que estamos intentando cargar /assets/images/penguin-versionhash.png
, encuentra el archivo fuente y lo sirve.
¡Podemos probarlo! En la pestaña principal, haz clic en cualquier icono de la barra de herramientas de depuración web para entrar en el perfilador y, a continuación, haz clic en "Últimas 10" para ver las 10 peticiones más recientes a través de Symfony. Y ahí está: la petición que sirvió la imagen del pingüino. Adorable.
En producción, cargar nuestros archivos a través de Symfony no sería lo suficientemente rápido. Así que, en su lugar, durante el despliegue, ejecutarás un nuevo comando de consola:
php bin/console asset-map:compile
Hablaremos más sobre el despliegue más adelante. ¡Pero esto es realmente genial! Copia cada archivo de cada ruta AssetMapper en el directorio public/assets/
utilizando su nombre de archivo versionado. Y ya está.
De repente, este archivo ya no está siendo servido por Symfony: ¡estamos viendo un archivo real, físico! En public/assets/
, ¡sí! Podemos ver los archivos finales en todo su esplendor.
Pero... mientras desarrollamos, elimina ese directorio para que todo siga cargándose dinámicamente.
Y ya que estamos aquí, ¿ves esos favicons dentro del directorio public/
? Estamos enlazando con ellos en la parte superior de base.html.twig
. Eso funciona perfectamente: la funciónasset()
puede seguir haciendo referencia a cosas dentro del directorio public/
.
... lines 1 - 2 | |
<head> | |
... lines 4 - 7 | |
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('apple-touch-icon.png') }}"> | |
<link rel="icon" type="image/png" sizes="32x32" href="{{ asset('favicon-32x32.png') }}"> | |
<link rel="icon" type="image/png" sizes="16x16" href="{{ asset('favicon-16x16.png') }}"> | |
... lines 11 - 19 | |
</head> | |
... lines 21 - 72 |
Pero... ¡sin apenas trabajo, podemos añadirles el versionado libre de activos! Paso 1: muévelos al directorio assets/images/
. Paso 2: añade a cada ruta el prefijoimages/
para obtener su ruta lógica.
Y... así de fácil, seguimos viendo el favicon aquí arriba... pero lo que es más importante, si vemos el código fuente de la página, ¡ahora están versionados!
A continuación, profundicemos un poco más en los archivos CSS. Por ejemplo, ¿cómo podemos referirnos a imágenes de fondo desde dentro de CSS... si el nombre final del archivo está versionado?
Hey @pasquale_pellicani!
nice to find that symfony goes back, abandoning once and for all the prebuilt js in favor of assets
I'm pretty happy too - it's really nice to work with :)
Does this method promise to become the best way to deal with css and js or is it just an alternative
I can't say for sure. My best guess right now is that we, for the next few years, will have 2 paths. The "build" systems are now so widely used, that I think it will take time for people to realize that they don't need it. And, build systems WILL still exist forever, at the very least, to handle things like JSX, Vue, etc. The challenge over the next 12 months will be to (A) continue improving the DX for asset mapper (we have some work to do on 6.4 for this, especially related to making CSS nicer to use I think) and (B) reminding people this exists and it's excellent! It also helps that we're leveraging "web standards" (e.g. importmaps, ECMAScript code).
Anyway, we'll see. But there is nothing preventing this method from becoming the main way of handling things for non-SPA sites.
Cheers!
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"babdev/pagerfanta-bundle": "^4.0", // v4.2.0
"doctrine/doctrine-bundle": "^2.7", // 2.10.0
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.4
"doctrine/orm": "^2.12", // 2.15.2
"knplabs/knp-time-bundle": "^1.18", // v1.20.0
"pagerfanta/doctrine-orm-adapter": "^4.0", // v4.1.0
"pagerfanta/twig": "^4.0", // v4.1.0
"stof/doctrine-extensions-bundle": "^1.7", // v1.7.1
"symfony/asset": "6.3.*", // v6.3.0
"symfony/asset-mapper": "6.3.*", // v6.3.0
"symfony/console": "6.3.*", // v6.3.0
"symfony/dotenv": "6.3.*", // v6.3.0
"symfony/flex": "^2", // v2.3.1
"symfony/framework-bundle": "6.3.*", // v6.3.0
"symfony/http-client": "6.3.*", // v6.3.0
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/proxy-manager-bridge": "6.3.*", // v6.3.0
"symfony/runtime": "6.3.*", // v6.3.0
"symfony/stimulus-bundle": "^2.9", // v2.9.1
"symfony/twig-bundle": "6.3.*", // v6.3.0
"symfony/ux-turbo": "^2.9", // v2.9.1
"symfony/web-link": "6.3.*", // v6.3.0
"symfony/yaml": "6.3.*", // v6.3.0
"twig/extra-bundle": "^2.12|^3.0", // v3.6.1
"twig/twig": "^2.12|^3.0" // v3.6.1
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.4
"symfony/debug-bundle": "6.3.*", // v6.3.0
"symfony/maker-bundle": "^1.41", // v1.49.0
"symfony/stopwatch": "6.3.*", // v6.3.0
"symfony/web-profiler-bundle": "6.3.*", // v6.3.0
"zenstruck/foundry": "^1.21" // v1.33.0
}
}
Hi, nice to find that symfony goes back, abandoning once and for all the prebuilt js in favor of assets, among other things that of assets is a very old (not bad) concept used by an excellent framework (I won't name names) considered minor compared to symfony. Does this method promise to become the best way to deal with css and js or is it just an alternative? Thanks