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

Ousama Ben Younes
Contributed by Ousama Ben Younes in #65078

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

Ousama Ben Younes
Contributed by Ousama Ben Younes in #65074

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

Ousama Ben Younes
Contributed by Ousama Ben Younes in #65075

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

Simon André
Contributed by Simon André in #64852

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

Pascal CESCON
Contributed by Pascal CESCON in #65622

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

Simon André
Contributed by Simon André in #65642

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.

Published in #Living on the edge