AssetMapper lets you use modern JavaScript and CSS without a build step, relying on native browser features like import maps. Symfony 8.2 improves it in several areas: security of third-party packages, control over what the import map exposes, and a smoother development experience.
Subresource Integrity for Import Maps
Subresource Integrity (SRI) lets browsers check that the files they download haven't been tampered with, by comparing them with a cryptographic hash that you provide. Symfony 8.2 adds a new option to generate these hashes for the resources of your import map:
1 2 3 4
# config/packages/asset_mapper.yaml
framework:
asset_mapper:
importmap_integrity_algorithms: ['sha384']
The supported algorithms are sha256, sha384 and sha512. When this
option is enabled, the importmap() Twig function adds the integrity key
to the rendered import map and the integrity attribute to the
modulepreload and stylesheet links:
1 2
<link rel="stylesheet" href="/assets/styles/app-1b4f0a2c.css" integrity="sha384-...">
<link rel="modulepreload" href="/assets/app-3e8b5c1d.js" integrity="sha384-...">
Minimum Release Age for Package Updates
Supply chain attacks usually target freshly published package versions. If you wait a few days before installing a new version, a compromised release has time to be detected and removed. Tools like npm, pnpm and yarn already provide this feature, and Symfony 8.2 adds it to AssetMapper:
1 2 3 4 5
# config/packages/asset_mapper.yaml
framework:
asset_mapper:
# in seconds (7 days); the default value (0) disables this check
minimum_release_age: 604800
With this option, the importmap:update command ignores the versions that are
newer than the given age (and also prerelease versions and the ones above the
latest tag). The importmap:outdated command shows the versions held back
in a new Withheld column:
1 2 3 4 5 6 7
$ php bin/console importmap:outdated
----------- --------- -------- ----------
Package Current Latest Withheld
----------- --------- -------- ----------
bootstrap 5.3.1 5.3.2 5.3.3
----------- --------- -------- ----------
This check doesn't apply to importmap:require, so you can still install a
recent version when you need an urgent upgrade. Keep in mind that, to know when
each version was published, update checks now download the full npm metadata of
each package, which is much larger than the abbreviated one used by default.
Requiring Raw ESM Packages
When you require a third-party package, AssetMapper downloads the ESM build that
jsDelivr generates for it. Sometimes this generated build is broken, so Symfony
8.2 adds a --no-esm option to download the file published by the package
as-is:
1
$ php bin/console importmap:require "fullcalendar/index.global.js=fullcalendar" --no-esm
This adds an esm key to the package entry in importmap.php:
1 2 3 4 5 6 7 8 9
// importmap.php
return [
// ...
'fullcalendar' => [
'version' => '7.0.0',
'package_specifier' => 'fullcalendar/index.global.js',
'esm' => false,
],
];
When using this option, you must pass the path of the file inside the package.
AssetMapper also downloads the files imported with relative paths (e.g.
import './chunk/calendar.js') and adds them to the import map. However, bare
imports such as import { h } from 'preact' are not resolved, so you must
require those packages yourself.
Ignoring Compiled Assets in Debug Mode
In production, AssetMapper reads the metadata files generated by the
asset-map:compile command. If you ran that command on your local machine,
the development environment also used those files, so your changes to the
source assets were ignored until you removed the public/assets/ directory.
In Symfony 8.2, AssetMapper ignores the compiled metadata when the debug mode
is enabled, so assets are always resolved from their source files in your
development environment. The asset-map:compile command also displays a note
to remind you about this behavior when you run it in debug mode.
Rendering Only the Reachable Import Map Entries
The importmap() Twig function renders all the entries of importmap.php.
In applications with several entrypoints, this means that a public page (e.g.
the login page) reveals the entrypoints of other sections (e.g. the admin
backend) and their dependencies.
Symfony 8.2 adds an option to only render the entries reachable from the entrypoints of the page:
1 2 3 4 5
# config/packages/asset_mapper.yaml
framework:
asset_mapper:
# the default value is 'all'
importmap_entries: reachable
The reachable entries include both static and dynamic imports, so lazy Stimulus
controllers keep working. The only exception is dynamic imports whose
specifier is a variable (e.g. import(someVariable)), which can't be traced.
That's why this option is disabled by default.
Configurable Metadata Directory
The asset-map:compile command generates the manifest.json,
importmap.json and entrypoint.*.json files in the public assets
directory. They are only read by PHP, but they are publicly accessible because
of their location. Symfony 8.2 adds an option to store them in any other
directory:
1 2 3 4
# config/packages/asset_mapper.yaml
framework:
asset_mapper:
metadata_dir: '%kernel.project_dir%/var/assets'
The default value of this option doesn't change, so these files stay in the public assets directory unless you configure it.