From bf32cbfc5833a35b713bf8f8fb070289ddd39fc0 Mon Sep 17 00:00:00 2001 From: Gal Schlezinger Date: Tue, 27 Sep 2022 20:30:15 +0300 Subject: [PATCH] [edge] serialize custom config to middleware-manifest (#40881) This PR serializes `regions` into `middleware-manifest.json`, allowing to extend Edge Functions and Middleware for deployment providers. ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: Seiya Nuta Co-authored-by: JJ Kasper --- packages/next/build/analysis/get-page-static-info.ts | 11 ++++++++++- .../next/build/webpack/plugins/middleware-plugin.ts | 7 +++++++ test/e2e/middleware-general/app/middleware.js | 2 ++ .../app/pages/api/edge-search-params.js | 2 +- test/e2e/middleware-general/test/index.test.ts | 12 ++++++++++++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/next/build/analysis/get-page-static-info.ts b/packages/next/build/analysis/get-page-static-info.ts index 3e6c4de580e67..589eb59ffb270 100644 --- a/packages/next/build/analysis/get-page-static-info.ts +++ b/packages/next/build/analysis/get-page-static-info.ts @@ -18,6 +18,7 @@ import { RSC_MODULE_TYPES } from '../../shared/lib/constants' export interface MiddlewareConfig { matchers: MiddlewareMatcher[] unstable_allowDynamicGlobs: string[] + regions: string[] | string } export interface MiddlewareMatcher { @@ -184,6 +185,14 @@ function getMiddlewareConfig( result.matchers = getMiddlewareMatchers(config.matcher, nextConfig) } + if (typeof config.regions === 'string' || Array.isArray(config.regions)) { + result.regions = config.regions + } else if (typeof config.regions !== 'undefined') { + Log.warn( + `The \`regions\` config was ignored: config must be empty, a string or an array of strings. (${pageFilePath})` + ) + } + if (config.unstable_allowDynamic) { result.unstable_allowDynamicGlobs = Array.isArray( config.unstable_allowDynamic @@ -256,7 +265,7 @@ export async function getPageStaticInfo(params: { const fileContent = (await tryToReadFile(pageFilePath, !isDev)) || '' if ( - /runtime|getStaticProps|getServerSideProps|matcher|unstable_allowDynamic/.test( + /runtime|getStaticProps|getServerSideProps|export const config/.test( fileContent ) ) { diff --git a/packages/next/build/webpack/plugins/middleware-plugin.ts b/packages/next/build/webpack/plugins/middleware-plugin.ts index d87d9301b586a..0d2908a9e46a2 100644 --- a/packages/next/build/webpack/plugins/middleware-plugin.ts +++ b/packages/next/build/webpack/plugins/middleware-plugin.ts @@ -36,6 +36,7 @@ export interface EdgeFunctionDefinition { matchers: MiddlewareMatcher[] wasm?: AssetBinding[] assets?: AssetBinding[] + regions?: string[] | string } export interface MiddlewareManifest { @@ -52,6 +53,7 @@ interface EntryMetadata { env: Set wasmBindings: Map assetBindings: Map + regions?: string[] | string } const NAME = 'MiddlewarePlugin' @@ -178,6 +180,7 @@ function getCreateAssets(params: { name, filePath, })), + ...(metadata.regions && { regions: metadata.regions }), } if (metadata.edgeApiFunction || metadata.edgeSSR) { @@ -737,6 +740,10 @@ function getExtractMetadata(params: { } } + if (edgeFunctionConfig?.config?.regions) { + entryMetadata.regions = edgeFunctionConfig.config.regions + } + /** * The entry module has to be either a page or a middleware and hold * the corresponding metadata. diff --git a/test/e2e/middleware-general/app/middleware.js b/test/e2e/middleware-general/app/middleware.js index 5a5f2f903d019..54e5b196af44d 100644 --- a/test/e2e/middleware-general/app/middleware.js +++ b/test/e2e/middleware-general/app/middleware.js @@ -2,6 +2,8 @@ import { NextRequest, NextResponse, URLPattern } from 'next/server' import magicValue from 'shared-package' +export const config = { regions: 'auto' } + const PATTERNS = [ [ new URLPattern({ pathname: '/:locale/:id' }), diff --git a/test/e2e/middleware-general/app/pages/api/edge-search-params.js b/test/e2e/middleware-general/app/pages/api/edge-search-params.js index a67cecdf18ec0..01a968ee9d806 100644 --- a/test/e2e/middleware-general/app/pages/api/edge-search-params.js +++ b/test/e2e/middleware-general/app/pages/api/edge-search-params.js @@ -1,6 +1,6 @@ import { NextResponse } from 'next/server' -export const config = { runtime: 'experimental-edge' } +export const config = { runtime: 'experimental-edge', regions: 'default' } /** * @param {import('next/server').NextRequest} diff --git a/test/e2e/middleware-general/test/index.test.ts b/test/e2e/middleware-general/test/index.test.ts index 9e7587a889ee4..f1391d728769c 100644 --- a/test/e2e/middleware-general/test/index.test.ts +++ b/test/e2e/middleware-general/test/index.test.ts @@ -125,10 +125,22 @@ describe('Middleware Runtime', () => { matchers: [{ regexp: '^/.*$' }], wasm: [], assets: [], + regions: 'auto', }, }) }) + it('should have the custom config in the manifest', async () => { + const manifest = await fs.readJSON( + join(next.testDir, '.next/server/middleware-manifest.json') + ) + + expect(manifest.functions['/api/edge-search-params']).toHaveProperty( + 'regions', + 'default' + ) + }) + it('should have correct files in manifest', async () => { const manifest = await fs.readJSON( join(next.testDir, '.next/server/middleware-manifest.json')