diff options
author | 2024-04-01 16:13:54 +0200 | |
---|---|---|
committer | 2024-04-01 16:13:54 +0200 | |
commit | f34e5a1b968f6f4ec1323eda74ba30445d524b98 (patch) | |
tree | fc26b475489f1d9c508cb61c18385be91dac695b /packages/integrations/cloudflare/src | |
parent | ce06156e9beda645d2ba60a5b4f3b9ce4db92e91 (diff) | |
download | astro-f34e5a1b968f6f4ec1323eda74ba30445d524b98.tar.gz astro-f34e5a1b968f6f4ec1323eda74ba30445d524b98.tar.zst astro-f34e5a1b968f6f4ec1323eda74ba30445d524b98.zip |
fix(cloudflare): routes generation logic (#217)
Diffstat (limited to 'packages/integrations/cloudflare/src')
-rw-r--r-- | packages/integrations/cloudflare/src/utils/generate-routes-json.ts | 126 |
1 files changed, 78 insertions, 48 deletions
diff --git a/packages/integrations/cloudflare/src/utils/generate-routes-json.ts b/packages/integrations/cloudflare/src/utils/generate-routes-json.ts index 39b5e5f83..2841e79eb 100644 --- a/packages/integrations/cloudflare/src/utils/generate-routes-json.ts +++ b/packages/integrations/cloudflare/src/utils/generate-routes-json.ts @@ -82,6 +82,7 @@ class TrieNode { class PathTrie { root: TrieNode; + returnHasWildcard = false; constructor() { this.root = new TrieNode(); @@ -112,6 +113,7 @@ class PathTrie { */ private dfs(node: TrieNode, path: string[], allPaths: string[][]): void { if (node.hasWildcardChild) { + this.returnHasWildcard = true; allPaths.push([...path, '*']); return; } @@ -125,10 +127,10 @@ class PathTrie { } } - getAllPaths(): string[][] { + getAllPaths(): [string[][], boolean] { const allPaths: string[][] = []; this.dfs(this.root, [], allPaths); - return allPaths; + return [allPaths, this.returnHasWildcard]; } } @@ -154,6 +156,44 @@ export async function createRoutesFile( const includePaths: string[][] = []; const excludePaths: string[][] = []; + /** + * All files in the `_config.build.assets` path, e.g. `_astro` + * are considered static assets and should not be handled by the function + * therefore we exclude a wildcard for that, e.g. `/_astro/*` + */ + const assetsPath = segmentsToCfSyntax( + [ + [{ content: _config.build.assets, dynamic: false, spread: false }], + [{ content: '', dynamic: true, spread: false }], + ], + _config + ); + excludePaths.push(assetsPath); + + if (existsSync(fileURLToPath(_config.publicDir))) { + const staticFiles = await glob(`${fileURLToPath(_config.publicDir)}/**/*`, { + cwd: fileURLToPath(_config.publicDir), + filesOnly: true, + dot: true, + }); + for (const staticFile of staticFiles) { + if (['_headers', '_redirects', '_routes.json'].includes(staticFile)) continue; + const staticPath = staticFile; + + const segments = removeLeadingForwardSlash(staticPath) + .split(posix.sep) + .filter(Boolean) + .map((s: string) => { + return getParts(s); + }); + excludePaths.push(segmentsToCfSyntax(segments, _config)); + } + } + + for (const redirect of redirects) { + excludePaths.push(segmentsToCfSyntax(redirect, _config)); + } + let hasPrerendered404 = false; for (const route of routes) { const convertedPath = segmentsToCfSyntax(route.segments, _config); @@ -189,6 +229,7 @@ export async function createRoutesFile( } for (const page of pages) { + if (page.pathname === '404') hasPrerendered404 = true; const pageSegments = removeLeadingForwardSlash(page.pathname) .split(posix.sep) .filter(Boolean) @@ -198,65 +239,46 @@ export async function createRoutesFile( excludePaths.push(segmentsToCfSyntax(pageSegments, _config)); } - if (existsSync(fileURLToPath(_config.publicDir))) { - const staticFiles = await glob(`${fileURLToPath(_config.publicDir)}/**/*`, { - cwd: fileURLToPath(_config.publicDir), - filesOnly: true, - dot: true, - }); - for (const staticFile of staticFiles) { - if (['_headers', '_redirects', '_routes.json'].includes(staticFile)) continue; - const staticPath = staticFile; - - const segments = removeLeadingForwardSlash(staticPath) - .split(posix.sep) - .filter(Boolean) - .map((s: string) => { - return getParts(s); - }); - excludePaths.push(segmentsToCfSyntax(segments, _config)); - } - } - - /** - * All files in the `_config.build.assets` path, e.g. `_astro` - * are considered static assets and should not be handled by the function - * therefore we exclude a wildcard for that, e.g. `/_astro/*` - */ - const assetsPath = segmentsToCfSyntax( - [ - [{ content: _config.build.assets, dynamic: false, spread: false }], - [{ content: '', dynamic: true, spread: false }], - ], - _config - ); - excludePaths.push(assetsPath); - - for (const redirect of redirects) { - excludePaths.push(segmentsToCfSyntax(redirect, _config)); - } - const includeTrie = new PathTrie(); for (const includePath of includePaths) { includeTrie.insert(includePath); } - const deduplicatedIncludePaths = includeTrie.getAllPaths(); + const [deduplicatedIncludePaths, includedPathsHaveWildcard] = includeTrie.getAllPaths(); const excludeTrie = new PathTrie(); for (const excludePath of excludePaths) { + /** + * A excludePath with starts with a wildcard (*) is a catch-all + * that would mean all routes are static, that would be equal to a full SSG project + * the adapter is not needed in this case, so we do not consider such paths + */ + if (excludePath[0] === '*') continue; excludeTrie.insert(excludePath); } - const deduplicatedExcludePaths = excludeTrie.getAllPaths(); + const [deduplicatedExcludePaths, _excludedPathsHaveWildcard] = excludeTrie.getAllPaths(); /** * Cloudflare allows no more than 100 include/exclude rules combined * https://developers.cloudflare.com/pages/functions/routing/#limits */ const CLOUDFLARE_COMBINED_LIMIT = 100; + /** + * Caluclate the number of automated and extended include rules + */ + const AUTOMATIC_INCLUDE_RULES_COUNT = deduplicatedIncludePaths.length; + const EXTENDED_INCLUDE_RULES_COUNT = includeExtends?.length ?? 0; + const INCLUDE_RULES_COUNT = AUTOMATIC_INCLUDE_RULES_COUNT + EXTENDED_INCLUDE_RULES_COUNT; + /** + * Caluclate the number of automated and extended exclude rules + */ + const AUTOMATIC_EXCLUDE_RULES_COUNT = deduplicatedExcludePaths.length; + const EXTENDED_EXCLUDE_RULES_COUNT = excludeExtends?.length ?? 0; + const EXCLUDE_RULES_COUNT = AUTOMATIC_EXCLUDE_RULES_COUNT + EXTENDED_EXCLUDE_RULES_COUNT; + if ( !hasPrerendered404 || - deduplicatedIncludePaths.length + (includeExtends?.length ?? 0) > CLOUDFLARE_COMBINED_LIMIT || - deduplicatedExcludePaths.length + (excludeExtends?.length ?? 0) > CLOUDFLARE_COMBINED_LIMIT + INCLUDE_RULES_COUNT > CLOUDFLARE_COMBINED_LIMIT || + EXCLUDE_RULES_COUNT > CLOUDFLARE_COMBINED_LIMIT ) { await writeRoutesFileToOutDir( _config, @@ -264,8 +286,14 @@ export async function createRoutesFile( ['/*'].concat(includeExtends?.map((entry) => entry.pattern) ?? []), deduplicatedExcludePaths .map((path) => `${prependForwardSlash(path.join('/'))}`) + .slice( + 0, + CLOUDFLARE_COMBINED_LIMIT - + EXTENDED_INCLUDE_RULES_COUNT - + EXTENDED_EXCLUDE_RULES_COUNT - + 1 + ) .concat(excludeExtends?.map((entry) => entry.pattern) ?? []) - .slice(0, 99) ); } else { await writeRoutesFileToOutDir( @@ -274,9 +302,11 @@ export async function createRoutesFile( deduplicatedIncludePaths .map((path) => `${prependForwardSlash(path.join('/'))}`) .concat(includeExtends?.map((entry) => entry.pattern) ?? []), - deduplicatedExcludePaths - .map((path) => `${prependForwardSlash(path.join('/'))}`) - .concat(excludeExtends?.map((entry) => entry.pattern) ?? []) + includedPathsHaveWildcard + ? deduplicatedExcludePaths + .map((path) => `${prependForwardSlash(path.join('/'))}`) + .concat(excludeExtends?.map((entry) => entry.pattern) ?? []) + : [] ); } } |