Implement support for redirects config in the Vercel adapter
This commit is contained in:
parent
11a517b1f1
commit
b8ef648f8c
8 changed files with 148 additions and 20 deletions
|
@ -177,7 +177,7 @@ async function generatePage(
|
||||||
if(pageData.route.redirectRoute) {
|
if(pageData.route.redirectRoute) {
|
||||||
pageModulePromise = ssrEntry.pageMap?.get(pageData.route.redirectRoute!.component);
|
pageModulePromise = ssrEntry.pageMap?.get(pageData.route.redirectRoute!.component);
|
||||||
} else {
|
} else {
|
||||||
pageModulePromise = { default: () => {} } as any;
|
pageModulePromise = () => Promise.resolve<any>({ default: () => {} });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!pageModulePromise) {
|
if (!pageModulePromise) {
|
||||||
|
|
|
@ -36,6 +36,10 @@ function getMatchPattern(segments: RoutePart[][]) {
|
||||||
.join('');
|
.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function appendTrailingSlash(route: string): string {
|
||||||
|
return route.at(-1) === '/' ? route : route + '/';
|
||||||
|
}
|
||||||
|
|
||||||
function getReplacePattern(segments: RoutePart[][]) {
|
function getReplacePattern(segments: RoutePart[][]) {
|
||||||
let n = 0;
|
let n = 0;
|
||||||
let result = '';
|
let result = '';
|
||||||
|
@ -54,28 +58,44 @@ function getReplacePattern(segments: RoutePart[][]) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRedirectLocation(route: RouteData, config: AstroConfig): string {
|
||||||
|
if(route.redirectRoute) {
|
||||||
|
const pattern = getReplacePattern(route.redirectRoute.segments);
|
||||||
|
const path = (config.trailingSlash === 'always' ? appendTrailingSlash(pattern) : pattern);
|
||||||
|
return config.base + path;
|
||||||
|
} else {
|
||||||
|
return config.base + route.redirect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getRedirects(routes: RouteData[], config: AstroConfig): VercelRoute[] {
|
export function getRedirects(routes: RouteData[], config: AstroConfig): VercelRoute[] {
|
||||||
let redirects: VercelRoute[] = [];
|
let redirects: VercelRoute[] = [];
|
||||||
|
|
||||||
if (config.trailingSlash === 'always') {
|
for(const route of routes) {
|
||||||
for (const route of routes) {
|
if(route.type === 'redirect') {
|
||||||
if (route.type !== 'page' || route.segments.length === 0) continue;
|
if(true || route.pathname) {
|
||||||
|
redirects.push({
|
||||||
redirects.push({
|
src: config.base + getMatchPattern(route.segments),
|
||||||
src: config.base + getMatchPattern(route.segments),
|
headers: { Location: getRedirectLocation(route, config) },
|
||||||
headers: { Location: config.base + getReplacePattern(route.segments) + '/' },
|
status: 301
|
||||||
status: 308,
|
})
|
||||||
});
|
} else {
|
||||||
}
|
console.error(`Dynamic routes not yet supported`);
|
||||||
} else if (config.trailingSlash === 'never') {
|
}
|
||||||
for (const route of routes) {
|
} else if (route.type === 'page') {
|
||||||
if (route.type !== 'page' || route.segments.length === 0) continue;
|
if (config.trailingSlash === 'always') {
|
||||||
|
redirects.push({
|
||||||
redirects.push({
|
src: config.base + getMatchPattern(route.segments),
|
||||||
src: config.base + getMatchPattern(route.segments) + '/',
|
headers: { Location: config.base + getReplacePattern(route.segments) + '/' },
|
||||||
headers: { Location: config.base + getReplacePattern(route.segments) },
|
status: 308,
|
||||||
status: 308,
|
});
|
||||||
});
|
} else if (config.trailingSlash === 'never') {
|
||||||
|
redirects.push({
|
||||||
|
src: config.base + getMatchPattern(route.segments) + '/',
|
||||||
|
headers: { Location: config.base + getReplacePattern(route.segments) },
|
||||||
|
status: 308,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
packages/integrations/vercel/test/fixtures/redirects/astro.config.mjs
vendored
Normal file
9
packages/integrations/vercel/test/fixtures/redirects/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import vercel from '@astrojs/vercel/static';
|
||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
adapter: vercel({imageService: true}),
|
||||||
|
experimental: {
|
||||||
|
assets: true
|
||||||
|
}
|
||||||
|
});
|
9
packages/integrations/vercel/test/fixtures/redirects/package.json
vendored
Normal file
9
packages/integrations/vercel/test/fixtures/redirects/package.json
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"name": "@test/astro-vercel-redirects",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@astrojs/vercel": "workspace:*",
|
||||||
|
"astro": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
8
packages/integrations/vercel/test/fixtures/redirects/src/pages/index.astro
vendored
Normal file
8
packages/integrations/vercel/test/fixtures/redirects/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Testing</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Testing</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
25
packages/integrations/vercel/test/fixtures/redirects/src/pages/team/articles/[...slug].astro
vendored
Normal file
25
packages/integrations/vercel/test/fixtures/redirects/src/pages/team/articles/[...slug].astro
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
export const getStaticPaths = (async () => {
|
||||||
|
const posts = [
|
||||||
|
{ slug: 'one', data: {draft: false, title: 'One'} },
|
||||||
|
{ slug: 'two', data: {draft: false, title: 'Two'} }
|
||||||
|
];
|
||||||
|
return posts.map((post) => {
|
||||||
|
return {
|
||||||
|
params: { slug: post.slug },
|
||||||
|
props: { draft: post.data.draft, title: post.data.title },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
const { slug } = Astro.params;
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{ title }</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{ title }</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
48
packages/integrations/vercel/test/redirects.test.js
Normal file
48
packages/integrations/vercel/test/redirects.test.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import * as cheerio from 'cheerio';
|
||||||
|
import { loadFixture } from './test-utils.js';
|
||||||
|
|
||||||
|
describe('Redirects', () => {
|
||||||
|
/** @type {import('../../../astro/test/test-utils.js').Fixture} */
|
||||||
|
let fixture;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
fixture = await loadFixture({
|
||||||
|
root: './fixtures/redirects/',
|
||||||
|
redirects: {
|
||||||
|
'/one': '/',
|
||||||
|
'/two': '/',
|
||||||
|
'/blog/[...slug]': '/team/articles/[...slug]',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await fixture.build();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function getConfig() {
|
||||||
|
const json = await fixture.readFile('../.vercel/output/config.json');
|
||||||
|
const config = JSON.parse(json);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
it('define static routes', async () => {
|
||||||
|
const config = await getConfig();
|
||||||
|
|
||||||
|
const oneRoute = config.routes.find(r => r.src === '/\\/one');
|
||||||
|
expect(oneRoute.headers.Location).to.equal('/');
|
||||||
|
expect(oneRoute.status).to.equal(301);
|
||||||
|
|
||||||
|
const twoRoute = config.routes.find(r => r.src === '/\\/one');
|
||||||
|
expect(twoRoute.headers.Location).to.equal('/');
|
||||||
|
expect(twoRoute.status).to.equal(301);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('defines dynamic routes', async () => {
|
||||||
|
const config = await getConfig();
|
||||||
|
|
||||||
|
const blogRoute = config.routes.find(r => r.src.startsWith('/\\/blog'));
|
||||||
|
expect(blogRoute).to.not.be.undefined;
|
||||||
|
expect(blogRoute.headers.Location.startsWith('/team/articles')).to.equal(true);
|
||||||
|
expect(blogRoute.status).to.equal(301);
|
||||||
|
});
|
||||||
|
});
|
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
|
@ -4868,6 +4868,15 @@ importers:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../../../../astro
|
version: link:../../../../../astro
|
||||||
|
|
||||||
|
packages/integrations/vercel/test/fixtures/redirects:
|
||||||
|
dependencies:
|
||||||
|
'@astrojs/vercel':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../..
|
||||||
|
astro:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../../../../astro
|
||||||
|
|
||||||
packages/integrations/vercel/test/fixtures/serverless-prerender:
|
packages/integrations/vercel/test/fixtures/serverless-prerender:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/vercel':
|
'@astrojs/vercel':
|
||||||
|
|
Loading…
Add table
Reference in a new issue