Skip to content

Commit

Permalink
feat: new handling for define:vars scripts and styles
Browse files Browse the repository at this point in the history
  • Loading branch information
natemoo-re committed Jul 19, 2022
1 parent 963100f commit 02b15ed
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 36 deletions.
1 change: 1 addition & 0 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,7 @@ export interface SSRMetadata {
export interface SSRResult {
styles: Set<SSRElement>;
scripts: Set<SSRElement>;
defineVarsScripts: Set<string>;
links: Set<SSRElement>;
createAstro(
Astro: AstroGlobalPartial,
Expand Down
3 changes: 3 additions & 0 deletions packages/astro/src/core/render/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export interface RenderOptions {
origin: string;
pathname: string;
scripts: Set<SSRElement>;
defineVarsScripts: Set<string>;
resolve: (s: string) => Promise<string>;
renderers: SSRLoadedRenderer[];
route?: RouteData;
Expand All @@ -94,6 +95,7 @@ export async function render(opts: RenderOptions): Promise<Response> {
mod,
pathname,
scripts,
defineVarsScripts,
renderers,
request,
resolve,
Expand Down Expand Up @@ -139,6 +141,7 @@ export async function render(opts: RenderOptions): Promise<Response> {
request,
site,
scripts,
defineVarsScripts,
ssr,
streaming,
});
Expand Down
7 changes: 7 additions & 0 deletions packages/astro/src/core/render/dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ export async function render(
}
}

let defineVarsScripts = new Set<string>();
const defineVars = mod.hasOwnProperty('$$metadata') ? Array.from(mod.$$metadata.defineVarsScriptPaths()) : [];
for (const path of defineVars) {
defineVarsScripts.add(path);
}

// Pass framework CSS in as style tags to be appended to the page.
const { urls: styleUrls, stylesMap } = await getStylesForURL(filePath, viteServer, mode);
let links = new Set<SSRElement>();
Expand Down Expand Up @@ -165,6 +171,7 @@ export async function render(
let response = await coreRender({
links,
styles,
defineVarsScripts,
logging,
markdown: astroConfig.markdown,
mod,
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/core/render/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface CreateResultArgs {
site: string | undefined;
links?: Set<SSRElement>;
scripts?: Set<SSRElement>;
defineVarsScripts?: Set<string>;
styles?: Set<SSRElement>;
request: Request;
}
Expand Down Expand Up @@ -140,6 +141,7 @@ export function createResult(args: CreateResultArgs): SSRResult {
styles: args.styles ?? new Set<SSRElement>(),
scripts: args.scripts ?? new Set<SSRElement>(),
links: args.links ?? new Set<SSRElement>(),
defineVarsScripts: args.defineVarsScripts ?? new Set<string>(),
/** This function returns the `Astro` faux-global */
createAstro(
astroGlobal: AstroGlobalPartial,
Expand Down
25 changes: 25 additions & 0 deletions packages/astro/src/runtime/client/deserialize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
interface PropTypeSelector {
[k: string]: (value: any) => any;
}

const propTypes: PropTypeSelector = {
0: (value) => value,
1: (value) => JSON.parse(value, reviver),
2: (value) => new RegExp(value),
3: (value) => new Date(value),
4: (value) => new Map(JSON.parse(value, reviver)),
5: (value) => new Set(JSON.parse(value, reviver)),
6: (value) => BigInt(value),
7: (value) => new URL(value),
};

const reviver = (propKey: string, raw: string): any => {
if (propKey === '' || !Array.isArray(raw)) return raw;
if (Array.isArray(raw) && typeof raw[0] !== 'number') return JSON.stringify(raw);
const [type, value] = raw;
return type in propTypes ? propTypes[type](value) : undefined;
};

export default function deserialize(value: string) {
return JSON.parse(value, reviver);
}
45 changes: 20 additions & 25 deletions packages/astro/src/runtime/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,20 +201,6 @@ export async function renderComponent(
if (Component && (Component as any).isAstroComponentFactory) {
async function* renderAstroComponentInline(): AsyncGenerator<string, void, undefined> {
let iterable = await renderToIterable(result, Component as any, _props, slots);
// If this component added any define:vars styles and the head has already been
// sent out, we need to include those inline.
if (result.styles.size && alreadyHeadRenderedResults.has(result)) {
let styles = Array.from(result.styles);
result.styles.clear();
for (const style of styles) {
if ('define:vars' in style.props) {
// We only want to render the property value and not the full stylesheet
// which is bundled in the head.
style.children = '';
yield markHTMLString(renderElement('style', style));
}
}
}
yield* iterable;
}

Expand Down Expand Up @@ -594,16 +580,30 @@ export function spreadAttributes(
}

// Adds CSS variables to an inline style tag
export function defineStyleVars(selector: string, vars: Record<any, any>) {
let output = '\n';
for (const [key, value] of Object.entries(vars)) {
output += ` --${key}: ${value};\n`;
export function defineStyleVars(defs: Record<any, any>[]) {
let output = '';
for (const vars of defs) {
for (const [key, value] of Object.entries(vars)) {
if (value || value === 0) {
output += `--${key}: ${value};`;
}
}
}
return markHTMLString(`${selector} {${output}}`);
return markHTMLString(output);
}

// Adds variables to an inline script.
export function defineScriptVars(vars: Record<any, any>) {
export async function defineScriptVars(vars: Record<any, any>, info?: { file: string, index: number }, result?: SSRResult) {
if (typeof info !== 'undefined' && typeof result !== 'undefined') {
let match: string | undefined;
for (const script of result.defineVarsScripts) {
if (script.replace('/@fs', '').startsWith(info.file) && script.includes(`index=${info.index}`)) {
match = await result.resolve(script);
break;
}
}
return markHTMLString(`import("${match}").then(res => res.default(${JSON.stringify(serializeProps(vars))}))`)
}
let output = '';
for (const [key, value] of Object.entries(vars)) {
output += `let ${key} = ${JSON.stringify(value)};\n`;
Expand Down Expand Up @@ -902,11 +902,6 @@ function renderElement(
const { lang: _, 'data-astro-id': astroId, 'define:vars': defineVars, ...props } = _props;
if (defineVars) {
if (name === 'style') {
if (props['is:global']) {
children = defineStyleVars(`:root`, defineVars) + '\n' + children;
} else {
children = defineStyleVars(`.astro-${astroId}`, defineVars) + '\n' + children;
}
delete props['is:global'];
delete props['is:scoped'];
}
Expand Down
21 changes: 19 additions & 2 deletions packages/astro/src/runtime/server/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,25 @@ export class Metadata {
pathname = metadata.mockURL.pathname;

while (i < metadata.hoisted.length) {
// Strip off the leading "/@fs" added during compilation.
yield `${pathname.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`;
if (metadata.hoisted[i].type !== 'define:vars') {
// Strip off the leading "/@fs" added during compilation.
yield `${pathname.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`;
}
i++;
}
}
}

*defineVarsScriptPaths() {
for (const metadata of this.deepMetadata()) {
let i = 0,
pathname = metadata.mockURL.pathname;

while (i < metadata.hoisted.length) {
if (metadata.hoisted[i].type === 'define:vars') {
// Strip off the leading "/@fs" added during compilation.
yield `${pathname}?astro&type=script&index=${i}&lang.ts`;
}
i++;
}
}
Expand Down
42 changes: 33 additions & 9 deletions packages/astro/src/vite-plugin-astro/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PluginContext } from 'rollup';
import type { PluginContext, SourceDescription } from 'rollup';
import type * as vite from 'vite';
import type { AstroConfig } from '../@types/astro';
import type { LogOptions } from '../core/logger/core.js';
Expand Down Expand Up @@ -175,17 +175,36 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
}
}

return {
code:
hoistedScript.type === 'inline'
? hoistedScript.code!
: `import "${hoistedScript.src!}";`,
let result: SourceDescription & { meta: any } = {
code: '',
meta: {
vite: {
lang: 'ts',
},
},
lang: 'ts'
}
}
};

switch (hoistedScript.type) {
case 'inline': {
let { code, map } = hoistedScript
result.code = appendSourceMap(code, map);
break;
}
case 'external': {
const { src } = hoistedScript
result.code = `import "${src}"`;
break;
}
case 'define:vars': {
let { code, map, keys } = hoistedScript
// offset mappings by one
map = map.replace(`"mappings": "`, `"mappings": ";`)
result.code = appendSourceMap(`import d from 'astro/client/deserialize.js'; export default (s) => (async function({ ${keys} }) {\n${code}\n})(d(s))`, map);
break;
}
}

return result
}
default:
return null;
Expand Down Expand Up @@ -349,3 +368,8 @@ ${source}
},
};
}

function appendSourceMap(content: string, map?: string) {
// if (!map) return content;
return `${content}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${Buffer.from(map).toString('base64')}`
}

0 comments on commit 02b15ed

Please sign in to comment.