mirror of
https://github.com/withastro/astro.git
synced 2025-03-24 23:21:57 -05:00
Fix CSS handling for experimental.directRenderScript (#11026)
This commit is contained in:
parent
1e33cd85ad
commit
8dfb1a23cc
9 changed files with 101 additions and 12 deletions
5
.changeset/clever-ads-scream.md
Normal file
5
.changeset/clever-ads-scream.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"astro": patch
|
||||
---
|
||||
|
||||
Skips rendering script tags if it's inlined and empty when `experimental.directRenderScript` is enabled
|
5
.changeset/rich-melons-worry.md
Normal file
5
.changeset/rich-melons-worry.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"astro": patch
|
||||
---
|
||||
|
||||
Fixes CSS handling if imported in a script tag in an Astro file when `experimental.directRenderScript` is enabled
|
|
@ -57,6 +57,11 @@ export interface BuildInternals {
|
|||
*/
|
||||
pagesByClientOnly: Map<string, Set<PageBuildData>>;
|
||||
|
||||
/**
|
||||
* A map for page-specific information by a script in an Astro file
|
||||
*/
|
||||
pagesByScriptId: Map<string, Set<PageBuildData>>;
|
||||
|
||||
/**
|
||||
* A map of hydrated components to export names that are discovered during the SSR build.
|
||||
* These will be used as the top-level entrypoints for the client build.
|
||||
|
@ -133,6 +138,7 @@ export function createBuildInternals(): BuildInternals {
|
|||
pageOptionsByPage: new Map(),
|
||||
pagesByViteID: new Map(),
|
||||
pagesByClientOnly: new Map(),
|
||||
pagesByScriptId: new Map(),
|
||||
|
||||
propagatedStylesMap: new Map(),
|
||||
propagatedScriptsMap: new Map(),
|
||||
|
@ -181,6 +187,26 @@ export function trackClientOnlyPageDatas(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks scripts to the pages they are associated with. (experimental.directRenderScript)
|
||||
*/
|
||||
export function trackScriptPageDatas(
|
||||
internals: BuildInternals,
|
||||
pageData: PageBuildData,
|
||||
scriptIds: string[]
|
||||
) {
|
||||
for (const scriptId of scriptIds) {
|
||||
let pageDataSet: Set<PageBuildData>;
|
||||
if (internals.pagesByScriptId.has(scriptId)) {
|
||||
pageDataSet = internals.pagesByScriptId.get(scriptId)!;
|
||||
} else {
|
||||
pageDataSet = new Set<PageBuildData>();
|
||||
internals.pagesByScriptId.set(scriptId, pageDataSet);
|
||||
}
|
||||
pageDataSet.add(pageData);
|
||||
}
|
||||
}
|
||||
|
||||
export function* getPageDatasByChunk(
|
||||
internals: BuildInternals,
|
||||
chunk: Rollup.RenderedChunk
|
||||
|
|
|
@ -11,7 +11,11 @@ import {
|
|||
getTopLevelPageModuleInfos,
|
||||
moduleIsTopLevelPage,
|
||||
} from '../graph.js';
|
||||
import { getPageDataByViteID, trackClientOnlyPageDatas } from '../internal.js';
|
||||
import {
|
||||
getPageDataByViteID,
|
||||
trackClientOnlyPageDatas,
|
||||
trackScriptPageDatas,
|
||||
} from '../internal.js';
|
||||
import type { StaticBuildOptions } from '../types.js';
|
||||
|
||||
function isPropagatedAsset(id: string) {
|
||||
|
@ -171,9 +175,21 @@ export function vitePluginAnalyzer(
|
|||
// each script module is its own entrypoint, so we directly assign each script modules to
|
||||
// `discoveredScripts` here, which will eventually be passed as inputs of the client build.
|
||||
if (options.settings.config.experimental.directRenderScript && astro.scripts.length) {
|
||||
for (let i = 0; i < astro.scripts.length; i++) {
|
||||
const hid = `${id.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`;
|
||||
internals.discoveredScripts.add(hid);
|
||||
const scriptIds = astro.scripts.map(
|
||||
(_, i) => `${id.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`
|
||||
);
|
||||
|
||||
// Assign as entrypoints for the client bundle
|
||||
for (const scriptId of scriptIds) {
|
||||
internals.discoveredScripts.add(scriptId);
|
||||
}
|
||||
|
||||
// The script may import CSS, so we also have to track the pages that use this script
|
||||
for (const pageInfo of getTopLevelPageModuleInfos(id, this)) {
|
||||
const newPageData = getPageDataByViteID(internals, pageInfo.id);
|
||||
if (!newPageData) continue;
|
||||
|
||||
trackScriptPageDatas(internals, newPageData, scriptIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,12 +145,21 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
|
|||
if (pageData) {
|
||||
appendCSSToPage(pageData, meta, pagesToCss, depth, order);
|
||||
}
|
||||
} else if (
|
||||
options.target === 'client' &&
|
||||
internals.hoistedScriptIdToPagesMap.has(pageInfo.id)
|
||||
) {
|
||||
for (const pageData of getPageDatasByHoistedScriptId(internals, pageInfo.id)) {
|
||||
appendCSSToPage(pageData, meta, pagesToCss, -1, order);
|
||||
} else if (options.target === 'client') {
|
||||
// For scripts or hoisted scripts, walk parents until you find a page, and add the CSS to that page.
|
||||
if (buildOptions.settings.config.experimental.directRenderScript) {
|
||||
const pageDatas = internals.pagesByScriptId.get(pageInfo.id)!;
|
||||
if (pageDatas) {
|
||||
for (const pageData of pageDatas) {
|
||||
appendCSSToPage(pageData, meta, pagesToCss, -1, order);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (internals.hoistedScriptIdToPagesMap.has(pageInfo.id)) {
|
||||
for (const pageData of getPageDatasByHoistedScriptId(internals, pageInfo.id)) {
|
||||
appendCSSToPage(pageData, meta, pagesToCss, -1, order);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,13 @@ export async function renderScript(result: SSRResult, id: string) {
|
|||
result._metadata.renderedScripts.add(id);
|
||||
|
||||
const inlined = result.inlinedScripts.get(id);
|
||||
if (inlined) {
|
||||
return markHTMLString(`<script type="module">${inlined}</script>`);
|
||||
if (inlined != null) {
|
||||
// The inlined script may actually be empty, so skip rendering it altogether if so
|
||||
if (inlined) {
|
||||
return markHTMLString(`<script type="module">${inlined}</script>`);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
const resolved = await result.resolve(id);
|
||||
|
|
10
packages/astro/test/fixtures/hoisted-imports/src/pages/script-import-style.astro
vendored
Normal file
10
packages/astro/test/fixtures/hoisted-imports/src/pages/script-import-style.astro
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<script>
|
||||
import "../styles/script-import-style.css";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Astro</h1>
|
||||
</body>
|
||||
</html>
|
3
packages/astro/test/fixtures/hoisted-imports/src/styles/script-import-style.css
vendored
Normal file
3
packages/astro/test/fixtures/hoisted-imports/src/styles/script-import-style.css
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
h1 {
|
||||
background-color: tomato;
|
||||
}
|
|
@ -87,5 +87,15 @@ describe('Hoisted Imports', () => {
|
|||
assert.ok(scripts[0].attribs.src);
|
||||
assert.ok(scripts[1].attribs.src);
|
||||
});
|
||||
|
||||
it('renders styles if imported from the script', async () => {
|
||||
const html = await fixture.readFile('/script-import-style/index.html');
|
||||
const $ = cheerio.load(html);
|
||||
const styles = $('style');
|
||||
assert.equal(styles.length, 1);
|
||||
// There should be no script because it's empty (contains only CSS import)
|
||||
const scripts = $('scripts');
|
||||
assert.equal(scripts.length, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue