mirror of
https://github.com/withastro/astro.git
synced 2025-02-03 22:29:08 -05:00
feat: (naively) minify astro-generated JS and CSS
This commit is contained in:
parent
b3b18554df
commit
4fc4bea975
3 changed files with 38 additions and 10 deletions
|
@ -1,6 +1,6 @@
|
|||
import type { AstroComponentMetadata } from '../../@types/astro';
|
||||
import type { SSRElement, SSRResult } from '../../@types/astro';
|
||||
import { hydrationSpecifier, serializeListValue } from './util.js';
|
||||
import { hydrationSpecifier, serializeListValue, naiveMinify } from './util.js';
|
||||
import serializeJavaScript from 'serialize-javascript';
|
||||
|
||||
// Serializes props passed into a component so that they can be reused during hydration.
|
||||
|
@ -91,7 +91,8 @@ interface HydrateScriptOptions {
|
|||
export async function generateHydrateScript(scriptOptions: HydrateScriptOptions, metadata: Required<AstroComponentMetadata>): Promise<SSRElement> {
|
||||
const { renderer, result, astroId, props } = scriptOptions;
|
||||
const { hydrate, componentUrl, componentExport } = metadata;
|
||||
|
||||
const PROPS_PLACEHOLDER = `/*astro:PROPS*/`;
|
||||
const HYDRATE_ARGS_PLACEHOLDER = `/*astro:HYDRATE_ARGS*/`;
|
||||
if (!componentExport) {
|
||||
throw new Error(`Unable to resolve a componentExport for "${metadata.displayName}"! Please open an issue.`);
|
||||
}
|
||||
|
@ -107,19 +108,32 @@ export async function generateHydrateScript(scriptOptions: HydrateScriptOptions,
|
|||
? `const [{ ${componentExport.value}: Component }, { default: hydrate }] = await Promise.all([import("${await result.resolve(componentUrl)}"), import("${await result.resolve(
|
||||
renderer.source
|
||||
)}")]);
|
||||
return (el, children) => hydrate(el)(Component, ${serializeProps(props)}, children);
|
||||
return (el, children) => hydrate(el)(Component, ${PROPS_PLACEHOLDER}, children);
|
||||
`
|
||||
: `await import("${await result.resolve(componentUrl)}");
|
||||
return () => {};
|
||||
`;
|
||||
|
||||
hydrationSource = `
|
||||
import setup from '${await result.resolve(hydrationSpecifier(hydrate))}';
|
||||
setup("${astroId}", {name:"${metadata.displayName}",${metadata.hydrateArgs ? `value:${HYDRATE_ARGS_PLACEHOLDER}` : ''}}, async () => {
|
||||
${hydrationSource}
|
||||
});
|
||||
`;
|
||||
// Minify output (we know all these identifiers)
|
||||
// Important! Use placeholder comments to avoid
|
||||
// minifying user content inside of strings
|
||||
hydrationSource = naiveMinify(hydrationSource, {
|
||||
setup: 'a',
|
||||
hydrate: 'b',
|
||||
Component: 'c',
|
||||
children: 'd',
|
||||
el: 'e',
|
||||
})
|
||||
.replace(PROPS_PLACEHOLDER, serializeProps(props))
|
||||
.replace(HYDRATE_ARGS_PLACEHOLDER, JSON.stringify(metadata.hydrateArgs));
|
||||
const hydrationScript = {
|
||||
props: { type: 'module', 'data-astro-component-hydration': true },
|
||||
children: `import setup from '${await result.resolve(hydrationSpecifier(hydrate))}';
|
||||
setup("${astroId}", {name:"${metadata.displayName}",${metadata.hydrateArgs ? `value: ${JSON.stringify(metadata.hydrateArgs)}` : ''}}, async () => {
|
||||
${hydrationSource}
|
||||
});
|
||||
`,
|
||||
children: hydrationSource,
|
||||
};
|
||||
|
||||
return hydrationScript;
|
||||
|
|
|
@ -460,7 +460,7 @@ export async function renderPage(result: SSRResult, Component: AstroComponentFac
|
|||
});
|
||||
});
|
||||
if (needsHydrationStyles) {
|
||||
styles.push(renderElement('style', { props: { 'astro-style': true }, children: 'astro-root, astro-fragment { display: contents; }' }));
|
||||
styles.push(renderElement('style', { props: { 'astro-style': true }, children: 'astro-root,astro-fragment{display:contents;}' }));
|
||||
}
|
||||
|
||||
const links = Array.from(result.links)
|
||||
|
|
|
@ -43,3 +43,17 @@ export function serializeListValue(value: any) {
|
|||
export function hydrationSpecifier(hydrate: string) {
|
||||
return `astro/client/${hydrate}.js`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minifies JS without parsing, just replacing whitespace and passed identifiers.
|
||||
* @param source a string of JS
|
||||
* @param identifiers any specific identifiers that should be replaced
|
||||
* @returns a minified source string
|
||||
*/
|
||||
export function naiveMinify(source: string, identifiers: Record<string, string> = {}): string {
|
||||
source = source.trim().replace(/\s+/g, ' ').replace(/([^a-z])\s+/g, '$1').replace(/\s+([^a-zA-Z])/g, '$1');
|
||||
for (const [identifier, char] of Object.entries(identifiers)) {
|
||||
source = source.replaceAll(identifier, char);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue