astro/packages/integrations/netlify/src/shared.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

146 lines
3.4 KiB
TypeScript
Raw Normal View History

import type { AstroConfig, RouteData } from 'astro';
import fs from 'fs';
type RedirectDefinition = {
dynamic: boolean;
input: string;
target: string;
weight: 0 | 1;
status: 200 | 404;
};
export async function createRedirects(
config: AstroConfig,
2022-05-11 15:14:43 +00:00
routes: RouteData[],
dir: URL,
entryFile: string,
type: 'functions' | 'edge-functions' | 'builders'
2022-05-11 15:14:43 +00:00
) {
const _redirectsURL = new URL('./_redirects', dir);
const kind = type ?? 'functions';
const definitions: RedirectDefinition[] = [];
2022-05-11 15:14:43 +00:00
for (const route of routes) {
if (route.pathname) {
Experimental Prerender API (#5297) * wip: hybrid output * wip: hybrid output mvp * refactor: move hybrid => server * wip: hybrid support for `output: 'server'` * feat(hybrid): overwrite static files * fix: update static build * feat(hybrid): skip page generation if no static entrypoints * feat: migrate from hybrid output => prerender flag * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: improve static cleanup * attempt: avoid preprocess scanning * hack: force generated .js files to be treated as ESM * better handling for astro metadata * fix: update scanner plugin * fix: page name bug * fix: keep ssr false when generating pages * fix: force output to be treated as ESM * fix: client output should respect buildConfig * fix: ensure outDir is always created * fix: do not replace files with noop * fix(netlify): add support for `experimental_prerender` pages * feat: switch to `experimental_prerender` * chore: update es-module-lexer code in test * feat: improved code-splitting, cleanup * feat: move prerender behind flag * test: prerender * test: update prerender test * chore: update lockfile * fix: only match `.html` files when resolving assets * chore: update changeset * chore: remove ESM hack * chore: allow `--experimental-prerender` flag, move `--experimental-error-overlay` into subobject * chore: update changeset * test(vite-plugin-scanner): add proper unit tests for vite-plugin-scanner * chore: remove leftover code * chore: add comment on cleanup task * refactor: move manual chunks logic to vite-plugin-prerender * fix: do not support let declarations * test: add var test * refactor: prefer existing util * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/core/errors/errors-data.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
2022-12-16 16:38:37 +00:00
if (route.distURL) {
definitions.push({
dynamic: false,
input: route.pathname,
target: prependForwardSlash(route.distURL.toString().replace(dir.toString(), '')),
status: 200,
2023-01-23 14:49:20 +00:00
weight: 1,
});
Experimental Prerender API (#5297) * wip: hybrid output * wip: hybrid output mvp * refactor: move hybrid => server * wip: hybrid support for `output: 'server'` * feat(hybrid): overwrite static files * fix: update static build * feat(hybrid): skip page generation if no static entrypoints * feat: migrate from hybrid output => prerender flag * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: improve static cleanup * attempt: avoid preprocess scanning * hack: force generated .js files to be treated as ESM * better handling for astro metadata * fix: update scanner plugin * fix: page name bug * fix: keep ssr false when generating pages * fix: force output to be treated as ESM * fix: client output should respect buildConfig * fix: ensure outDir is always created * fix: do not replace files with noop * fix(netlify): add support for `experimental_prerender` pages * feat: switch to `experimental_prerender` * chore: update es-module-lexer code in test * feat: improved code-splitting, cleanup * feat: move prerender behind flag * test: prerender * test: update prerender test * chore: update lockfile * fix: only match `.html` files when resolving assets * chore: update changeset * chore: remove ESM hack * chore: allow `--experimental-prerender` flag, move `--experimental-error-overlay` into subobject * chore: update changeset * test(vite-plugin-scanner): add proper unit tests for vite-plugin-scanner * chore: remove leftover code * chore: add comment on cleanup task * refactor: move manual chunks logic to vite-plugin-prerender * fix: do not support let declarations * test: add var test * refactor: prefer existing util * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/core/errors/errors-data.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
2022-12-16 16:38:37 +00:00
} else {
definitions.push({
dynamic: false,
input: route.pathname,
target: `/.netlify/${kind}/${entryFile}`,
status: 200,
weight: 1,
});
Experimental Prerender API (#5297) * wip: hybrid output * wip: hybrid output mvp * refactor: move hybrid => server * wip: hybrid support for `output: 'server'` * feat(hybrid): overwrite static files * fix: update static build * feat(hybrid): skip page generation if no static entrypoints * feat: migrate from hybrid output => prerender flag * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: improve static cleanup * attempt: avoid preprocess scanning * hack: force generated .js files to be treated as ESM * better handling for astro metadata * fix: update scanner plugin * fix: page name bug * fix: keep ssr false when generating pages * fix: force output to be treated as ESM * fix: client output should respect buildConfig * fix: ensure outDir is always created * fix: do not replace files with noop * fix(netlify): add support for `experimental_prerender` pages * feat: switch to `experimental_prerender` * chore: update es-module-lexer code in test * feat: improved code-splitting, cleanup * feat: move prerender behind flag * test: prerender * test: update prerender test * chore: update lockfile * fix: only match `.html` files when resolving assets * chore: update changeset * chore: remove ESM hack * chore: allow `--experimental-prerender` flag, move `--experimental-error-overlay` into subobject * chore: update changeset * test(vite-plugin-scanner): add proper unit tests for vite-plugin-scanner * chore: remove leftover code * chore: add comment on cleanup task * refactor: move manual chunks logic to vite-plugin-prerender * fix: do not support let declarations * test: add var test * refactor: prefer existing util * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/core/errors/errors-data.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
2022-12-16 16:38:37 +00:00
if (route.route === '/404') {
definitions.push({
dynamic: true,
input: '/*',
target: `/.netlify/${kind}/${entryFile}`,
status: 404,
2023-01-23 14:49:20 +00:00
weight: 0,
});
Experimental Prerender API (#5297) * wip: hybrid output * wip: hybrid output mvp * refactor: move hybrid => server * wip: hybrid support for `output: 'server'` * feat(hybrid): overwrite static files * fix: update static build * feat(hybrid): skip page generation if no static entrypoints * feat: migrate from hybrid output => prerender flag * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: improve static cleanup * attempt: avoid preprocess scanning * hack: force generated .js files to be treated as ESM * better handling for astro metadata * fix: update scanner plugin * fix: page name bug * fix: keep ssr false when generating pages * fix: force output to be treated as ESM * fix: client output should respect buildConfig * fix: ensure outDir is always created * fix: do not replace files with noop * fix(netlify): add support for `experimental_prerender` pages * feat: switch to `experimental_prerender` * chore: update es-module-lexer code in test * feat: improved code-splitting, cleanup * feat: move prerender behind flag * test: prerender * test: update prerender test * chore: update lockfile * fix: only match `.html` files when resolving assets * chore: update changeset * chore: remove ESM hack * chore: allow `--experimental-prerender` flag, move `--experimental-error-overlay` into subobject * chore: update changeset * test(vite-plugin-scanner): add proper unit tests for vite-plugin-scanner * chore: remove leftover code * chore: add comment on cleanup task * refactor: move manual chunks logic to vite-plugin-prerender * fix: do not support let declarations * test: add var test * refactor: prefer existing util * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/core/errors/errors-data.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
2022-12-16 16:38:37 +00:00
}
}
2022-05-11 15:14:43 +00:00
} else {
const pattern =
2023-01-23 14:49:20 +00:00
'/' +
route.segments
.map(([part]) => {
//(part.dynamic ? '*' : part.content)
if (part.dynamic) {
if (part.spread) {
return '*';
} else {
return ':' + part.content;
}
} else {
2023-01-23 14:49:20 +00:00
return part.content;
}
2023-01-23 14:49:20 +00:00
})
.join('/');
Experimental Prerender API (#5297) * wip: hybrid output * wip: hybrid output mvp * refactor: move hybrid => server * wip: hybrid support for `output: 'server'` * feat(hybrid): overwrite static files * fix: update static build * feat(hybrid): skip page generation if no static entrypoints * feat: migrate from hybrid output => prerender flag * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: improve static cleanup * attempt: avoid preprocess scanning * hack: force generated .js files to be treated as ESM * better handling for astro metadata * fix: update scanner plugin * fix: page name bug * fix: keep ssr false when generating pages * fix: force output to be treated as ESM * fix: client output should respect buildConfig * fix: ensure outDir is always created * fix: do not replace files with noop * fix(netlify): add support for `experimental_prerender` pages * feat: switch to `experimental_prerender` * chore: update es-module-lexer code in test * feat: improved code-splitting, cleanup * feat: move prerender behind flag * test: prerender * test: update prerender test * chore: update lockfile * fix: only match `.html` files when resolving assets * chore: update changeset * chore: remove ESM hack * chore: allow `--experimental-prerender` flag, move `--experimental-error-overlay` into subobject * chore: update changeset * test(vite-plugin-scanner): add proper unit tests for vite-plugin-scanner * chore: remove leftover code * chore: add comment on cleanup task * refactor: move manual chunks logic to vite-plugin-prerender * fix: do not support let declarations * test: add var test * refactor: prefer existing util * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/core/errors/errors-data.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
2022-12-16 16:38:37 +00:00
if (route.distURL) {
2023-01-23 14:49:20 +00:00
const target =
`${pattern}` + (config.build.format === 'directory' ? '/index.html' : '.html');
definitions.push({
dynamic: true,
input: pattern,
target,
status: 200,
2023-01-23 14:49:20 +00:00
weight: 1,
});
Experimental Prerender API (#5297) * wip: hybrid output * wip: hybrid output mvp * refactor: move hybrid => server * wip: hybrid support for `output: 'server'` * feat(hybrid): overwrite static files * fix: update static build * feat(hybrid): skip page generation if no static entrypoints * feat: migrate from hybrid output => prerender flag * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: improve static cleanup * attempt: avoid preprocess scanning * hack: force generated .js files to be treated as ESM * better handling for astro metadata * fix: update scanner plugin * fix: page name bug * fix: keep ssr false when generating pages * fix: force output to be treated as ESM * fix: client output should respect buildConfig * fix: ensure outDir is always created * fix: do not replace files with noop * fix(netlify): add support for `experimental_prerender` pages * feat: switch to `experimental_prerender` * chore: update es-module-lexer code in test * feat: improved code-splitting, cleanup * feat: move prerender behind flag * test: prerender * test: update prerender test * chore: update lockfile * fix: only match `.html` files when resolving assets * chore: update changeset * chore: remove ESM hack * chore: allow `--experimental-prerender` flag, move `--experimental-error-overlay` into subobject * chore: update changeset * test(vite-plugin-scanner): add proper unit tests for vite-plugin-scanner * chore: remove leftover code * chore: add comment on cleanup task * refactor: move manual chunks logic to vite-plugin-prerender * fix: do not support let declarations * test: add var test * refactor: prefer existing util * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/core/errors/errors-data.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
2022-12-16 16:38:37 +00:00
} else {
definitions.push({
dynamic: true,
input: pattern,
target: `/.netlify/${kind}/${entryFile}`,
status: 200,
2023-01-23 14:49:20 +00:00
weight: 1,
});
Experimental Prerender API (#5297) * wip: hybrid output * wip: hybrid output mvp * refactor: move hybrid => server * wip: hybrid support for `output: 'server'` * feat(hybrid): overwrite static files * fix: update static build * feat(hybrid): skip page generation if no static entrypoints * feat: migrate from hybrid output => prerender flag * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: appease typescript * fix: improve static cleanup * attempt: avoid preprocess scanning * hack: force generated .js files to be treated as ESM * better handling for astro metadata * fix: update scanner plugin * fix: page name bug * fix: keep ssr false when generating pages * fix: force output to be treated as ESM * fix: client output should respect buildConfig * fix: ensure outDir is always created * fix: do not replace files with noop * fix(netlify): add support for `experimental_prerender` pages * feat: switch to `experimental_prerender` * chore: update es-module-lexer code in test * feat: improved code-splitting, cleanup * feat: move prerender behind flag * test: prerender * test: update prerender test * chore: update lockfile * fix: only match `.html` files when resolving assets * chore: update changeset * chore: remove ESM hack * chore: allow `--experimental-prerender` flag, move `--experimental-error-overlay` into subobject * chore: update changeset * test(vite-plugin-scanner): add proper unit tests for vite-plugin-scanner * chore: remove leftover code * chore: add comment on cleanup task * refactor: move manual chunks logic to vite-plugin-prerender * fix: do not support let declarations * test: add var test * refactor: prefer existing util * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/core/errors/errors-data.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/astro/src/@types/astro.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
2022-12-16 16:38:37 +00:00
}
2022-05-11 15:14:43 +00:00
}
}
let _redirects = prettify(definitions);
2022-05-11 15:14:43 +00:00
// Always use appendFile() because the redirects file could already exist,
// e.g. due to a `/public/_redirects` file that got copied to the output dir.
// If the file does not exist yet, appendFile() automatically creates it.
await fs.promises.appendFile(_redirectsURL, _redirects, 'utf-8');
}
function prettify(definitions: RedirectDefinition[]) {
2023-01-23 14:49:20 +00:00
let minInputLength = 0,
minTargetLength = 0;
definitions.sort((a, b) => {
// Find the longest input, so we can format things nicely
2023-01-23 14:49:20 +00:00
if (a.input.length > minInputLength) {
minInputLength = a.input.length;
}
2023-01-23 14:49:20 +00:00
if (b.input.length > minInputLength) {
minInputLength = b.input.length;
}
// Same for the target
2023-01-23 14:49:20 +00:00
if (a.target.length > minTargetLength) {
minTargetLength = a.target.length;
}
2023-01-23 14:49:20 +00:00
if (b.target.length > minTargetLength) {
minTargetLength = b.target.length;
}
// Sort dynamic routes on top
return b.weight - a.weight;
});
let _redirects = '';
// Loop over the definitions
definitions.forEach((defn, i) => {
// Figure out the number of spaces to add. We want at least 4 spaces
// after the input. This ensure that all targets line up together.
2023-01-23 14:49:20 +00:00
let inputSpaces = minInputLength - defn.input.length + 4;
let targetSpaces = minTargetLength - defn.target.length + 4;
_redirects +=
(i === 0 ? '' : '\n') +
defn.input +
' '.repeat(inputSpaces) +
defn.target +
' '.repeat(Math.abs(targetSpaces)) +
defn.status;
});
return _redirects;
}
function prependForwardSlash(str: string) {
return str[0] === '/' ? str : '/' + str;
}