Closed mayank99 closed 6 months ago
I have a generic app that renders out couple dozen different sites using the same underlying application code, but with different styles, assets, and content needing to be loaded in for each site. This issue means I am unable to dynamically import the correct stylesheets for each site independently, resulting in having to import styles for every site (which then causes collision issues I would also need to resolve), or the current workaround I'm doing which uses a script to run separate builds for each configuration, adding in a static import of the correct CSS files before each build in order to generate a dozen or so different outputs that are virtually identical outside of the bundled CSS.
Naively, this seems like something I should be able to do without much work, akin to the way that JS modules are dynamically chunked and only loaded when the corresponding island is rendered.
Besides just complicating my build process, this massively slows down my CI/CD pipeline and incurs extra compute and storage cost, so I'd really really love to see support for this if it's possible!
Thanks for opening an issue! I'm tagging this as requires refactor
because we fully understand how limiting Astro's reliance on static analysis can be, but refactoring this part of our codebase will be a massive undertaking.
As simple as this issue seems on the surface (it does work in Vite!), Astro has a lot of custom code to handle style propagation across multiple frameworks and rendering modes. Fully supporting dynamically imported styles will require a redesign of that system.
Hi. Just want to drop in the conversation about our use case and what fixing the issue will help.
I worked on a project for migrating a Search Engine Results Page from React SPA to Astro SSR. The aim is to reduce the amount of JS needed to display something on the page. In this case, nothing at all, we just need HTML and CSS to display something - FCP (or all the thing - LCP). So we might be able to cut down LCP by half (as in about 7s down to 3.5s, tested in Lighthouse locally so YMMV). We just need to solve the very bad first-visit case. Other notes: Our SERP page handles 1 million DAU, we expect 150 RPS, and as of right now we didn't deploy the Astro version yet because of the old app's complexity and we need to make sure Astro is up to the task.
We are having a "small" issue: Our SERP doesn't always have all the >30 types of result in the same page, but it still has to import all of them via Astro.glob
so that it can render the results.
const snippetAstroFiles = await Astro.glob("./snippets/*/index.astro");
Then we filter by folder name all of the snippets for a particular query, and render them in a for
loop in the Astro template.
The problem is that all of the <script>
tags will be run, no matter if a particular snippet is rendered or not. I expect the <script>
bundles to be bundled separately so that it can be loaded conditionally, instead of being bundled with other <script>
s.
This comment in another issue is pointing out that Contents Collection is the workaround, but it's not perfect. We would have to have 1:1 MDX files and render them somehow, which is cumbersome. If static analysis is too complex, I expect a way to dynamically and lazily import modules like React's React.lazy
import.
This is also apparent in conditionally rendered Astro components, like:
{
!query && (
<Home result={homeResult || undefined} isExtension={isExtension} />
)
}
I assume that <Home>
is imported in the frontmatter, which is fine - it's nothing like React.lazy
. However there is no Astro.lazy
I think.
The reason we chose Astro SSR is because:
I'm sorry if I'm using Astro for the wrong purpose. This issue might be problematic if we have a bunch of <script>
running on each different snippet but we are not (I tried and reverted it), so there is no critical bug now. But bundles from not-rendered Astro components are still being imported and that is not ideal. Now that I've gone to another company, I will just leave the problem here so that if our SERP downloads too many unnecessary JS, we have a reference to read.
That was my experience of putting Astro up for the challenge. Mostly positive experience, so thanks Astro!
CSS in Astro (and in Vite and all other meta-frameworks) are not actually loaded by javascript. If you turn this into a non-dynamic import you will see that the CSS exists before the JavaScript is run.
This is because Astro is a SSR framework; people want their styles to be visible before the JS runs.
If you want some styles to be loaded dynamically then you should write some code to load a <link rel="stylesheet">
. Note that this will cause FOUC unless you are very careful. Good luck.
Astro Info
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
lazy loading styles using dynamic
import()
like this does not work:the styles will get loaded even before the function is called.
same scenario works correctly in vite: https://stackblitz.com/edit/vitejs-vite-u5qhnz?file=index.html,styles.css&terminal=dev
possibly related issue: https://github.com/withastro/astro/issues/6328
What's the expected result?
styles should only be imported after the code is actually called.
one important detail: in my case, the
import()
is only used in a client-side script, so astro should never inline it, only bundle it.Link to Minimal Reproducible Example
https://stackblitz.com/edit/withastro-astro-xmc34j
Participation