Skip to content

Commit

Permalink
feat: support for _routes.json in the root dir (#402)
Browse files Browse the repository at this point in the history
  • Loading branch information
james-elicx authored Jul 25, 2023
1 parent eae9f6a commit ea98a8f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/green-lemons-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudflare/next-on-pages': minor
---

Support for defining an `_routes.json` file in the root of the project. Entries in the root's file are copied over to the generated one in the output directory.
45 changes: 41 additions & 4 deletions packages/next-on-pages/src/buildApplication/buildMetadataFiles.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { join } from 'path';
import { writeFile } from 'fs/promises';
import { nextOnPagesVersion } from '../utils';
import { nextOnPagesVersion, readJsonFile } from '../utils';
import { getPhaseRoutes, getVercelConfig } from './getVercelConfig';
import { cliError } from '../cli';

/**
* Builds metadata files needed for the worker to correctly run.
*
* @param outputDir Output directory for the metadata files.
* @param opts Options for building metadata files.
*/
export async function buildMetadataFiles(
outputDir: string,
Expand All @@ -16,6 +20,12 @@ export async function buildMetadataFiles(
]);
}

/**
* Builds the `_headers` file, which is used by Cloudflare to determine which headers to add to
* responses for routes that match the given pattern.
*
* @param outputDir Output directory for the metadata files.
*/
async function buildNextStaticHeaders(outputDir: string) {
const vercelConfig = await getVercelConfig();

Expand Down Expand Up @@ -44,19 +54,39 @@ ${Object.entries(nextStaticHeaders)
}
}

/**
* Builds the `_routes.json` file, which is used by Cloudflare to determine which routes should
* invoke the worker.
*
* Collects existing entries from the `_routes.json` file in the root of the project, if it exists.
*
* @param outputDir Output directory for the metadata files.
* @param opts Options for building metadata files.
*/
async function buildRoutes(outputDir: string, opts: BuildMetadataFilesOpts) {
const nextStaticPath = getNextStaticDirPath(opts);

const existingFile = await readJsonFile<RoutesJsonFile>('_routes.json');
if (existingFile && existingFile.version !== 1) {
cliError(
`Found _routes.json with version ${existingFile.version}, but only version 1 is supported.`,
);
process.exit(1);
}

const { include = [], exclude = [] } = existingFile ?? {};
const includeEntries = include.length > 0 ? include : ['/*'];
const excludeEntries = new Set([`${nextStaticPath}/*`, ...exclude]);

try {
await writeFile(
join(outputDir, '_routes.json'),
JSON.stringify({
version: 1,
description: `Built with @cloudflare/next-on-pages@${nextOnPagesVersion}.`,
include: ['/*'],
exclude: [`${nextStaticPath}/*`],
include: includeEntries,
exclude: [...excludeEntries],
}),
{ flag: 'ax' }, // don't generate file if it's already manually maintained
);
} catch (e) {
if ((e as { code?: string }).code !== 'EEXIST') {
Expand All @@ -65,6 +95,13 @@ async function buildRoutes(outputDir: string, opts: BuildMetadataFilesOpts) {
}
}

type RoutesJsonFile = {
version: 1;
description: string;
include: string[];
exclude: string[];
};

/**
* Finds the path to the `/_next/static` directory from the list of static assets. Accounts for the
* path being inside sub-directories, e.g. `/blog/_next/static`, and falls back to `/_next/static`.
Expand Down

0 comments on commit ea98a8f

Please sign in to comment.