Fred fixes part 2

This commit is contained in:
Fred K. Schott 2021-09-20 19:29:16 +00:00 committed by Matthew Phillips
parent ec746089df
commit 3c1fcc237d
10 changed files with 1060 additions and 1215 deletions

View file

@ -40,9 +40,7 @@
"npm": "7.11.2", "npm": "7.11.2",
"yarn": "1.22.10" "yarn": "1.22.10"
}, },
"dependencies": { "dependencies": {},
"camel-case": "^4.1.2"
},
"devDependencies": { "devDependencies": {
"@changesets/cli": "^2.16.0", "@changesets/cli": "^2.16.0",
"@types/jest": "^27.0.1", "@types/jest": "^27.0.1",

View file

@ -42,17 +42,14 @@
"@astrojs/compiler": "^0.1.0-canary.37", "@astrojs/compiler": "^0.1.0-canary.37",
"@astrojs/markdown-remark": "^0.3.1", "@astrojs/markdown-remark": "^0.3.1",
"@babel/core": "^7.15.0", "@babel/core": "^7.15.0",
"@types/rimraf": "^3.0.2",
"@web/rollup-plugin-html": "^1.9.1", "@web/rollup-plugin-html": "^1.9.1",
"astring": "^1.7.5", "astring": "^1.7.5",
"camel-case": "^4.1.2",
"chokidar": "^3.5.2",
"ci-info": "^3.2.0", "ci-info": "^3.2.0",
"connect": "^3.7.0", "connect": "^3.7.0",
"del": "^6.0.0",
"es-module-lexer": "^0.7.1", "es-module-lexer": "^0.7.1",
"esbuild": "^0.12.23", "esbuild": "^0.12.23",
"estree-util-value-to-estree": "^1.2.0", "estree-util-value-to-estree": "^1.2.0",
"etag": "^1.8.1",
"fast-xml-parser": "^3.19.0", "fast-xml-parser": "^3.19.0",
"fdir": "^5.1.0", "fdir": "^5.1.0",
"get-port": "^5.1.1", "get-port": "^5.1.1",
@ -63,6 +60,7 @@
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"path-to-regexp": "^6.2.0", "path-to-regexp": "^6.2.0",
"picomatch": "^2.3.0", "picomatch": "^2.3.0",
"rimraf": "^3.0.2",
"sass": "^1.38.1", "sass": "^1.38.1",
"semver": "^7.3.5", "semver": "^7.3.5",
"send": "^0.17.1", "send": "^0.17.1",
@ -71,6 +69,7 @@
"slash": "^4.0.0", "slash": "^4.0.0",
"srcset-parse": "^1.1.0", "srcset-parse": "^1.1.0",
"source-map": "^0.7.3", "source-map": "^0.7.3",
"sourcemap-codec": "^1.4.8",
"string-width": "^5.0.0", "string-width": "^5.0.0",
"strip-ansi": "^7.0.1", "strip-ansi": "^7.0.1",
"supports-esm": "^1.0.0", "supports-esm": "^1.0.0",
@ -81,7 +80,6 @@
"devDependencies": { "devDependencies": {
"@types/babel__core": "^7.1.15", "@types/babel__core": "^7.1.15",
"@types/connect": "^3.4.35", "@types/connect": "^3.4.35",
"@types/etag": "^1.8.1",
"@types/mime": "^2.0.3", "@types/mime": "^2.0.3",
"@types/node-fetch": "^2.5.12", "@types/node-fetch": "^2.5.12",
"@types/send": "^0.17.1", "@types/send": "^0.17.1",

View file

@ -100,7 +100,6 @@ export interface AstroUserConfig {
// @types/config.ts file, consider replacing it with the following lines: // @types/config.ts file, consider replacing it with the following lines:
// //
// export interface AstroUserConfig extends z.input<typeof AstroConfigSchema> { // export interface AstroUserConfig extends z.input<typeof AstroConfigSchema> {
// markdownOptions?: Partial<AstroMarkdownOptions>;
// } // }
export type AstroConfig = z.output<typeof AstroConfigSchema>; export type AstroConfig = z.output<typeof AstroConfigSchema>;

View file

@ -1,6 +1,5 @@
import type { LogOptions } from '../logger'; import type { LogOptions } from '../logger';
import rimraf from 'rimraf';
import del from 'del';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import { defaultLogDestination, defaultLogLevel, info } from '../logger.js'; import { defaultLogDestination, defaultLogLevel, info } from '../logger.js';
@ -13,7 +12,7 @@ export async function reload(cwd: string) {
try { try {
info(logging, 'reload', `Clearing the cache...`); info(logging, 'reload', `Clearing the cache...`);
const viteCache = new URL('node_modules/.vite/', `file://${cwd}/`); const viteCache = new URL('node_modules/.vite/', `file://${cwd}/`);
await del(fileURLToPath(viteCache)); rimraf.sync(fileURLToPath(viteCache));
return 0; return 0;
} catch { } catch {
return 1; return 1;

View file

@ -4,16 +4,12 @@ import type { AstroConfig, ManifestData, RouteCache, RouteData, SSRError } from
import type { LogOptions } from '../logger'; import type { LogOptions } from '../logger';
import type { HmrContext, ModuleNode } from 'vite'; import type { HmrContext, ModuleNode } from 'vite';
import chokidar from 'chokidar'; import { fileURLToPath } from 'url';
import connect from 'connect'; import connect from 'connect';
import mime from 'mime'; import mime from 'mime';
import getEtag from 'etag';
import { performance } from 'perf_hooks'; import { performance } from 'perf_hooks';
import { fileURLToPath } from 'url';
import { createRequire } from 'module'; import { createRequire } from 'module';
import stripAnsi from 'strip-ansi'; import stripAnsi from 'strip-ansi';
import path from 'path';
import { promises as fs } from 'fs';
import vite from 'vite'; import vite from 'vite';
import { defaultLogOptions, error, info } from '../logger.js'; import { defaultLogOptions, error, info } from '../logger.js';
import { createRouteManifest, matchRoute } from '../runtime/routing.js'; import { createRouteManifest, matchRoute } from '../runtime/routing.js';
@ -65,7 +61,6 @@ export class AstroDevServer {
private origin: string; private origin: string;
private routeCache: RouteCache = {}; private routeCache: RouteCache = {};
private viteServer: vite.ViteDevServer | undefined; private viteServer: vite.ViteDevServer | undefined;
private watcher: chokidar.FSWatcher;
private mostRecentRoute?: RouteData; private mostRecentRoute?: RouteData;
constructor(config: AstroConfig, options: DevOptions) { constructor(config: AstroConfig, options: DevOptions) {
@ -76,20 +71,6 @@ export class AstroDevServer {
this.port = config.devOptions.port; this.port = config.devOptions.port;
this.origin = config.buildOptions.site ? new URL(config.buildOptions.site).origin : `http://localhost:${this.port}`; this.origin = config.buildOptions.site ? new URL(config.buildOptions.site).origin : `http://localhost:${this.port}`;
this.manifest = createRouteManifest({ config }); this.manifest = createRouteManifest({ config });
// rebuild manifest on change (watch all events, but only rebuild if .astro or .md files are touched)
this.watcher = chokidar.watch(fileURLToPath(config.pages), { ignored: ['!**/*.astro', '!**/*.md', '**'] }); // ignore everything but .astro & .md
this.watcher.on('add', () => {
this.routeCache = {};
this.manifest = createRouteManifest({ config: this.config });
});
this.watcher.on('unlink', () => {
this.routeCache = {};
this.manifest = createRouteManifest({ config: this.config });
});
this.watcher.on('change', () => {
this.routeCache = {}; // note: manifests dont need to be rebuilt on file content changes
});
} }
/** Start dev server */ /** Start dev server */
@ -98,6 +79,7 @@ export class AstroDevServer {
const devStart = performance.now(); const devStart = performance.now();
// 2. create Vite instance // 2. create Vite instance
const pagesDirectory = fileURLToPath(this.config.pages);
const viteConfig = await loadViteConfig( const viteConfig = await loadViteConfig(
{ {
mode: 'development', mode: 'development',
@ -109,6 +91,28 @@ export class AstroDevServer {
{ astroConfig: this.config, logging: this.logging, devServer: this } { astroConfig: this.config, logging: this.logging, devServer: this }
); );
this.viteServer = await vite.createServer(viteConfig); this.viteServer = await vite.createServer(viteConfig);
this.viteServer.watcher.on('add', (file) => {
// Only rebuild routes if new file is a page.
if (!file.startsWith(pagesDirectory)) {
return;
}
this.routeCache = {};
this.manifest = createRouteManifest({ config: this.config });
});
this.viteServer.watcher.on('unlink', (file) => {
// Only rebuild routes if deleted file is a page.
if (!file.startsWith(pagesDirectory)) {
return;
}
this.routeCache = {};
this.manifest = createRouteManifest({ config: this.config });
});
this.viteServer.watcher.on('change', () => {
// No need to rebuild routes on file content changes.
// However, we DO want to clear the cache in case
// the change caused a getStaticPaths() return to change.
this.routeCache = {};
});
// 3. add middlewares // 3. add middlewares
this.app.use((req, res, next) => this.handleRequest(req, res, next)); this.app.use((req, res, next) => this.handleRequest(req, res, next));
@ -136,7 +140,6 @@ export class AstroDevServer {
if (this.httpServer) this.httpServer.close(); // close HTTP server if (this.httpServer) this.httpServer.close(); // close HTTP server
await Promise.all([ await Promise.all([
...(this.viteServer ? [this.viteServer.close()] : []), // close Vite server ...(this.viteServer ? [this.viteServer.close()] : []), // close Vite server
this.watcher.close(), // close chokidar
]); ]);
} }

View file

@ -1,6 +1,6 @@
import type { AstroComponentMetadata } from '../@types/astro'; import type { AstroComponentMetadata } from '../@types/astro';
import { valueToEstree, Value } from 'estree-util-value-to-estree'; import { valueToEstree } from 'estree-util-value-to-estree';
import * as astring from 'astring'; import * as astring from 'astring';
import shorthash from 'shorthash'; import shorthash from 'shorthash';
import { renderToString, renderAstroComponent } from '../runtime/astro.js'; import { renderToString, renderAstroComponent } from '../runtime/astro.js';
@ -21,7 +21,7 @@ const customGenerator: astring.Generator = {
} }
}, },
}; };
const serialize = (value: Value) => const serialize = (value: any) =>
generate(valueToEstree(value), { generate(valueToEstree(value), {
generator: customGenerator, generator: customGenerator,
}); });
@ -47,9 +47,10 @@ async function _render(child: any): Promise<any> {
} }
export class AstroComponent { export class AstroComponent {
private htmlParts: string[]; private htmlParts: TemplateStringsArray;
private expressions: TemplateStringsArray; private expressions: any[];
constructor(htmlParts: string[], expressions: TemplateStringsArray) {
constructor(htmlParts: TemplateStringsArray, expressions: any[]) {
this.htmlParts = htmlParts; this.htmlParts = htmlParts;
this.expressions = expressions; this.expressions = expressions;
} }
@ -67,7 +68,7 @@ export class AstroComponent {
} }
} }
export function render(htmlParts: string[], ...expressions: TemplateStringsArray) { export async function render(htmlParts: TemplateStringsArray, ...expressions: any[]) {
return new AstroComponent(htmlParts, expressions); return new AstroComponent(htmlParts, expressions);
} }
@ -162,11 +163,10 @@ export const renderComponent = async (result: any, displayName: string, Componen
const { hydrationDirective, props } = extractHydrationDirectives(_props); const { hydrationDirective, props } = extractHydrationDirectives(_props);
let html = ''; let html = '';
if (!hydrationDirective) { if (hydrationDirective) {
return '<pre>Not implemented</pre>'; metadata.hydrate = hydrationDirective[0] as AstroComponentMetadata['hydrate'];
metadata.hydrateArgs = hydrationDirective[1];
} }
metadata.hydrate = hydrationDirective[0] as AstroComponentMetadata['hydrate'];
metadata.hydrateArgs = hydrationDirective[1];
for (const [url, exported] of Object.entries(result._metadata.importedModules)) { for (const [url, exported] of Object.entries(result._metadata.importedModules)) {
for (const [key, value] of Object.entries(exported as any)) { for (const [key, value] of Object.entries(exported as any)) {
@ -186,6 +186,11 @@ export const renderComponent = async (result: any, displayName: string, Componen
} }
({ html } = await renderer.ssr.renderToStaticMarkup(Component, props, null)); ({ html } = await renderer.ssr.renderToStaticMarkup(Component, props, null));
if (!hydrationDirective) {
return html;
}
const astroId = shorthash.unique(html); const astroId = shorthash.unique(html);
result.scripts.add(await generateHydrateScript({ renderer, astroId, props }, metadata as Required<AstroComponentMetadata>)); result.scripts.add(await generateHydrateScript({ renderer, astroId, props }, metadata as Required<AstroComponentMetadata>));

View file

@ -21,6 +21,6 @@ export async function renderToString(result: any, componentFactory: AstroCompone
export async function renderPage(result: any, Component: AstroComponentFactory, props: any, children: any) { export async function renderPage(result: any, Component: AstroComponentFactory, props: any, children: any) {
const template = await renderToString(result, Component, props, children); const template = await renderToString(result, Component, props, children);
const styles = Array.from(result.styles).map((style) => `<style>${style}</style>`); const styles = Array.from(result.styles).map((style) => `<style>${style}</style>`);
const scripts = Array.from(result.scripts).map((script) => `<script type="module">${script}</script>`); const scripts = Array.from(result.scripts);
return template.replace('</head>', styles.join('\n') + scripts.join('\n') + '</head>'); return template.replace('</head>', styles.join('\n') + scripts.join('\n') + '</head>');
} }

View file

@ -3,7 +3,7 @@ import { map } from 'unist-util-map';
const MDX_ELEMENTS = new Set(['mdxJsxFlowElement', 'mdxJsxTextElement']); const MDX_ELEMENTS = new Set(['mdxJsxFlowElement', 'mdxJsxTextElement']);
export default function rehypeJsx(): any { export default function rehypeJsx(): any {
return function (node: any): any { return function (node: any): any {
return map(node, (child) => { return map(node, (child: any) => {
if (child.type === 'element') { if (child.type === 'element') {
return { ...child, tagName: `${child.tagName}` } return { ...child, tagName: `${child.tagName}` }
} }
@ -12,7 +12,7 @@ export default function rehypeJsx(): any {
...child, ...child,
type: 'element', type: 'element',
tagName: `${child.name}`, tagName: `${child.name}`,
properties: child.attributes.reduce((acc, entry) => { properties: child.attributes.reduce((acc: any[], entry: any) => {
let attr = entry.value; let attr = entry.value;
if (attr && typeof attr === 'object') { if (attr && typeof attr === 'object') {
attr = `{${attr.value}}` attr = `{${attr.value}}`

View file

@ -1,5 +1,5 @@
{ {
"extends": "../../tsconfig.base.json", "extends": "../../../tsconfig.base.json",
"include": ["src"], "include": ["src"],
"compilerOptions": { "compilerOptions": {
"allowJs": true, "allowJs": true,

2179
yarn.lock

File diff suppressed because it is too large Load diff