Progress on build demo
This commit is contained in:
parent
93ded5d79b
commit
530b77ed0a
7 changed files with 154 additions and 10 deletions
BIN
examples/docs/src/images/twitter.png
Normal file
BIN
examples/docs/src/images/twitter.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 457 B |
|
@ -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>
|
||||
|
|
1
examples/docs/src/layouts/script.js
Normal file
1
examples/docs/src/layouts/script.js
Normal file
|
@ -0,0 +1 @@
|
|||
console.log("HERE I AM");
|
|
@ -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!`);
|
||||
|
|
|
@ -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
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue