Skip to content

Commit

Permalink
feat: only load CSS when mdx is rendered!
Browse files Browse the repository at this point in the history
  • Loading branch information
bholmesdev committed Nov 3, 2022
1 parent a9af735 commit 9fc5311
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 17 deletions.
4 changes: 3 additions & 1 deletion packages/astro/src/core/build/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { resolvedPagesVirtualModuleId } from '../app/index.js';
export function* walkParentInfos(
id: string,
ctx: { getModuleInfo: GetModuleInfo },
until?: (importer: string) => boolean,
depth = 0,
seen = new Set<string>(),
childId = ''
Expand All @@ -16,12 +17,13 @@ export function* walkParentInfos(
let order = childId ? info.importedIds.indexOf(childId) : 0;
yield [info, depth, order];
}
if (until?.(id)) return;
const importers = (info?.importers || []).concat(info?.dynamicImporters || []);
for (const imp of importers) {
if (seen.has(imp)) {
continue;
}
yield* walkParentInfos(imp, ctx, ++depth, seen, id);
yield* walkParentInfos(imp, ctx, until, ++depth, seen, id);
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/core/build/static-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { emptyDir, removeDir } from '../../core/fs/index.js';
import { prependForwardSlash } from '../../core/path.js';
import { isModeServerWithNoAdapter } from '../../core/util.js';
import { runHookBuildSetup } from '../../integrations/index.js';
import { assetSsrPlugin } from '../../vite-plugin-asset-ssr/index.js';
import { PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
import { info } from '../logger/core.js';
import { getOutDirWithinCwd } from './common.js';
Expand Down Expand Up @@ -151,6 +152,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
target: 'server',
}),
...(viteConfig.plugins || []),
assetSsrPlugin({ internals }),
// SSR needs to be last
settings.config.output === 'server' && vitePluginSSR(internals, settings.adapter!),
vitePluginAnalyzer(internals),
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/core/build/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface PageBuildData {
route: RouteData;
moduleSpecifier: string;
css: Map<string, { depth: number; order: number }>;
delayedCss?: Set<string>;
hoistedScript: { type: 'inline' | 'external'; value: string } | undefined;
}
export type AllPagesData = Record<ComponentPath, PageBuildData>;
Expand Down
43 changes: 28 additions & 15 deletions packages/astro/src/core/build/vite-plugin-css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
getPageDatasByHoistedScriptId,
isHoistedScript,
} from './internal.js';
import { FLAG } from '../../vite-plugin-asset-ssr/index.js';
import { DELAYED_ASSET_FLAG } from '../../vite-plugin-asset-ssr/index.js';

interface PluginOptions {
internals: BuildInternals;
Expand Down Expand Up @@ -113,25 +113,15 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]
}
};

let exclude: Set<string> = new Set();
for (const [_, chunk] of Object.entries(bundle)) {
if (chunk.type === 'chunk' && chunk.facadeModuleId?.includes(FLAG)) {
exclude.add(chunk.fileName);
for (const imp of chunk.imports) {
exclude.add(imp);
}
}
}

for (const [_, chunk] of Object.entries(bundle)) {
if (chunk.type === 'chunk') {
const c = chunk;

if ('viteMetadata' in chunk && !exclude.has((chunk as OutputChunk).fileName)) {
if ('viteMetadata' in chunk) {
const meta = chunk['viteMetadata'] as ViteMetadata;

// Chunks that have the viteMetadata.importedCss are CSS chunks
if (meta.importedCss.size && !(chunk as OutputChunk).facadeModuleId?.endsWith(FLAG)) {
if (meta.importedCss.size) {
// In the SSR build, keep track of all CSS chunks' modules as the client build may
// duplicate them, e.g. for `client:load` components that render in SSR and client
// for hydation.
Expand Down Expand Up @@ -167,8 +157,31 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]

// For this CSS chunk, walk parents until you find a page. Add the CSS to that page.
for (const id of Object.keys(c.modules)) {
for (const [pageInfo, depth, order] of walkParentInfos(id, this)) {
if (moduleIsTopLevelPage(pageInfo)) {
for (const [pageInfo, depth, order] of walkParentInfos(
id,
this,
function until(importer) {
return importer.endsWith(DELAYED_ASSET_FLAG);
}
)) {
if (pageInfo.id.endsWith(DELAYED_ASSET_FLAG)) {
for (const parent of walkParentInfos(id, this)) {
console.log('walking parent...');
const parentInfo = parent[0];
if (moduleIsTopLevelPage(parentInfo)) {
const pageViteID = parentInfo.id;
const pageData = getPageDataByViteID(internals, pageViteID);
if (pageData) {
if (!pageData.delayedCss) {
pageData.delayedCss = new Set();
}
for (const css of meta.importedCss) {
pageData.delayedCss.add(css);
}
}
}
}
} else if (moduleIsTopLevelPage(pageInfo)) {
const pageViteID = pageInfo.id;
const pageData = getPageDataByViteID(internals, pageViteID);
if (pageData) {
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/core/create-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import astroScriptsPageSSRPlugin from '../vite-plugin-scripts/page-ssr.js';
import { createCustomViteLogger } from './errors/dev/index.js';
import { resolveDependency } from './util.js';
import { astroContentPlugin } from '../content/vite-plugin.js';
import { injectDelayedAssetPlugin } from '../vite-plugin-asset-ssr/index.js';

interface CreateViteOptions {
settings: AstroSettings;
Expand Down Expand Up @@ -113,6 +114,7 @@ export async function createVite(
astroScriptsPageSSRPlugin({ settings }),
astroLoadFallbackPlugin({ fs }),
astroContentPlugin({ settings, logging }),
injectDelayedAssetPlugin(),
],
publicDir: fileURLToPath(settings.config.publicDir),
root: fileURLToPath(settings.config.root),
Expand Down
50 changes: 49 additions & 1 deletion packages/astro/src/vite-plugin-asset-ssr/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,49 @@
export const FLAG = '?astro-asset-ssr';
import { Plugin } from 'vite';
import { moduleIsTopLevelPage, walkParentInfos } from '../core/build/graph.js';
import { BuildInternals, getPageDataByViteID } from '../core/build/internal.js';

const assetPlaceholder = `'@@ASTRO-ASSET-PLACEHOLDER@@'`;

export const DELAYED_ASSET_FLAG = '?astro-asset-ssr';

export function injectDelayedAssetPlugin(): Plugin {
return {
name: 'astro-inject-delayed-asset-plugin',
enforce: 'post',
load(id) {
if (id.endsWith(DELAYED_ASSET_FLAG)) {
const code = `
export { Content } from ${JSON.stringify(id.replace(DELAYED_ASSET_FLAG, ''))};
export const collectedCss = ${assetPlaceholder}
`;
return code;
}
},
};
}

export function assetSsrPlugin({ internals }: { internals: BuildInternals }): Plugin {
return {
name: 'astro-asset-ssr-plugin',
async generateBundle(_options, bundle) {
for (const [_, chunk] of Object.entries(bundle)) {
if (chunk.type === 'chunk' && chunk.code.includes(assetPlaceholder)) {
for (const id of Object.keys(chunk.modules)) {
for (const [pageInfo, depth, order] of walkParentInfos(id, this)) {
if (moduleIsTopLevelPage(pageInfo)) {
const pageViteID = pageInfo.id;
const pageData = getPageDataByViteID(internals, pageViteID);
if (pageData) {
chunk.code = chunk.code.replace(
assetPlaceholder,
JSON.stringify([...(pageData.delayedCss ?? [])])
);
}
}
}
}
}
}
},
};
}

0 comments on commit 9fc5311

Please sign in to comment.