modulepreload

This commit is contained in:
lilnasy 2023-10-11 00:18:25 +00:00
parent a8b979ef40
commit 4eeca70fc6
No known key found for this signature in database
GPG key ID: B09B8AE8D3751F1F
7 changed files with 39 additions and 12 deletions

View file

@ -212,11 +212,11 @@ export class App {
env: this.#pipeline.env, env: this.#pipeline.env,
mod: handler as any, mod: handler as any,
}); });
} else { }
const pathname = prependForwardSlash(this.removeBase(url.pathname)); const pathname = prependForwardSlash(this.removeBase(url.pathname));
const info = this.#routeDataToRouteInfo.get(routeData)!; const info = this.#routeDataToRouteInfo.get(routeData)!;
// may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc. // may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc.
const links = new Set<never>(); const links = new Set(info.links.map(props => ({ props, children: '' })));
const styles = createStylesheetElementSet(info.styles); const styles = createStylesheetElementSet(info.styles);
let scripts = new Set<SSRElement>(); let scripts = new Set<SSRElement>();
@ -246,7 +246,6 @@ export class App {
env: this.#pipeline.env, env: this.#pipeline.env,
}); });
} }
}
/** /**
* If it is a known error code, try sending the according page (e.g. 404.astro / 500.astro). * If it is a known error code, try sending the according page (e.g. 404.astro / 500.astro).

View file

@ -16,7 +16,10 @@ export type StylesheetAsset =
export interface RouteInfo { export interface RouteInfo {
routeData: RouteData; routeData: RouteData;
file: string; file: string;
links: string[]; links: Array<{
href: string
rel: 'modulepreload'
}>;
scripts: // Integration injected scripts: // Integration injected
( (
| { children: string; stage: string } | { children: string; stage: string }

View file

@ -261,7 +261,7 @@ async function generatePage(
const pageInfo = getPageDataByComponent(pipeline.getInternals(), pageData.route.component); const pageInfo = getPageDataByComponent(pipeline.getInternals(), pageData.route.component);
// may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc. // may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc.
const linkIds: [] = []; const links = [...pageInfo?.preload.modules ?? []].map(href => ({ rel: 'modulepreload' as const, href }));
const scripts = pageInfo?.hoistedScript ?? null; const scripts = pageInfo?.hoistedScript ?? null;
const styles = pageData.styles const styles = pageData.styles
.sort(cssOrder) .sort(cssOrder)
@ -291,7 +291,7 @@ async function generatePage(
const generationOptions: Readonly<GeneratePathOptions> = { const generationOptions: Readonly<GeneratePathOptions> = {
pageData, pageData,
linkIds, links,
scripts, scripts,
styles, styles,
mod: pageModule, mod: pageModule,
@ -425,7 +425,10 @@ function getInvalidRouteSegmentError(
interface GeneratePathOptions { interface GeneratePathOptions {
pageData: PageBuildData; pageData: PageBuildData;
linkIds: string[]; links: Array<{
rel: 'modulepreload'
href: string
}>;
scripts: { type: 'inline' | 'external'; value: string } | null; scripts: { type: 'inline' | 'external'; value: string } | null;
styles: StylesheetAsset[]; styles: StylesheetAsset[];
mod: ComponentInstance; mod: ComponentInstance;
@ -490,7 +493,7 @@ function getUrlForPath(
async function generatePath(pathname: string, gopts: GeneratePathOptions, pipeline: BuildPipeline) { async function generatePath(pathname: string, gopts: GeneratePathOptions, pipeline: BuildPipeline) {
const manifest = pipeline.getManifest(); const manifest = pipeline.getManifest();
const { mod, scripts: hoistedScripts, styles: _styles, pageData } = gopts; const { mod, links: _links, scripts: hoistedScripts, styles: _styles, pageData } = gopts;
// This adds the page name to the array so it can be shown as part of stats. // This adds the page name to the array so it can be shown as part of stats.
if (pageData.route.type === 'page') { if (pageData.route.type === 'page') {
@ -500,7 +503,7 @@ async function generatePath(pathname: string, gopts: GeneratePathOptions, pipeli
pipeline.getEnvironment().logger.debug('build', `Generating: ${pathname}`); pipeline.getEnvironment().logger.debug('build', `Generating: ${pathname}`);
// may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc. // may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc.
const links = new Set<never>(); const links = new Set(_links.map(props => ({ props, children: '' })));
const scripts = createModuleScriptsSet( const scripts = createModuleScriptsSet(
hoistedScripts ? [hoistedScripts] : [], hoistedScripts ? [hoistedScripts] : [],
manifest.base, manifest.base,

View file

@ -55,6 +55,11 @@ export async function collectPagesData(
propagatedStyles: new Map(), propagatedStyles: new Map(),
propagatedScripts: new Map(), propagatedScripts: new Map(),
hoistedScript: undefined, hoistedScript: undefined,
preload: {
modules: new Set,
fonts: new Set,
styles: new Set
},
}; };
clearInterval(routeCollectionLogTimeout); clearInterval(routeCollectionLogTimeout);
@ -78,6 +83,11 @@ export async function collectPagesData(
propagatedStyles: new Map(), propagatedStyles: new Map(),
propagatedScripts: new Map(), propagatedScripts: new Map(),
hoistedScript: undefined, hoistedScript: undefined,
preload: {
modules: new Set,
fonts: new Set,
styles: new Set
},
}; };
} }

View file

@ -67,14 +67,17 @@ export function vitePluginHoistedScripts(
}); });
for (const [id, output] of considerInlining.entries()) { for (const [id, output] of considerInlining.entries()) {
const canBeInlined = const canBeInlined =
importedByOtherScripts.has(output.fileName) === false && importedByOtherScripts.has(output.fileName) === false &&
output.imports.length === 0 && output.imports.length === 0 &&
output.dynamicImports.length === 0 && output.dynamicImports.length === 0 &&
Buffer.byteLength(output.code) <= assetInlineLimit; Buffer.byteLength(output.code) <= assetInlineLimit;
let removeFromBundle = false; let removeFromBundle = false;
const facadeId = output.facadeModuleId!;
const pages = internals.hoistedScriptIdToPagesMap.get(facadeId)!; const pages = internals.hoistedScriptIdToPagesMap.get(output.facadeModuleId!)!;
for (const pathname of pages) { for (const pathname of pages) {
const vid = viteID(new URL('.' + pathname, settings.config.root)); const vid = viteID(new URL('.' + pathname, settings.config.root));
const pageInfo = getPageDataByViteID(internals, vid); const pageInfo = getPageDataByViteID(internals, vid);
@ -91,6 +94,10 @@ export function vitePluginHoistedScripts(
value: id, value: id,
}; };
} }
for (const importedScript of output.imports) {
pageInfo.preload.modules.add(importedScript)
}
} }
} }

View file

@ -210,7 +210,7 @@ function buildManifest(
} }
// may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc. // may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc.
const links: [] = []; const links = [...pageData.preload.modules].map(href => ({ rel: 'modulepreload' as const, href }));
const styles = pageData.styles const styles = pageData.styles
.sort(cssOrder) .sort(cssOrder)

View file

@ -25,6 +25,11 @@ export interface PageBuildData {
component: ComponentPath; component: ComponentPath;
route: RouteData; route: RouteData;
moduleSpecifier: string; moduleSpecifier: string;
preload: {
modules: Set<string>
fonts: Set<string>
styles: Set<string>
};
propagatedStyles: Map<string, Set<StylesheetAsset>>; propagatedStyles: Map<string, Set<StylesheetAsset>>;
propagatedScripts: Map<string, Set<string>>; propagatedScripts: Map<string, Set<string>>;
hoistedScript: { type: 'inline' | 'external'; value: string } | undefined; hoistedScript: { type: 'inline' | 'external'; value: string } | undefined;