If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeSometimes things won't work. But, with AssetMapper, there are some telltale signs when things go wrong. Let's see a few of the most common ways that things can... get weird.
One of the fastest ways to mess things up is in /templates/vinyl/homepage.html.twig
: use the asset()
function and pass an invalid path. Remember, in assets/images/
, we have penguin.png
. So, images/penguin.png
is its "logical path" in AssetMapper. Let's say images/
, but then duck.png
.
... lines 1 - 4 | |
{% block body %} | |
<div class="px-4"> | |
... lines 7 - 8 | |
<img src="{{ asset('images/duck.png') }}"> | |
... lines 10 - 34 | |
</div> | |
{% endblock %} |
This is obviously not the right path... or even the right animal. So no surprise that, on the homepage, we get a 404. The key thing about this 404, if we look at the console, is its suspicious-looking path. Look closely: there's no version in the filename! This tells us that this path was not found in any of the AssetMapper directories: it's an invalid logical path. And so, AssetMapper ignored it and returned the raw, unversioned filename.
To help visualize the valid logical paths, remember that you can run:
php bin/console debug:asset
Up here, this is everything that you're allowed to pass to the asset()
function. And there's images/penguin.png
. If we put images/penguin.png
here instead... now it works.
... lines 1 - 4 | |
{% block body %} | |
<div class="px-4"> | |
... lines 7 - 8 | |
<img src="{{ asset('images/penguin.png') }}"> | |
... lines 10 - 34 | |
</div> | |
{% endblock %} |
The key thing to look for is the version hash in the filename. If it's not there, AssetMapper couldn't find your path.
Another common mistake is to mess up an import. Like... maybe in styles/app.css
, we mistype a part of this image url()
. Or, in app.js
, when importing vinyl.js
, we forget the .js
at the end.
... line 1 | |
import Vinyl from './lib/vinyl'; | |
... lines 3 - 7 |
Accidents like this give us the same result as the first mistake! When we refresh, we get a 404. You can see that here. But again, the key thing is the missing version hash. That's a sign that the path couldn't be found, so it couldn't be handled by AssetMapper.
In this case, the invalid path lives in app.js
. When we're inside a template and use the asset()
function, we pass the logical path to a file. But if we're inside of app.js
or app.css
, instead of the logical path, we use the relative path. This is by design. We get to code inside of these files as if AssetMapper doesn't exist. We don't need to think about logical paths, we just think:
What relative path would I use if these files were all just being served directly to my browser?
Anyway, if the version hash is missing, we have an invalid path, which could be an invalid logical path in a template or an invalid relative path in some import somewhere.
By the way, there's an almost hidden way to see if any invalid imports appear anywhere in your code. First, run:
php bin/console cache:clear
That clears Symfony's cache, of course, but it also clears an internal cache in AssetMapper. Now when we run
php bin/console debug:asset
it re-builds the cache for all of those assets internally. When it does that, it parses our files and reports any missing imports. See?
WARNING Unable to find asset
./lib/vinyl
imported fromassets/app.js
.
And in this case, we even get an extra message:
Try adding ".js" to the end of the import
Good idea. If we add that .js
back... things work again.
The last common way to mess things up is to use a bare import - an import that doesn't start with ./
or ../
- for something that does not appear in your importmap
. Here, the intention is to use the bootstrap
library... but we don't have it in our importmap
. The exact error will vary based on your browser, but for me it says:
Failed to resolve module specifier "bootstrap". Relative references must start with either "/", "./", or "../".
Translation:
Hey! If you're trying to refer to a relative path, you forgot the
./
or../
part, you goofball! But if you're trying to import a package, you forgot to add it to your importmap!
The solution is usually to run: php bin/console importmap:require
to add that package.
Next up: what if you have a bunch of CSS or JavaScript that you only want to load on a single page or section of your site - like an admin section? How can we organize things so that we don't have to load all of that code on every page?
"Houston: no signs of life"
Start the conversation!
// 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
}
}