8000 [AssetMapper] Put importmap in polyfill so it can be hosted locally easily by weaverryan · Pull Request #51828 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[AssetMapper] Put importmap in polyfill so it can be hosted locally easily #51828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ CHANGELOG
* Deprecate the `framework.asset_mapper.provider` config option
* Add `--exclude` option to the `cache:pool:clear` command
* Add parameters deprecations to the output of `debug:container` command
* Change `framework.asset_mapper.importmap_polyfill` from a URL to the name of an item in the importmap

6.3
---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -924,8 +924,8 @@ private function addAssetMapperSection(ArrayNodeDefinition $rootNode, callable $
->defaultValue('%kernel.project_dir%/importmap.php')
->end()
->scalarNode('importmap_polyfill')
->info('URL of the ES Module Polyfill to use, false to disable. Defaults to using a CDN URL.')
->defaultValue(null)
->info('The importmap name that will be used to load the polyfill. Set to false to disable.')
->defaultValue('es-module-shims')
->end()
->arrayNode('importmap_script_attributes')
->info('Key-value pair of attributes to add to script tags output for the importmap.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
use Symfony\Component\Asset\PackageInterface;
use Symfony\Component\AssetMapper\AssetMapper;
use Symfony\Component\AssetMapper\Compiler\AssetCompilerInterface;
use Symfony\Component\AssetMapper\ImportMap\ImportMapManager;
use Symfony\Component\BrowserKit\AbstractBrowser;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
Expand Down Expand Up @@ -1378,7 +1377,7 @@ private function registerAssetMapperConfiguration(array $config, ContainerBuilde

$container
->getDefinition('asset_mapper.importmap.renderer')
->replaceArgument(3, $config['importmap_polyfill'] ?? ImportMapManager::POLYFILL_URL)
->replaceArgument(3, $config['importmap_polyfill'])
->replaceArgument(4, $config['importmap_script_attributes'])
;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public function testAssetMapperCanBeEnabled()
'missing_import_mode' => 'warn',
'extensions' => [],
'importmap_path' => '%kernel.project_dir%/importmap.php',
'importmap_polyfill' => null,
'importmap_polyfill' => 'es-module-shims',
'vendor_dir' => '%kernel.project_dir%/assets/vendor',
'importmap_script_attributes' => [],
];
Expand Down Expand Up @@ -668,7 +668,7 @@ protected static function getBundleDefaultConfig()
'missing_import_mode' => 'warn',
'extensions' => [],
'importmap_path' => '%kernel.project_dir%/importmap.php',
'importmap_polyfill' => null,
'importmap_polyfill' => 'es-module-shims',
'vendor_dir' => '%kernel.project_dir%/assets/vendor',
'importmap_script_attributes' => [],
],
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/AssetMapper/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ CHANGELOG
* Allow specifying packages to update for the `importmap:update` command
* Add a `importmap:audit` command to check for security vulnerability advisories in dependencies
* Add a `importmap:outdated` command to check for outdated packages
* Change the polyfill used for the importmap renderer from a URL to an entry in the importmap

6.3
---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
*/
class ImportMapManager
{
public const POLYFILL_URL = 'https://ga.jspm.io/npm:es-module-shims@1.7.2/dist/es-module-shims.js';
public const IMPORT_MAP_CACHE_FILENAME = 'importmap.json';
public const ENTRYPOINT_CACHE_FILENAME_PATTERN = 'entrypoint.%s.json';

Expand Down
24 changes: 21 additions & 3 deletions src/Symfony/Component/AssetMapper/ImportMap/ImportMapRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
*/
class ImportMapRenderer
{
private const DEFAULT_ES_MODULE_SHIMS_POLYFILL_URL = 'https://ga.jspm.io/npm:es-module-shims@1.8.0/dist/es-module-shims.js';

public function __construct(
private readonly ImportMapManager $importMapManager,
private readonly ?Packages $assetPackages = null,
private readonly string $charset = 'UTF-8',
private readonly string|false $polyfillUrl = ImportMapManager::POLYFILL_URL,
private readonly string|false $polyfillImportName = false,
private readonly array $scriptAttributes = [],
private readonly ?RequestStack $requestStack = null,
) {
Expand All @@ -45,6 +47,7 @@ public function render(string|array $entryPoint, array $attributes = []): string
$importMap = [];
$modulePreloads = [];
$cssLinks = [];
$polyFillPath = null;
foreach ($importMapData as $importName => $data) {
$path = $data['path'];

Expand All @@ -53,6 +56,12 @@ public function render(string|array $entryPoint, array $attributes = []): string
$path = $this->assetPackages->getUrl(ltrim($path, '/'));
}

// if this represents the polyfill, hide it from the import map
if ($importName === $this->polyfillImportName) {
$polyFillPath = $path;
continue;
}

$preload = $data['preload'] ?? false;
if ('css' !== $data['type']) {
$importMap[$importName] = $path;
Expand Down Expand Up @@ -87,8 +96,17 @@ public function render(string|array $entryPoint, array $attributes = []): string
</script>
HTML;

if ($this->polyfillUrl) {
$url = $this->escapeAttributeValue($this->polyfillUrl);
if (false !== $this->polyfillImportName && null === $polyFillPath) {
if ('es-module-shims' !== $this->polyfillImportName) {
throw new \InvalidArgumentException(sprintf('The JavaScript module polyfill was not found in your import map. Either disable the polyfill or run "php bin/console importmap:require "%s"" to install it.', $this->polyfillImportName));
}

// a fallback for the default polyfill in case it's not in the importmap
$polyFillPath = self::DEFAULT_ES_MODULE_SHIMS_POLYFILL_URL;
}

if ($polyFillPath) {
$url = $this->escapeAttributeValue($polyFillPath);

$output .= <<<HTML

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public function testBasicRender()
'path' => 'https://cdn.example.com/assets/remote-d1g35t.js',
'type' => 'js',
],
'es-module-shim' => [
'path' => 'https://ga.jspm.io/npm:es-module-shims',
'type' => 'js',
],
]);

$assetPackages = $this->createMock(Packages::class);
Expand All @@ -64,11 +68,14 @@ public function testBasicRender()
return '/subdirectory/'.$path;
});

$renderer = new ImportMapRenderer($importMapManager, $assetPackages);
$renderer = new ImportMapRenderer($importMapManager, $assetPackages, polyfillImportName: 'es-module-shim');
$html = $renderer->render(['app']);

$this->assertStringContainsString('<script type="importmap">', $html);
$this->assertStringContainsString('https://ga.jspm.io/npm:es-module-shims', $html);
// polyfill is rendered as a normal script tag
$this->assertStringContainsString('<script async src="https://ga.jspm.io/npm:es-module-shims"></script>', $html);
// and is hidden from the import map
$this->assertStringNotContainsString('"es-module-shim"', $html);
$this->assertStringContainsString('import \'app\';', $html);

// preloaded js file
Expand All @@ -93,9 +100,26 @@ public function testNoPolyfill()
$this->assertStringNotContainsString('https://ga.jspm.io/npm:es-module-shims', $renderer->render([]));
}

public function testDefaultPolyfillUsedIfNotInImportmap()
{
$importMapManager = $this->createMock(ImportMapManager::class);
$importMapManager->expects($this->once())
->method('getImportMapData')
->with(['app'])
->willReturn([]);

$renderer = new ImportMapRenderer(
$importMapManager,
$this->createMock(Packages::class),
polyfillImportName: 'es-module-shims',
);
$html = $renderer->render(['app']);
$this->assertStringContainsString('<script async src="https://ga.jspm.io/npm:es-module-shims@', $html);
}

public function testCustomScriptAttributes()
{
$renderer = new ImportMapRenderer($this->createBasicImportMapManager(), null, 'UTF-8', 'https://polyfillUrl.example', [
$renderer = new ImportMapRenderer($this->createBasicImportMapManager(), null, 'UTF-8', 'es-module-shims', [
'something' => true,
'data-turbo-track' => 'reload',
]);
Expand Down Expand Up @@ -128,6 +152,10 @@ private function createBasicImportMapManager(): ImportMapManager
'path' => 'app.js',
'type' => 'js',
],
'es-module-shims' => [
'path' => 'https://polyfillUrl.example',
'type' => 'js',
],
])
;

Expand Down
0