Skip to content

Commit

Permalink
Revert "Implement hydrated components in the static build (withastro#…
Browse files Browse the repository at this point in the history
…2260)" (withastro#2292)

* Revert "Implement hydrated components in the static build (withastro#2260)"

This reverts commit ae5255d.

* Adds a changeset
  • Loading branch information
matthewp committed Dec 30, 2021
1 parent ae1e61a commit 2e55dc2
Show file tree
Hide file tree
Showing 20 changed files with 207 additions and 382 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-zoos-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Rolls back a feature flag feature that was breaking the docs site
1 change: 0 additions & 1 deletion examples/fast-build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"dev": "astro dev --experimental-static-build",
"start": "astro dev",
"build": "astro build --experimental-static-build",
"scan-build": "astro build",
"preview": "astro preview"
},
"devDependencies": {
Expand Down
24 changes: 0 additions & 24 deletions examples/fast-build/src/components/Counter.vue

This file was deleted.

20 changes: 0 additions & 20 deletions examples/fast-build/src/pages/[pokemon].astro

This file was deleted.

18 changes: 6 additions & 12 deletions examples/fast-build/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import imgUrl from '../images/penguin.jpg';
import grayscaleUrl from '../images/random.jpg?grayscale=true';
import Greeting from '../components/Greeting.vue';
import Counter from '../components/Counter.vue';
---

<html>
Expand All @@ -27,14 +26,9 @@ import Counter from '../components/Counter.vue';
<Greeting />
</section>

<section>
<h1>ImageTools</h1>
<img src={grayscaleUrl} />
</section>

<section>
<h1>Hydrated component</h1>
<Counter client:idle />
</section>
</body>
</html>
<section>
<h1>ImageTools</h1>
<img src={grayscaleUrl} />
</section>
</body>
</html>
2 changes: 1 addition & 1 deletion packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"test": "mocha --parallel --timeout 15000"
},
"dependencies": {
"@astrojs/compiler": "^0.7.0",
"@astrojs/compiler": "^0.6.0",
"@astrojs/language-server": "^0.8.2",
"@astrojs/markdown-remark": "^0.6.0",
"@astrojs/prism": "0.4.0",
Expand Down
1 change: 0 additions & 1 deletion packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,5 @@ export interface SSRResult {
scripts: Set<SSRElement>;
links: Set<SSRElement>;
createAstro(Astro: AstroGlobalPartial, props: Record<string, any>, slots: Record<string, any> | null): AstroGlobal;
resolve: (s: string) => Promise<string>;
_metadata: SSRMetadata;
}
5 changes: 0 additions & 5 deletions packages/astro/src/core/build/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ export interface BuildInternals {

// A mapping to entrypoints (facadeId) to assets (styles) that are added.
facadeIdToAssetsMap: Map<string, string[]>;

// A mapping of specifiers like astro/client/idle.js to the hashed bundled name.
// Used to render pages with the correct specifiers.
entrySpecifierToBundleMap: Map<string, string>;
}

/**
Expand Down Expand Up @@ -45,6 +41,5 @@ export function createBuildInternals(): BuildInternals {
astroStyleMap,
astroPageStyleMap,
facadeIdToAssetsMap,
entrySpecifierToBundleMap: new Map<string, string>(),
};
}
152 changes: 22 additions & 130 deletions packages/astro/src/core/build/static-build.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { OutputChunk, PreRenderedChunk, RollupOutput } from 'rollup';
import type { Plugin as VitePlugin } from '../vite';
import type { AstroConfig, RouteCache, SSRElement } from '../../@types/astro';
import type { AstroConfig, RouteCache } from '../../@types/astro';
import type { AllPagesData } from './types';
import type { LogOptions } from '../logger';
import type { ViteConfigWithSSR } from '../create-vite';
Expand All @@ -9,16 +9,12 @@ import type { BuildInternals } from '../../core/build/internal.js';
import type { AstroComponentFactory } from '../../runtime/server';

import fs from 'fs';
import npath from 'path';
import { fileURLToPath } from 'url';
import glob from 'fast-glob';
import vite from '../vite.js';
import { debug, info, error } from '../../core/logger.js';
import { createBuildInternals } from '../../core/build/internal.js';
import { rollupPluginAstroBuildCSS } from '../../vite-plugin-build-css/index.js';
import { getParamsAndProps } from '../ssr/index.js';
import { createResult } from '../ssr/result.js';
import { renderPage } from '../../runtime/server/index.js';
import { renderComponent, getParamsAndProps } from '../ssr/index.js';

export interface StaticBuildOptions {
allPages: AllPagesData;
Expand All @@ -32,47 +28,35 @@ export interface StaticBuildOptions {
export async function staticBuild(opts: StaticBuildOptions) {
const { allPages, astroConfig } = opts;

// The pages to be built for rendering purposes.
const pageInput = new Set<string>();

// The JavaScript entrypoints.
const jsInput = new Set<string>();
const jsInput: Set<string> = new Set();

// A map of each page .astro file, to the PageBuildData which contains information
// about that page, such as its paths.
const facadeIdToPageDataMap = new Map<string, PageBuildData>();

for (const [component, pageData] of Object.entries(allPages)) {
const [renderers, mod] = pageData.preload;
const metadata = mod.$$metadata;

const topLevelImports = new Set([
// Any component that gets hydrated
...metadata.hydratedComponentPaths(),
// Any hydration directive like astro/client/idle.js
...metadata.hydrationDirectiveSpecifiers(),
// The client path for each renderer
...renderers.filter((renderer) => !!renderer.source).map((renderer) => renderer.source!),
]);

for (const specifier of topLevelImports) {
jsInput.add(specifier);
// Hydrated components are statically identified.
for (const path of mod.$$metadata.getAllHydratedComponentPaths()) {
// Note that this part is not yet implemented in the static build.
//jsInput.add(path);
}

let astroModuleId = new URL('./' + component, astroConfig.projectRoot).pathname;
pageInput.add(astroModuleId);
jsInput.add(astroModuleId);
facadeIdToPageDataMap.set(astroModuleId, pageData);
}

// Build internals needed by the CSS plugin
const internals = createBuildInternals();

// Run the SSR build and client build in parallel
const [ssrResult] = (await Promise.all([ssrBuild(opts, internals, pageInput), clientBuild(opts, internals, jsInput)])) as RollupOutput[];
// Perform the SSR build
const result = (await ssrBuild(opts, internals, jsInput)) as RollupOutput;

// Generate each of the pages.
await generatePages(ssrResult, opts, internals, facadeIdToPageDataMap);
await cleanSsrOutput(opts);
await generatePages(result, opts, internals, facadeIdToPageDataMap);
}

async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, input: Set<string>) {
Expand All @@ -83,7 +67,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
mode: 'production',
build: {
emptyOutDir: true,
minify: false,
minify: false, // 'esbuild', // significantly faster than "terser" but may produce slightly-bigger bundles
outDir: fileURLToPath(astroConfig.dist),
ssr: true,
rollupOptions: {
Expand All @@ -95,41 +79,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
target: 'es2020', // must match an esbuild target
},
plugins: [
vitePluginNewBuild(input, internals, 'mjs'),
rollupPluginAstroBuildCSS({
internals,
}),
...(viteConfig.plugins || []),
],
publicDir: viteConfig.publicDir,
root: viteConfig.root,
envPrefix: 'PUBLIC_',
server: viteConfig.server,
base: astroConfig.buildOptions.site ? new URL(astroConfig.buildOptions.site).pathname : '/',
});
}

async function clientBuild(opts: StaticBuildOptions, internals: BuildInternals, input: Set<string>) {
const { astroConfig, viteConfig } = opts;

return await vite.build({
logLevel: 'error',
mode: 'production',
build: {
emptyOutDir: false,
minify: 'esbuild',
outDir: fileURLToPath(astroConfig.dist),
rollupOptions: {
input: Array.from(input),
output: {
format: 'esm',
},
preserveEntrySignatures: 'exports-only',
},
target: 'es2020', // must match an esbuild target
},
plugins: [
vitePluginNewBuild(input, internals, 'js'),
vitePluginNewBuild(),
rollupPluginAstroBuildCSS({
internals,
}),
Expand Down Expand Up @@ -174,7 +124,6 @@ async function generatePage(output: OutputChunk, opts: StaticBuildOptions, inter

const generationOptions: Readonly<GeneratePathOptions> = {
pageData,
internals,
linkIds,
Component,
};
Expand All @@ -187,14 +136,13 @@ async function generatePage(output: OutputChunk, opts: StaticBuildOptions, inter

interface GeneratePathOptions {
pageData: PageBuildData;
internals: BuildInternals;
linkIds: string[];
Component: AstroComponentFactory;
}

async function generatePath(pathname: string, opts: StaticBuildOptions, gopts: GeneratePathOptions) {
async function generatePath(path: string, opts: StaticBuildOptions, gopts: GeneratePathOptions) {
const { astroConfig, logging, origin, routeCache } = opts;
const { Component, internals, linkIds, pageData } = gopts;
const { Component, linkIds, pageData } = gopts;

const [renderers, mod] = pageData.preload;

Expand All @@ -203,36 +151,14 @@ async function generatePath(pathname: string, opts: StaticBuildOptions, gopts: G
route: pageData.route,
routeCache,
logging,
pathname,
pathname: path,
mod,
});

debug(logging, 'generate', `Generating: ${pathname}`);
info(logging, 'generate', `Generating: ${path}`);

const result = createResult({ astroConfig, origin, params, pathname, renderers });
result.links = new Set<SSRElement>(
linkIds.map((href) => ({
props: {
rel: 'stylesheet',
href,
},
children: '',
}))
);
// Override the `resolve` method so that hydrated components are given the
// hashed filepath to the component.
result.resolve = async (specifier: string) => {
const hashedFilePath = internals.entrySpecifierToBundleMap.get(specifier);
if (typeof hashedFilePath !== 'string') {
throw new Error(`Cannot find the built path for ${specifier}`);
}
const relPath = npath.posix.relative(pathname, '/' + hashedFilePath);
const fullyRelativePath = relPath[0] === '.' ? relPath : './' + relPath;
return fullyRelativePath;
};

let html = await renderPage(result, Component, pageProps, null);
const outFolder = new URL('.' + pathname + '/', astroConfig.dist);
const html = await renderComponent(renderers, Component, astroConfig, path, origin, params, pageProps, linkIds);
const outFolder = new URL('.' + path + '/', astroConfig.dist);
const outFile = new URL('./index.html', outFolder);
await fs.promises.mkdir(outFolder, { recursive: true });
await fs.promises.writeFile(outFile, html, 'utf-8');
Expand All @@ -241,20 +167,7 @@ async function generatePath(pathname: string, opts: StaticBuildOptions, gopts: G
}
}

async function cleanSsrOutput(opts: StaticBuildOptions) {
// The SSR output is all .mjs files, the client output is not.
const files = await glob('**/*.mjs', {
cwd: opts.astroConfig.dist.pathname,
});
await Promise.all(
files.map(async (filename) => {
const url = new URL(filename, opts.astroConfig.dist);
await fs.promises.rm(url);
})
);
}

export function vitePluginNewBuild(input: Set<string>, internals: BuildInternals, ext: 'js' | 'mjs'): VitePlugin {
export function vitePluginNewBuild(): VitePlugin {
return {
name: '@astro/rollup-plugin-new-build',

Expand All @@ -270,34 +183,13 @@ export function vitePluginNewBuild(input: Set<string>, internals: BuildInternals
outputOptions(outputOptions) {
Object.assign(outputOptions, {
entryFileNames(_chunk: PreRenderedChunk) {
return 'assets/[name].[hash].' + ext;
return 'assets/[name].[hash].mjs';
},
chunkFileNames(_chunk: PreRenderedChunk) {
return 'assets/[name].[hash].' + ext;
return 'assets/[name].[hash].mjs';
},
});
return outputOptions;
},

async generateBundle(_options, bundle) {
const promises = [];
const mapping = new Map<string, string>();
for (const specifier of input) {
promises.push(
this.resolve(specifier).then((result) => {
if (result) {
mapping.set(result.id, specifier);
}
})
);
}
await Promise.all(promises);
for (const [, chunk] of Object.entries(bundle)) {
if (chunk.type === 'chunk' && chunk.facadeModuleId && mapping.has(chunk.facadeModuleId)) {
const specifier = mapping.get(chunk.facadeModuleId)!;
internals.entrySpecifierToBundleMap.set(specifier, chunk.fileName);
}
}
},
};
}
Loading

0 comments on commit 2e55dc2

Please sign in to comment.