Chapters
-
Course Code
Subscribe to download the code!
Subscribe to download the code!
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Vale, ¿cómo vamos a introducir CSS y JavaScript en nuestra aplicación? ¿Vamos a añadir un sistema de compilación como Vite o Webpack? ¡Pues no! ¡Esa es una de las cosas divertidas de todo esto! Vamos a crear algo increíble sin ningún sistema de compilación. Para ello, vamos a instalar un nuevo componente de Symfony llamado AssetMapper.
Instalar AssetMapper
Gira hasta nuestro terminal y ejecuta:
composer require symfony/asset-mapper
Esta es la nueva alternativa a Webpack Encore. Puede hacer prácticamente todo lo que Encore puede hacer y más... pero es mucho más sencillo. Definitivamente deberías utilizarla en los nuevos proyectos.
Al Ejecuta:
git status
Vemos que su receta Flex ha realizado una serie de cambios. Por ejemplo, .gitignore
está ignorando un directorio public/assets/
y assets/vendor/
:
Show Lines
|
// ... lines 1 - 11 |
###> symfony/asset-mapper ### | |
/public/assets/ | |
/assets/vendor | |
###< symfony/asset-mapper ### |
Hablaremos más sobre esto más adelante. Pero en producción, aquí es donde se escribirán tus activos y, cuando instalemos bibliotecas JavaScript de terceros, vivirán en ese directorio vendor/
.
También actualiza base.html.twig
y añade un archivo importmap.php
. Pero déjalos en un segundo plano por ahora: hablaremos de ellos mañana.
Las "rutas mapeadas
Para la aventura de hoy, imagina que, cuando instalamos esto, lo único que nos dio fue un nuevo archivoasset_mapper.yaml
y un directorio assets/
. Vamos a comprobar ese archivo de configuración: config/packages/asset_mapper.yaml
:
framework: | |
asset_mapper: | |
# The paths to make available to the asset mapper. | |
paths: | |
- assets/ |
La idea de AssetMapper no podría ser más sencilla: defines rutas -como el directorioassets/
- y AssetMapper hace que todos los archivos que contengan estén disponibles públicamente... como si vivieran en el directorio public/
.
Hacer referencia a un archivo de activos
Veámoslo en acción tú. Si te has descargado el código del curso, deberías tener un directorio tutorial/
, que he añadido para que podamos copiar algunas cosas de él. Copia logo.png
. Dentro de assets/
, podemos darle el aspecto que queramos. Así que vamos a crear un nuevo directorio llamado images/
y a pegarlo dentro.
Como este nuevo archivo vive dentro del directorio assets/
, deberíamos poder referenciarlo públicamente. Hagámoslo en nuestro diseño base: templates/base.html.twig
. En cualquier lugar, di <img src="">
, {{
y luego utiliza la función normal asset()
. Como argumento, pasa la ruta relativa al directorio assets/
. Esto se llama la ruta lógica: images/logo.png
:
<!DOCTYPE html> | |
<html> | |
Show Lines
|
// ... lines 3 - 14 |
<body> | |
<img src="{{ asset('images/logo.png') }}" alt="Space Inviters Logo" /> | |
Show Lines
|
// ... lines 17 - 18 |
</body> | |
</html> |
Antes de probar esto, una forma fácil de ver todos los activos disponibles es mediante:
php bin/console debug:asset
Muy sencillo: esto busca en todas tus rutas mapeadas -sólo assets/
para nosotros-, encuentra cada archivo y luego los enumera con su ruta lógica. Así que puedo ser perezoso y copiar eso, pegarlo aquí.... y listo.
Ahora bien, cuando probamos esto, ¡no funciona! La función asset()
sigue siendo un componente propio, así que vamos a instalarla:
composer require symfony/asset
Y ahora.... ¡un logo genial!
Versionado instantáneo de activos
Para ver lo realmente genial, inspecciona la imagen y fíjate en el nombre del archivo. Es/assets/images/logo-
y luego este largo hash. Este hash procede del contenido del archivo. Si actualizáramos logo.png
, se generaría automáticamente un nuevo hash. Y eso es superimportante por dos razones, relacionadas entre sí. Primero, porque cuando despleguemos, el nuevo nombre de archivo reventará la caché del navegador de nuestros usuarios para que vean el nuevo archivo inmediatamente. Y en segundo lugar, gracias a esto, podemos configurar nuestro servidor web de producción para que sirva todos los activos con cabeceras de Expiración de larga duración, lo que maximiza el almacenamiento en caché y el rendimiento.
Servir activos en desarrollo frente a producción
Ahora, en el entorno dev
, no existe un archivo físico con este nombre de archivo, sino que la petición de este activo se procesa a través de Symfony y es interceptada por un receptor del núcleo. Ese listener mira la URL, encuentra el logo.png
correspondiente dentro del directorio assets/images/
y lo devuelve.
Pero en producción, eso no es lo suficientemente rápido. Así que, al desplegar, se ejecuta:
php bin/console asset-map:compile
Muy sencillo: esto escribe todos los archivos en el directorio public/assets/
. Mira: ¡en public/assets/
, ahora tenemos archivos reales, físicos! Así que cuando voy y actualizo, este archivo no está siendo procesado por Symfony, está cargando uno de esos archivos reales.
Ahora bien, si alguna vez ejecutas este comando localmente, asegúrate de borrar ese directorio después... para que deje de utilizar las versiones compiladas:
rm -rf public/assets/
¡Vaya! ¡El día 2 ya está hecho! Ahora tenemos una forma de servir imágenes, CSS o cualquier archivo públicamente con versionado automático de archivos. La segunda parte de AssetMapper
trata sobre los módulos JavaScript. Y ese será el tema de mañana.
13 Comments
Hey @Johann!
For example this beautyfull Space Inviters Logo img-tag. If i hover over {{ asset('images/logo.png') }} in my twig template and everywhere, Phpstorm just tells me "Missing asset".
💯 me too. I believe this is something that will need to be updated with the Symfony + PhpStorm plugin. It looks like there's an issue about it - https://github.com/Haehnchen/idea-php-symfony2-plugin/issues/2236 and the author has been pretty responsive and supportive for AssetMapper support. So hopefully it can be added :).
Cheers!
Hi !
I find Asset mapper really easy to use compared to webpack but I have one problem, how can I import a private repository ? I'm using Tiptap editor with my app and I want to import some pro extensions. But I cannot find anything in the asset mapper doc about importing from private repository protected with a private token (via .npmrc file) as explained the tip tap documentation.
Is there a proper way to do it ?
Also, I was wondering why asset mapper is sometimes not requiring all the files of the package, for example I required katex and it only added a main js file, not the folders containing css and others js files I need (/contribs for exemple). I required them easily by specifying paths in the importmap command. Why with some packages it gets all the files and others only one ? Is there a mistake in my way of importing packages or understanding it at least ? Or si it something related to the package configuration ?
Thank you very much again for all the awesome and affordable courses !
I also ran into an issue in dev where assets were returning a 404 due to nginx config.
The offender was
location ~* \.(js|css|png|jpg|jpeg|gif|webp|ico|eot|svg|ttf|woff)$ {
expires 1y;
}
A useful config in production, but in dev, it means assets are served directly, bypassing symfony's listener to rewrite the path.
Hey @Nicolas-S
Good catch, yes, that causes problems with the dev environment. From my point of view, it will be good to add some check for static file exist, and if it does not exist, then pass it to the listener.
Cheers!
I'm not sure what's going on but after running composer require symfony/asset, my browser is getting 404 for all assets. I can run asset-map:compile and then the assets load just fine.
At first I thought this meant I had APP_ENV set to prod, but that's not it. I have confirmed that it is set to dev.
I did set up a docker container to run this project instead of using symfony serve. Could that be a factor in this?
Hey @kinadian!
I might know what's going on :). If you open a 404 URL in your browser, what do you see? Is it a Symfony 404? Or a generic 404 from your web server? The key to loading assets in dev is that the asset URLs need to be processed through Symfony. In other words, when a request is made to /assets/app-abcd123.js
, that request needs to be processed by Symfony. Sometimes a web server will, by default, see the .js
and only look for that physical file (then trigger a 404 if it's not found). If I'm correct, check the rewrite rules on your web server. This won't be an issue on production, as you've seen, but you'll definitely want to get this working locally.
Cheers!
Hi @weaverryan!
Thank you. I asked a colleague to help. We ended up getting it fixed by installing symfony/apache-pack. This added an .htaccess file which changes apache's behaviour to let the request get processed by Symfony instead of returning a 404.
You were right, the 404 was a generic one from apache, not the Symfony 404 page.
Nice work! If you're using Apache, that is 100% the correct thing to do. I'm happy you got it sorted. Now, onward :)
With asset-mapper v.6.4 you may expect to not see the correct background color (i.e. skyblue).
In this case: try to remove comments in app.js (yes... the comments), remove public/asset directory and relaunch symfony serve command.
Thanks Ryan!
Thanks for sharing this! There was a but introduced in some version of AssetMapper related to the comment. I believe that should be fixed in 6.4.4 and 7.0.4, which will release very shortly after this comment.
Cheers!
Hey @weaverryan
The Asset Mapper looks really cool and I'm almost convinced to use it instead of Webpack Encore. The only thing that's holding me back, is that I do not see any examples or documentation on how to add integrity hashes for styles/scripts. Is this possible with the Asset Mapper?
Regards,
YT
Hey @Senet!
Ha! I like the challenge - let's see if we can get you the rest of the way there :).
The only thing that's holding me back, is that I do not see any examples or documentation on how to add integrity hashes for styles/scripts. Is this possible with the Asset Mapper?
You're right to catch this. It is not yet implemented - we did a LOT for 6.4 (and this was on my list), but it didn't quite happen. It became less of a priority because AssetMapper 6.4 (unlike 6.3) doesn't rely on serving content from CDNs. However, I recognize that some people may still want integrity hashes even if their assets are being served from the same hostname or perhaps if you use AssetMapper but still offload the serving of the files to your own CDN (am I listing one of your use-cases accurately)?
So right now, there is no hook in AssetMapper to add those, though it should be super easy to add. AssetMapper already knows the content of each asset and is responsible for rendering the script and link tags... so I can't really see a problem. However (and I'm not an expert at all on this topic), while we an add an integrity hash to any link or script tags on the page, if app.js
has import './foo.js'
, there is no mechanism currently to enforce an integrity hash on foo.js. You can read some discussion about it here - https://github.com/WICG/import-maps/issues/221. But even in that discussion, people are mainly talking about the importance of this when referencing assets on CDNs... and AssetMapper doesn't refer to CDN URLs. So, overall, I'm not sure HOW needed integrity hashes are... but I recognize that people (beyond you) will likely ask about this also.
Cheers!
"Houston: no signs of life"
Start the conversation!
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": ">=8.2",
"ext-ctype": "*",
"ext-iconv": "*",
"babdev/pagerfanta-bundle": "4.x-dev", // 4.x-dev
"doctrine/doctrine-bundle": "^2.10", // 2.12.x-dev
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.4.x-dev
"doctrine/orm": "^2.16", // 2.18.x-dev
"knplabs/knp-time-bundle": "dev-main", // dev-main
"pagerfanta/doctrine-orm-adapter": "4.x-dev", // 4.x-dev
"pagerfanta/twig": "4.x-dev", // 4.x-dev
"symfony/asset": "6.4.*", // 6.4.x-dev
"symfony/asset-mapper": "6.4.*", // 6.4.x-dev
"symfony/console": "6.4.x-dev", // 6.4.x-dev
"symfony/dotenv": "6.4.x-dev", // 6.4.x-dev
"symfony/flex": "^2", // 2.x-dev
"symfony/form": "6.4.x-dev", // 6.4.x-dev
"symfony/framework-bundle": "6.4.x-dev", // 6.4.x-dev
"symfony/monolog-bundle": "^3.0", // dev-master
"symfony/runtime": "6.4.x-dev", // 6.4.x-dev
"symfony/security-csrf": "6.4.x-dev", // 6.4.x-dev
"symfony/stimulus-bundle": "2.x-dev", // 2.x-dev
"symfony/twig-bundle": "6.4.x-dev", // 6.4.x-dev
"symfony/ux-autocomplete": "2.x-dev", // 2.x-dev
"symfony/ux-live-component": "2.x-dev", // 2.x-dev
"symfony/ux-turbo": "2.x-dev", // 2.x-dev
"symfony/ux-twig-component": "2.x-dev", // 2.x-dev
"symfony/validator": "6.4.x-dev", // 6.4.x-dev
"symfony/web-link": "6.4.*", // 6.4.x-dev
"symfony/yaml": "6.4.x-dev", // 6.4.x-dev
"symfonycasts/dynamic-forms": "dev-main", // dev-main
"symfonycasts/tailwind-bundle": "dev-main", // dev-main
"tales-from-a-dev/flowbite-bundle": "dev-main", // dev-main
"twig/extra-bundle": "^2.12|^3.0", // 3.x-dev
"twig/twig": "^2.12|^3.0" // 3.x-dev
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.6.x-dev
"phpunit/phpunit": "^9.5", // 9.6.x-dev
"symfony/browser-kit": "6.4.*", // 6.4.x-dev
"symfony/css-selector": "6.4.*", // 6.4.x-dev
"symfony/debug-bundle": "6.4.x-dev", // 6.4.x-dev
"symfony/maker-bundle": "^1.51", // dev-main
"symfony/panther": "^2.1", // v2.1.1
"symfony/phpunit-bridge": "7.1.x-dev", // 7.1.x-dev
"symfony/stopwatch": "6.4.x-dev", // 6.4.x-dev
"symfony/web-profiler-bundle": "6.4.x-dev", // 6.4.x-dev
"zenstruck/browser": "1.x-dev", // 1.x-dev
"zenstruck/foundry": "^1.36" // 1.x-dev
}
}
Good morning all,
because i really love asset mapper, i played around with it the last weeks and i hoped to get a solution for a little issue in my IDE with this LAST Stack.
I use PhpStorm, latest version but i never get autosuggestions/autocompletion for assets. For example this beautyfull Space Inviters Logo img-tag. If i hover over {{ asset('images/logo.png') }} in my twig template and everywhere, Phpstorm just tells me "Missing asset".
How can i fix this?
JD