Serialize route generation (#3354)
This commit is contained in:
parent
9481a3c08d
commit
4ac792a02d
5 changed files with 61 additions and 59 deletions
|
@ -974,6 +974,9 @@ export interface RouteData {
|
||||||
export type SerializedRouteData = Omit<RouteData, 'generate' | 'pattern'> & {
|
export type SerializedRouteData = Omit<RouteData, 'generate' | 'pattern'> & {
|
||||||
generate: undefined;
|
generate: undefined;
|
||||||
pattern: string;
|
pattern: string;
|
||||||
|
_meta: {
|
||||||
|
trailingSlash: AstroConfig['trailingSlash'];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RuntimeMode = 'development' | 'production';
|
export type RuntimeMode = 'development' | 'production';
|
||||||
|
|
|
@ -115,7 +115,7 @@ function buildManifest(
|
||||||
.filter((script) => script.stage === 'head-inline')
|
.filter((script) => script.stage === 'head-inline')
|
||||||
.map(({ stage, content }) => ({ stage, children: content })),
|
.map(({ stage, content }) => ({ stage, children: content })),
|
||||||
],
|
],
|
||||||
routeData: serializeRouteData(pageData.route),
|
routeData: serializeRouteData(pageData.route, astroConfig.trailingSlash),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ import type { LogOptions } from '../../logger/core';
|
||||||
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { compile } from 'path-to-regexp';
|
|
||||||
import slash from 'slash';
|
import slash from 'slash';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { warn } from '../../logger/core.js';
|
import { warn } from '../../logger/core.js';
|
||||||
import { resolvePages } from '../../util.js';
|
import { resolvePages } from '../../util.js';
|
||||||
|
import { getRouteGenerator } from './generator.js';
|
||||||
|
|
||||||
interface Item {
|
interface Item {
|
||||||
basename: string;
|
basename: string;
|
||||||
|
@ -88,34 +88,6 @@ function getTrailingSlashPattern(addTrailingSlash: AstroConfig['trailingSlash'])
|
||||||
return '\\/?$';
|
return '\\/?$';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGenerator(segments: RoutePart[][], addTrailingSlash: AstroConfig['trailingSlash']) {
|
|
||||||
const template = segments
|
|
||||||
.map((segment) => {
|
|
||||||
return segment[0].spread
|
|
||||||
? `/:${segment[0].content.slice(3)}(.*)?`
|
|
||||||
: '/' +
|
|
||||||
segment
|
|
||||||
.map((part) => {
|
|
||||||
if (part)
|
|
||||||
return part.dynamic
|
|
||||||
? `:${part.content}`
|
|
||||||
: part.content
|
|
||||||
.normalize()
|
|
||||||
.replace(/\?/g, '%3F')
|
|
||||||
.replace(/#/g, '%23')
|
|
||||||
.replace(/%5B/g, '[')
|
|
||||||
.replace(/%5D/g, ']')
|
|
||||||
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
||||||
})
|
|
||||||
.join('');
|
|
||||||
})
|
|
||||||
.join('');
|
|
||||||
|
|
||||||
const trailing = addTrailingSlash !== 'never' && segments.length ? '/' : '';
|
|
||||||
const toPath = compile(template + trailing);
|
|
||||||
return toPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSpread(str: string) {
|
function isSpread(str: string) {
|
||||||
const spreadPattern = /\[\.{3}/g;
|
const spreadPattern = /\[\.{3}/g;
|
||||||
return spreadPattern.test(str);
|
return spreadPattern.test(str);
|
||||||
|
@ -271,7 +243,7 @@ export function createRouteManifest(
|
||||||
const component = item.file;
|
const component = item.file;
|
||||||
const trailingSlash = item.isPage ? config.trailingSlash : 'never';
|
const trailingSlash = item.isPage ? config.trailingSlash : 'never';
|
||||||
const pattern = getPattern(segments, trailingSlash);
|
const pattern = getPattern(segments, trailingSlash);
|
||||||
const generate = getGenerator(segments, trailingSlash);
|
const generate = getRouteGenerator(segments, trailingSlash);
|
||||||
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic)
|
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic)
|
||||||
? `/${segments.map((segment) => segment[0].content).join('/')}`
|
? `/${segments.map((segment) => segment[0].content).join('/')}`
|
||||||
: null;
|
: null;
|
||||||
|
|
34
packages/astro/src/core/routing/manifest/generator.ts
Normal file
34
packages/astro/src/core/routing/manifest/generator.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import type { AstroConfig, RoutePart } from '../../../@types/astro';
|
||||||
|
|
||||||
|
import { compile } from 'path-to-regexp';
|
||||||
|
|
||||||
|
export function getRouteGenerator(
|
||||||
|
segments: RoutePart[][],
|
||||||
|
addTrailingSlash: AstroConfig['trailingSlash']
|
||||||
|
) {
|
||||||
|
const template = segments
|
||||||
|
.map((segment) => {
|
||||||
|
return segment[0].spread
|
||||||
|
? `/:${segment[0].content.slice(3)}(.*)?`
|
||||||
|
: '/' +
|
||||||
|
segment
|
||||||
|
.map((part) => {
|
||||||
|
if (part)
|
||||||
|
return part.dynamic
|
||||||
|
? `:${part.content}`
|
||||||
|
: part.content
|
||||||
|
.normalize()
|
||||||
|
.replace(/\?/g, '%3F')
|
||||||
|
.replace(/#/g, '%23')
|
||||||
|
.replace(/%5B/g, '[')
|
||||||
|
.replace(/%5D/g, ']')
|
||||||
|
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
const trailing = addTrailingSlash !== 'never' && segments.length ? '/' : '';
|
||||||
|
const toPath = compile(template + trailing);
|
||||||
|
return toPath;
|
||||||
|
}
|
|
@ -1,34 +1,27 @@
|
||||||
import type { RouteData, SerializedRouteData, RoutePart } from '../../../@types/astro';
|
import type { RouteData, SerializedRouteData, AstroConfig } from '../../../@types/astro';
|
||||||
|
|
||||||
function createRouteData(
|
import { getRouteGenerator } from './generator.js';
|
||||||
pattern: RegExp,
|
|
||||||
params: string[],
|
export function serializeRouteData(
|
||||||
component: string,
|
routeData: RouteData,
|
||||||
pathname: string | undefined,
|
trailingSlash: AstroConfig['trailingSlash']
|
||||||
type: 'page' | 'endpoint',
|
): SerializedRouteData {
|
||||||
segments: RoutePart[][]
|
|
||||||
): RouteData {
|
|
||||||
return {
|
return {
|
||||||
type,
|
...routeData,
|
||||||
pattern,
|
generate: undefined,
|
||||||
params,
|
pattern: routeData.pattern.source,
|
||||||
component,
|
_meta: { trailingSlash },
|
||||||
// TODO bring back
|
|
||||||
generate: () => '',
|
|
||||||
pathname: pathname || undefined,
|
|
||||||
segments,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serializeRouteData(routeData: RouteData): SerializedRouteData {
|
export function deserializeRouteData(rawRouteData: SerializedRouteData): RouteData {
|
||||||
// Is there a better way to do this in TypeScript?
|
return {
|
||||||
const outRouteData = routeData as unknown as SerializedRouteData;
|
type: rawRouteData.type,
|
||||||
outRouteData.pattern = routeData.pattern.source;
|
pattern: new RegExp(rawRouteData.pattern),
|
||||||
return outRouteData;
|
params: rawRouteData.params,
|
||||||
}
|
component: rawRouteData.component,
|
||||||
|
generate: getRouteGenerator(rawRouteData.segments, rawRouteData._meta.trailingSlash),
|
||||||
export function deserializeRouteData(rawRouteData: SerializedRouteData) {
|
pathname: rawRouteData.pathname || undefined,
|
||||||
const { component, params, pathname, type, segments } = rawRouteData;
|
segments: rawRouteData.segments,
|
||||||
const pattern = new RegExp(rawRouteData.pattern);
|
};
|
||||||
return createRouteData(pattern, params, component, pathname, type, segments);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue