Progress on build demo

This commit is contained in:
Matthew Phillips 2021-12-02 08:11:39 -05:00
parent 93ded5d79b
commit 530b77ed0a
7 changed files with 154 additions and 10 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

View file

@ -118,5 +118,7 @@ const githubEditUrl = CONFIG.GITHUB_EDIT_URL && (CONFIG.GITHUB_EDIT_URL + curren
<RightSidebar content={content} githubEditUrl={githubEditUrl} />
</aside>
</main>
<script type="module" src={Astro.resolve('./script.js')} hoist></script>
<img src={Astro.resolve('../images/twitter.png')} />
</body>
</html>

View file

@ -0,0 +1 @@
console.log("HERE I AM");

View file

@ -1,6 +1,6 @@
import type { AstroConfig, ComponentInstance, GetStaticPathsResult, ManifestData, RouteCache, RouteData, RSSResult } from '../../@types/astro';
import type { LogOptions } from '../logger';
import type { AllPagesData } from './types';
import type { AllPagesData, PageBuildData } from './types';
import type { RenderedChunk } from 'rollup';
import { rollupPluginAstroBuildHTML } from '../../vite-plugin-build-html/index.js';
@ -12,7 +12,7 @@ import vite, { ViteDevServer } from '../vite.js';
import { fileURLToPath } from 'url';
import { createVite, ViteConfigWithSSR } from '../create-vite.js';
import { debug, defaultLogOptions, info, levels, timerMessage, warn } from '../logger.js';
import { preload as ssrPreload } from '../ssr/index.js';
import { preload as ssrPreload, renderComponent, getParamsAndProps } from '../ssr/index.js';
import { generatePaginateFunction } from '../ssr/paginate.js';
import { createRouteManifest, validateGetStaticPathsModule, validateGetStaticPathsResult } from '../ssr/routing.js';
import { generateRssFunction } from '../ssr/rss.js';
@ -162,20 +162,26 @@ class AstroBuilder {
const pageNames: string[] = [];
// Blah
const facadeIdToPageDataMap = new Map<string, PageBuildData>();
// Bundle the assets in your final build: This currently takes the HTML output
// of every page (stored in memory) and bundles the assets pointed to on those pages.
timer.buildStart = performance.now();
await vite.build({
let result = await vite.build({
logLevel: 'error',
mode: 'production',
build: {
emptyOutDir: true,
minify: 'esbuild', // significantly faster than "terser" but may produce slightly-bigger bundles
minify: false,// 'esbuild', // significantly faster than "terser" but may produce slightly-bigger bundles
outDir: fileURLToPath(this.config.dist),
ssr: true,
rollupOptions: {
// The `input` will be populated in the build rollup plugin.
input: [],
output: { format: 'esm' },
output: {
format: 'cjs'
},
},
target: 'es2020', // must match an esbuild target
},
@ -192,6 +198,7 @@ class AstroBuilder {
pageNames,
routeCache: this.routeCache,
viteServer,
facadeIdToPageDataMap,
}),
rollupPluginAstroBuildCSS({
astroPageStyleMap,
@ -209,6 +216,13 @@ class AstroBuilder {
});
debug(logging, 'build', timerMessage('Vite build finished', timer.buildStart));
/* TODO REMOVE THIS NEW HACKY CODE */
console.log('End build step, now generating');
for(let out of (result as any).output) {
if(out.facadeModuleId)
await this.doTheRest(out, facadeIdToPageDataMap);
}
// Write any additionally generated assets to disk.
timer.assetsStart = performance.now();
Object.keys(assets).map((k) => {
@ -237,6 +251,35 @@ class AstroBuilder {
}
}
private async doTheRest(out: any, facadeIdToPageDataMap: Map<string, PageBuildData>) {
let url = new URL('./' + out.fileName, this.config.dist);
let pageData = facadeIdToPageDataMap.get(out.facadeModuleId)!;
let compiledModule = await import(url.toString());
let Component = compiledModule.default.default;
const [renderers, mod] = pageData.preload;
for(let path of pageData.paths) {
try {
const [params, pageProps] = await getParamsAndProps({
route: pageData.route,
routeCache: this.routeCache,
logging: this.logging,
pathname: path,
mod
})
console.log(`Generating: ${path}`);
let html = await renderComponent(renderers, Component, this.config, path, this.origin, params, pageProps);
let outFolder = new URL('.' + path + '/', this.config.dist);
let outFile = new URL('./index.html', outFolder);
await fs.promises.mkdir(outFolder, { recursive: true });
await fs.promises.writeFile(outFile, html, 'utf-8');
} catch(err) {
console.error("did not work", err);
}
}
}
/** Extract all static paths from a dynamic route */
private async getStaticPathsForRoute(route: RouteData): Promise<{ paths: string[]; rss?: RSSResult }> {
if (!this.viteServer) throw new Error(`vite.createServer() not called!`);

View file

@ -17,6 +17,7 @@ import type {
SSRResult,
} from '../../@types/astro';
import type { LogOptions } from '../logger';
import type { AstroComponentFactory } from '../../runtime/server/index';
import eol from 'eol';
import fs from 'fs';
@ -138,6 +139,89 @@ export async function preload({ astroConfig, filePath, viteServer }: SSROptions)
return [renderers, mod];
}
export async function renderComponent(renderers: Renderer[], Component: AstroComponentFactory, astroConfig: AstroConfig, pathname: string, origin: string, params: Params, pageProps: Props): Promise<string> {
const result: SSRResult = {
styles: new Set<SSRElement>(),
scripts: new Set<SSRElement>(),
/** This function returns the `Astro` faux-global */
createAstro(astroGlobal: AstroGlobalPartial, props: Record<string, any>, slots: Record<string, any> | null) {
const site = new URL(origin);
const url = new URL('.' + pathname, site);
const canonicalURL = getCanonicalURL('.' + pathname, astroConfig.buildOptions.site || origin);
return {
__proto__: astroGlobal,
props,
request: {
canonicalURL,
params,
url,
},
slots: Object.fromEntries(Object.entries(slots || {}).map(([slotName]) => [slotName, true])),
// This is used for <Markdown> but shouldn't be used publicly
privateRenderSlotDoNotUse(slotName: string) {
return renderSlot(result, slots ? slots[slotName] : null);
},
// <Markdown> also needs the same `astroConfig.markdownOptions.render` as `.md` pages
async privateRenderMarkdownDoNotUse(content: string, opts: any) {
let mdRender = astroConfig.markdownOptions.render;
let renderOpts = {};
if (Array.isArray(mdRender)) {
renderOpts = mdRender[1];
mdRender = mdRender[0];
}
if (typeof mdRender === 'string') {
({ default: mdRender } = await import(mdRender));
}
const { code } = await mdRender(content, { ...renderOpts, ...(opts ?? {}) });
return code;
},
} as unknown as AstroGlobal;
},
_metadata: {
renderers,
pathname,
experimentalStaticBuild: astroConfig.buildOptions.experimentalStaticBuild
},
};
let html = await renderPage(result, Component, pageProps, null);
return html;
}
export async function getParamsAndProps({route, routeCache, logging, pathname, mod}: {route: RouteData | undefined, routeCache: RouteCache, pathname: string, mod: ComponentInstance, logging: LogOptions}): Promise<[Params, Props]> {
// Handle dynamic routes
let params: Params = {};
let pageProps: Props = {};
if (route && !route.pathname) {
if (route.params.length) {
const paramsMatch = route.pattern.exec(pathname);
if (paramsMatch) {
params = getParams(route.params)(paramsMatch);
}
}
validateGetStaticPathsModule(mod);
if (!routeCache[route.component]) {
routeCache[route.component] = await (
await mod.getStaticPaths!({
paginate: generatePaginateFunction(route),
rss: () => {
/* noop */
},
})
).flat();
}
validateGetStaticPathsResult(routeCache[route.component], logging);
const routePathParams: GetStaticPathsResult = routeCache[route.component];
const matchedStaticPath = routePathParams.find(({ params: _params }) => JSON.stringify(_params) === JSON.stringify(params));
if (!matchedStaticPath) {
throw new Error(`[getStaticPaths] route pattern matched, but no matching static path found. (${pathname})`);
}
pageProps = { ...matchedStaticPath.props } || {};
}
return [params, pageProps];
}
/** use Vite to SSR */
export async function render(renderers: Renderer[], mod: ComponentInstance, ssrOpts: SSROptions): Promise<string> {
const { astroConfig, filePath, logging, mode, origin, pathname, route, routeCache, viteServer } = ssrOpts;
@ -225,6 +309,7 @@ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrO
_metadata: {
renderers,
pathname,
experimentalStaticBuild: astroConfig.buildOptions.experimentalStaticBuild
},
};

View file

@ -2,7 +2,7 @@ import type { AstroConfig, RouteCache } from '../@types/astro';
import type { LogOptions } from '../core/logger';
import type { ViteDevServer, Plugin as VitePlugin } from '../core/vite';
import type { OutputChunk, PreRenderedChunk, RenderedChunk } from 'rollup';
import type { AllPagesData } from '../core/build/types';
import type { AllPagesData, PageBuildData } from '../core/build/types';
import parse5 from 'parse5';
import srcsetParse from 'srcset-parse';
import * as npath from 'path';
@ -36,6 +36,8 @@ interface PluginOptions {
origin: string;
routeCache: RouteCache;
viteServer: ViteDevServer;
facadeIdToPageDataMap: Map<string, PageBuildData>;
}
export function rollupPluginAstroBuildHTML(options: PluginOptions): VitePlugin {
@ -72,10 +74,16 @@ export function rollupPluginAstroBuildHTML(options: PluginOptions): VitePlugin {
// Hydrated components are statically identified.
for (const path of mod.$$metadata.getAllHydratedComponentPaths()) {
jsInput.add(path);
//jsInput.add(path);
}
let astroModuleId = new URL('./' + component, astroConfig.projectRoot).pathname;
jsInput.add(astroModuleId);
options.facadeIdToPageDataMap.set(astroModuleId, pageData);
for (const pathname of pageData.paths) {
/*
pageNames.push(pathname.replace(/\/?$/, '/index.html').replace(/^\//, ''));
const id = ASTRO_PAGE_PREFIX + pathname;
const html = await ssrRender(renderers, mod, {
@ -183,6 +191,8 @@ export function rollupPluginAstroBuildHTML(options: PluginOptions): VitePlugin {
if (!pageStyleImportOrder.includes(assetHref)) pageStyleImportOrder.push(assetHref);
}
}
*/
}
}
@ -233,10 +243,13 @@ export function rollupPluginAstroBuildHTML(options: PluginOptions): VitePlugin {
if (!pageName) {
pageName = 'index';
}
return `assets/${pageName}.[hash].js`;
return `assets/${pageName}.[hash].cjs`;
}
return 'assets/[name].[hash].js';
return 'assets/[name].[hash].cjs';
},
chunkFileNames(chunk: PreRenderedChunk) {
return 'assets/[name].[hash].cjs';
}
});
return outputOptions;
},

View file

@ -18,7 +18,7 @@ describe('Astro basics', () => {
});
describe('build', () => {
it('Can load page', async () => {
it.only('Can load page', async () => {
const html = await fixture.readFile(`/index.html`);
const $ = cheerio.load(html);