Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[AssetMapper] Add support for CSS files in the importmap#51543
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
[AssetMapper] Add support for CSS files in the importmap#51543
Uh oh!
There was an error while loading.Please reload this page.
Conversation
90f4bb3 to7b3f810CompareUh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
fa22633 to5ef0727CompareUh oh!
There was an error while loading.Please reload this page.
nicolas-grekas left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I played with this, it just works :)
When using--download, this will break assets referenced byurl() /@import (exceptdata: ones of course). To fix this, we'd need to parse those and fetch them, recursively.
Also I'm wondering: currently, the importmap recipe adds a link tag. Could we leverage this new feat to not do this in the recipe anymore? Would be nice :)
src/Symfony/Component/AssetMapper/Tests/ImportMap/Resolver/JsDelivrEsmResolverTest.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
weaverryan commentedSep 14, 2023
I'll check into that - we already do something similar for CSS.
Right now, I believe that |
stof commentedSep 14, 2023
Please don't. |
weaverryan commentedSep 15, 2023
That's 100% true. But it's also massively user-friendly. To be precise, there are 2 different sides to this: A) The ability to have B) The ability to If/when web standards catch up, we can migrate to whatever that standard is. As a compromise, we could put |
stof commentedSep 15, 2023
Having the JS being the trigger to load the CSS is very bad from a performance point of view: the CSS must be render-blocking while the recommended setup is to run the JS code as |
weaverryan commentedSep 15, 2023
You're totally right. Fortunately, that behavior will only be for non-preloaded CSS. The basic idea is:
Btw, a CSS file can be |
c0618cf toba79d06Compareweaverryan commentedSep 18, 2023
I need to fix a few tests, but PR is ready for review & description has been updated. This is now a robust system for handling CSS and it's fun to use :). |
84d94ae to3e10302Compareweaverryan commentedSep 23, 2023
Test failures are unrelated or expected (due to the high deps grabbing 7.0 code that doesn't contain the code from the PR). This is ready for review! You can see some example usage athttps://github.com/weaverryan/ux/tree/assetmapper-css/ux.symfony.com |
724ba05 to467dea6Compareweaverryan commentedSep 27, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
|
467dea6 to2020644Compareweaverryan commentedSep 28, 2023
Found / fixed a problem with cascading the preload into "remote" importmap entries. This is ready again. |
a3d7e1c toe236cbaCompare93a92eb to9a00f0eCompare
nicolas-grekas left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
LGTM, I just found minor things before approving 🙏
src/Symfony/Component/AssetMapper/Event/BeforeAssetsCompileEvent.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/AssetMapper/ImportMap/ImportMapRenderer.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/AssetMapper/ImportMap/ImportMapRenderer.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
nicolas-grekas left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
please add a line to the changelog (of the twig-bridge also I guess)
| } | ||
| publicfunctionimportmap(?string$entryPoint ='app',array$attributes = []):string | ||
| publicfunctionimportmap(string|array$entryPoint,array$attributes = []):string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
this breaks existing apps that usethe default recipe
is this desired?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Removing support for the implementapp entrypoint should go through a deprecation even if the component is experimental IMO due to this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
and probably also the support of passingnull then if we have a deprecation layer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
good catch. Check the last commit. I've leftapp as the default (in part for BC). But in the recipe, I WOULD like to start people withimportmap('app') because it's more explicit.
391e272 to5060fa1Compare
nicolas-grekas left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
(merging to unlock follow up PRs on the topic, let's iterate. Please report back if you have any concerns of course)
nicolas-grekas commentedSep 29, 2023
Thank you@weaverryan. |
…p.php (weaverryan)This PR was squashed before being merged into the 6.4 branch.Discussion----------[AssetMapper] Allow simple, relative paths in importmap.php| Q | A| ------------- | ---| Branch? | 6.4| Bug fix? | no| New feature? | yes| Deprecations? | no| Tickets | None| License | MIT| Doc PR | TODOThis PR is based on top of#51543 - so that needs to be merged first.Currently, the `path` key in `importmap.php` MUST be the logic path to an file. Especially when trying to refer to assets in a bundle, this forces us to use paths that... don't look very obvious to users - e.g.```php 'app' => [ 'path' => 'app.js', ], '`@symfony`/stimulus-bundle' => [ 'path' => '`@symfony`/stimulus-bundle/loader.js', ],```This PR adds support for relative paths (starting with `.`). This means the `importmap.php` file can look like this now:```php 'app' => [ 'path' => './assets/app.js', ], '`@symfony`/stimulus-bundle' => [ 'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js', ],```Those paths are now simple. One less thing to explain to people.Commits-------978b14d [AssetMapper] Allow simple, relative paths in importmap.php
Uh oh!
There was an error while loading.Please reload this page.
Hi!
This is the brainchild of@nicolas-grekas & I (mostly him). This PR adds 2 big user-facing features:
A) CSS Handling including ability to import CSS
The
importmap.phpnow supports a'type' => 'css':This, by itself, won't cause the CSS file to be loaded. But it WILL be added to the importmap, though the exact behavior will depend on the entrypoint (see next section).
But, in the simplest case, it will output something like this, which adds the
<link rel="stylesheet">tag to the page if this file is every imported in JSimport 'app.css'.More commonly, in the same way that AssetMapper finds relative JavaScript imports and adds them to the importmap, it also finds relative CSS imports and addsthose to the importmap. This allows you to:
import './styles/foo.css'without needing to addfoo.cssto the importmap. It "just works". This would result infoo.cssbeing added to the page via JavaScript unless it is in the import chain of an entrypoint (see next section), in which case it would be a true<link>tag.Also, you can now download CSS files via
importmap:require(or, if a package comes with a CSS file, it will be downloaded and added automatically - i.e. if the package has astylekey):# will download `bootstrap` AND `bootstrap/dist/css/bootstrap.min.css`php bin/console importmap:require bootstrapB) Auto-preload based on entrypoints
Like with Webpack, there is now a concept of "entrypoints". The ONE time you call
{{ importmap() }}on the page, you will pass the 1 or many "entrypoint" names fromimportmap.phpthat should be loaded - e.g.importmap('app')(the most common) orimportmap(['app', 'checkout']).Most simply (and this is true already in AssetMapper), this causes a
<script type="module">import 'app';</script>to be rendered into the page.But in this PR, it also has another critical role:
app.jsimportsother.jsimportsyet-another.jsimportssome_styles.css, using non-lazy imports (i.e.import './other.jsvs the lazyimport('./other.js')), thenother.js,yet-another.jsandsome_styles.cssare all returned.other.js-> preloaded (i.e.modulepreloadtag rendered)yet-another.js-> preloaded (i.e.modulepreloadtag rendered)some_styles.css"preloaded" - i.e. a ` is added to the page.The idea is that, if
app.jsis your entrypoint, thenevery non-lazy import in its import chain will need to be downloaded before the JavaScript starts executing. So all files should be preloaded. Additionally, if we find any CSS that is imported in a non-lazy way, we render those aslinktags.The
preloadoption inimportmap.phpis GONE. Preloading is controlled entirely through the entrypoint.This entrypoint logic also affects the ordering of the non-lazy CSS files (i.e. the CSS files that will be rendered as
linktags). It finds all (in order) non-lazy imported CSS files from the entrypoint and render them aslinktags in order (like Webpack).I propose the recipe starting
importmap.phpis updated to be:And then in
assets/app.js:C) Other Improvements
asset-map:compileso other processes can hook into this (will make bundles like TailwindBundle) nicer.importmap:exportcommand: I don't see a need for this//or/*TODOs