Compare commits

..

5 Commits

Author SHA1 Message Date
Erika Rowland
2fa8af9136 minor change to test failure 2024-05-29 13:25:38 -07:00
Sean Massa
2090719c39 Merge branch 'endangeredmassa/reject-mismatch-corepack' of https://github.com/vercel/vercel into endangeredmassa/reject-mismatch-corepack 2024-05-15 18:34:39 -05:00
Sean Massa
11813250ce fix value used in error 2024-05-15 18:33:55 -05:00
Sean Massa
58bec9aa01 Create lemon-bears-talk.md 2024-05-15 17:08:35 -05:00
Sean Massa
dd199896ab reject mismatched corepack and detected package managers 2024-05-15 17:06:18 -05:00
208 changed files with 656 additions and 1602 deletions

View File

@@ -0,0 +1,2 @@
---
---

View File

@@ -0,0 +1,5 @@
---
"@vercel/build-utils": patch
---
reject mismatched corepack and detected package managers

View File

@@ -63,21 +63,16 @@ updates:
allow:
- dependency-name: '@remix-run*'
- dependency-name: '@shopify*'
- dependency-name: 'remix*'
ignore:
- dependency-name: '@remix-run*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
- dependency-name: 'remix*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
- dependency-name: '@shopify*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- 'remix*'
- '@remix-run*'
- '@shopify*'
update-types:

View File

@@ -99,7 +99,7 @@ jobs:
echo "misses=$TURBO_MISS_COUNT" >> $GITHUB_OUTPUT
- name: 'Upload Test Report to Datadog'
if: ${{ steps['turbo-summary'].outputs.misses != '0' && !cancelled() }}
run: 'npx @datadog/datadog-ci@2.36.0 junit upload --service vercel-cli .junit-reports'
run: 'npx @datadog/datadog-ci@2.18.1 junit upload --service vercel-cli .junit-reports'
env:
DATADOG_API_KEY: ${{secrets.DATADOG_API_KEY_CLI}}
DD_ENV: ci

View File

@@ -4,12 +4,6 @@
### Patch Changes
- examples: Update Astro template. ([#11687](https://github.com/vercel/vercel/pull/11687))
## null
### Patch Changes
- chore: update Nuxt example ([#10869](https://github.com/vercel/vercel/pull/10869))
## null

View File

@@ -1,6 +1,3 @@
# astro
.astro
# build output
dist/
.output/
@@ -14,6 +11,7 @@ yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production

View File

@@ -3,9 +3,10 @@
This directory is a brief example of an [Astro](https://astro.build/) site that can be deployed to Vercel with zero configuration. This demo showcases:
- `/` - A static page (pre-rendered)
- `/ssr` - A page that uses server-side rendering (through [Vercel Functions](https://vercel.com/docs/functions))
- `/ssr` - A page that uses server-side rendering (through [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions))
- `/ssr-with-swr-caching` - Similar to the previous page, but also caches the response on the [Vercel Edge Network](https://vercel.com/docs/edge-network/overview) using `cache-control` headers
- `/image` - Astro [Asset](https://docs.astro.build/en/guides/images/) using Vercel [Image Optimization](https://vercel.com/docs/image-optimization)
- `/image` - Astro [Asset](https://docs.astro.build/en/guides/assets/) using Vercel [Image Optimization](https://vercel.com/docs/image-optimization)
- `/edge.json` - An Astro API Endpoint that returns JSON data using [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions)
Learn more about [Astro on Vercel](https://vercel.com/docs/frameworks/astro).

View File

@@ -0,0 +1,17 @@
import { defineConfig } from 'astro/config';
// Use Vercel Edge Functions (Recommended)
import vercel from '@astrojs/vercel/edge';
// Can also use Serverless Functions
// import vercel from '@astrojs/vercel/serverless';
// Or a completely static build
// import vercel from '@astrojs/vercel/static';
export default defineConfig({
output: 'server',
experimental: {
assets: true
},
adapter: vercel({
imageService: true,
}),
});

View File

@@ -1,9 +0,0 @@
import { defineConfig } from 'astro/config';
import vercelServerless from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'server',
adapter: vercelServerless({
imageService: true,
}),
});

View File

@@ -8,9 +8,9 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/vercel": "7.6.0",
"astro": "^4.9.2",
"react": "18.3.1",
"web-vitals": "^4.0.1"
"@astrojs/vercel": "3.8.2",
"astro": "^2.10.14",
"react": "18.2.0",
"web-vitals": "^3.3.1"
}
}

View File

@@ -0,0 +1,9 @@
export async function get() {
return new Response(JSON.stringify({ time: new Date() }), {
status: 200,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 's-maxage=10, stale-while-revalidate',
},
});
}

View File

@@ -9,7 +9,7 @@
},
"devDependencies": {
"@types/jest": "27.4.1",
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"@vercel/frameworks": "3.0.2"
},
"version": null

View File

@@ -1,19 +1,5 @@
# @vercel-internals/types
## 1.0.38
### Patch Changes
- Updated dependencies [[`5c12ed695`](https://github.com/vercel/vercel/commit/5c12ed69500ceff6a9dc544eab0acd7af64c044a), [`21444a38e`](https://github.com/vercel/vercel/commit/21444a38e50ed680c91b0e3955f15e378eeda64b), [`06d2d860e`](https://github.com/vercel/vercel/commit/06d2d860e47aed792247bf929805b180ed6e2dab)]:
- @vercel/build-utils@8.2.2
## 1.0.37
### Patch Changes
- Updated dependencies [[`83741a0eb`](https://github.com/vercel/vercel/commit/83741a0eb9e44457b083e8790a11eb89984e6357)]:
- @vercel/build-utils@8.2.1
## 1.0.36
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "@vercel-internals/types",
"version": "1.0.38",
"version": "1.0.36",
"types": "index.d.ts",
"main": "index.d.ts",
"files": [
@@ -10,7 +10,7 @@
"dependencies": {
"@types/node": "14.14.31",
"@vercel-internals/constants": "1.0.4",
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"@vercel/routing-utils": "3.1.0"
},
"devDependencies": {

View File

@@ -1,21 +1,5 @@
# @vercel/build-utils
## 8.2.2
### Patch Changes
- Change node 16.x EOL for Vercel ([#11704](https://github.com/vercel/vercel/pull/11704))
- Improve error message and refactor ([#11706](https://github.com/vercel/vercel/pull/11706))
- [built-utils] Handle case of not having lockfile when corepack is enabled ([#11697](https://github.com/vercel/vercel/pull/11697))
## 8.2.1
### Patch Changes
- [node] update node@16 deprecation day ([#11671](https://github.com/vercel/vercel/pull/11671))
## 8.2.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "8.2.2",
"version": "8.2.0",
"license": "Apache-2.0",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -13,7 +13,7 @@ export const NODE_VERSIONS: NodeVersion[] = [
major: 16,
range: '16.x',
runtime: 'nodejs16.x',
discontinueDate: new Date('2025-01-31'),
discontinueDate: new Date('2024-06-15'),
},
{
major: 14,

View File

@@ -20,6 +20,12 @@ import { cloneEnv } from '../clone-env';
// Only allow one `runNpmInstall()` invocation to run concurrently
const runNpmInstallSema = new Sema(1);
const NO_OVERRIDE = {
detectedLockfile: undefined,
detectedPackageManager: undefined,
path: undefined,
};
export type CliType = 'yarn' | 'npm' | 'pnpm' | 'bun';
export interface ScanParentDirsResult {
@@ -353,9 +359,7 @@ export async function scanParentDirs(
// TODO: read "bun-lockfile-format-v0"
lockfileVersion = 0;
} else {
cliType = packageJson
? detectPackageManagerNameWithoutLockfile(packageJson)
: 'npm';
cliType = 'npm';
}
const packageJsonPath = pkgJsonPath || undefined;
@@ -368,37 +372,6 @@ export async function scanParentDirs(
};
}
function detectPackageManagerNameWithoutLockfile(packageJson: PackageJson) {
const packageJsonPackageManager = packageJson.packageManager;
if (usingCorepack(process.env, packageJsonPackageManager)) {
const corepackPackageManager = validateVersionSpecifier(
packageJsonPackageManager
);
switch (corepackPackageManager?.packageName) {
case 'npm':
case 'pnpm':
case 'yarn':
case 'bun':
return corepackPackageManager.packageName;
case undefined:
return 'npm';
default:
throw new Error(
`Unknown package manager "${corepackPackageManager?.packageName}". Change your package.json "packageManager" field to a known package manager: npm, pnpm, yarn, bun.`
);
}
}
return 'npm';
}
function usingCorepack(
env: { [x: string]: string | undefined },
packageJsonPackageManager: string | undefined
) {
const corepackFlagged = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
return corepackFlagged && Boolean(packageJsonPackageManager);
}
export async function walkParentDirs({
base,
start,
@@ -590,8 +563,6 @@ export function getEnvForPackageManager({
nodeVersion: NodeVersion | undefined;
env: { [x: string]: string | undefined };
}) {
const corepackEnabled = usingCorepack(env, packageJsonPackageManager);
const {
detectedLockfile,
detectedPackageManager,
@@ -599,10 +570,12 @@ export function getEnvForPackageManager({
} = getPathOverrideForPackageManager({
cliType,
lockfileVersion,
corepackEnabled,
corepackPackageManager: packageJsonPackageManager,
nodeVersion,
});
const corepackFlagged = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
const corepackEnabled = corepackFlagged && Boolean(packageJsonPackageManager);
if (corepackEnabled) {
debug(
`Detected corepack use for "${packageJsonPackageManager}". Not overriding package manager version.`
@@ -661,12 +634,9 @@ type DetectedPnpmVersion =
| 'corepack_enabled';
function detectPnpmVersion(
lockfileVersion: number | undefined,
corepackEnabled: boolean
lockfileVersion: number | undefined
): DetectedPnpmVersion {
switch (true) {
case corepackEnabled:
return 'corepack_enabled';
case lockfileVersion === undefined:
return 'not found';
case lockfileVersion === 5.3:
@@ -697,12 +667,12 @@ function shouldUseNpm7(
export function getPathOverrideForPackageManager({
cliType,
lockfileVersion,
corepackEnabled,
corepackPackageManager,
nodeVersion,
}: {
cliType: CliType;
lockfileVersion: number | undefined;
corepackEnabled: boolean;
corepackPackageManager: string | undefined;
nodeVersion: NodeVersion | undefined;
}): {
/**
@@ -715,77 +685,76 @@ export function getPathOverrideForPackageManager({
detectedPackageManager: string | undefined;
/**
* Value of $PATH that includes the binaries for the detected package manager.
* Undefined if no $PATH are necessary.
* `undefined` if no $PATH are necessary.
*/
path: string | undefined;
} {
const no_override = {
detectedLockfile: undefined,
detectedPackageManager: undefined,
path: undefined,
};
switch (cliType) {
case 'npm':
switch (true) {
case corepackEnabled:
return no_override;
case shouldUseNpm7(lockfileVersion, nodeVersion):
return {
path: '/node16/bin-npm7',
detectedLockfile: 'package-lock.json',
detectedPackageManager: 'npm 7+',
};
default:
return no_override;
}
case 'pnpm':
switch (detectPnpmVersion(lockfileVersion, corepackEnabled)) {
case 'corepack_enabled':
return no_override;
case 'pnpm 7':
// pnpm 7
return {
path: '/pnpm7/node_modules/.bin',
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm 7',
};
case 'pnpm 8':
// pnpm 8
return {
path: '/pnpm8/node_modules/.bin',
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm 8',
};
case 'pnpm 9':
// pnpm 9
return {
path: '/pnpm9/node_modules/.bin',
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm 9',
};
case 'pnpm 6':
default:
return no_override;
}
case 'bun':
switch (true) {
case corepackEnabled:
return no_override;
default:
// Bun 1
return {
path: '/bun1',
detectedLockfile: 'bun.lockb',
detectedPackageManager: 'Bun',
};
}
case 'yarn':
return no_override;
const detectedPackageManger = detectPackageManager(
cliType,
lockfileVersion,
nodeVersion
);
if (!detectedPackageManger) {
return NO_OVERRIDE;
}
if (!corepackPackageManager) {
return detectedPackageManger;
}
if (
validateVersionOverlap(
detectedPackageManger.detectedPackageManager,
corepackPackageManager
)
) {
// corepack is going to take care of it; do nothing special
return NO_OVERRIDE;
}
throw new Error(
`Detected package manager (by lockfile) "${detectedPackageManger.detectedPackageManager}" does not match intended corepack package manager "${corepackPackageManager}". Update your lockfile or "package.json#packageManager" values to match.`
);
}
function validateVersionSpecifier(version?: string) {
function validateVersionOverlap(
detectedPackageManger: string,
corepackPackageManager: string
) {
const validatedDetectedPackageManger = validateVersionSpecifier(
detectedPackageManger
);
if (!validatedDetectedPackageManger) {
throw new Error(
`Detected package manager "${detectedPackageManger}" is not a valid semver value.`
);
}
const validatedCorepackPackageManager = validateVersionSpecifier(
corepackPackageManager
);
if (!validatedCorepackPackageManager) {
throw new Error(
`Intended corepack defined package manager "${corepackPackageManager}" is not a valid semver value.`
);
}
if (
validatedDetectedPackageManger.packageName !==
validatedCorepackPackageManager.packageName
) {
throw new Error(
`Detected package manager "${validatedDetectedPackageManger.packageName}" does not match intended corepack defined package manager "${validatedCorepackPackageManager.packageName}". Change your lockfile or "package.json#packageManager" value to match.`
);
}
return intersects(
validatedDetectedPackageManger.packageVersionRange,
validatedCorepackPackageManager.packageVersionRange
);
}
function validateVersionSpecifier(version: string) {
if (!version) {
return undefined;
}
@@ -818,6 +787,65 @@ function validateVersionSpecifier(version?: string) {
};
}
function detectPackageManager(
cliType: CliType,
lockfileVersion: number | undefined,
nodeVersion: NodeVersion | undefined
) {
switch (cliType) {
case 'npm':
switch (true) {
case shouldUseNpm7(lockfileVersion, nodeVersion):
return {
path: '/node16/bin-npm7',
detectedLockfile: 'package-lock.json',
detectedPackageManager: 'npm@7.x',
};
default:
return undefined;
}
case 'pnpm':
switch (detectPnpmVersion(lockfileVersion)) {
case 'pnpm 7':
// pnpm 7
return {
path: '/pnpm7/node_modules/.bin',
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm@7.x',
};
case 'pnpm 8':
// pnpm 8
return {
path: '/pnpm8/node_modules/.bin',
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm@8.x',
};
case 'pnpm 9':
// pnpm 9
return {
path: '/pnpm9/node_modules/.bin',
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm@9.x',
};
case 'pnpm 6':
default:
return undefined;
}
case 'bun':
switch (true) {
default:
// Bun 1
return {
path: '/bun1',
detectedLockfile: 'bun.lockb',
detectedPackageManager: 'bun@1.x',
};
}
case 'yarn':
return undefined;
}
}
/**
* Helper to get the binary paths that link to the used package manager.
* Note: Make sure it doesn't contain any `console.log` calls.
@@ -858,13 +886,19 @@ export function getPathForPackageManager({
// broken behavior.
const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
const overrides = getPathOverrideForPackageManager({
let overrides = getPathOverrideForPackageManager({
cliType,
lockfileVersion,
corepackEnabled,
corepackPackageManager: undefined,
nodeVersion,
});
if (corepackEnabled) {
// this is essentially always overriding the value of `override`, but that's what was happening
// in this deprecated function before
overrides = NO_OVERRIDE;
}
const alreadyInPath = (newPath: string) => {
const oldPath = env.PATH ?? '';
return oldPath.split(path.delimiter).includes(newPath);

View File

@@ -63,7 +63,7 @@ describe('Test `getEnvForPackageManager()`', () => {
FOO: 'bar',
PATH: `/node16/bin-npm7${delimiter}foo`,
},
consoleLogOutput: 'Detected `package-lock.json` generated by npm 7+',
consoleLogOutput: 'Detected `package-lock.json` generated by npm@7.x',
consoleWarnOutput: null,
},
{
@@ -71,7 +71,7 @@ describe('Test `getEnvForPackageManager()`', () => {
args: {
cliType: 'npm',
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
packageJsonPackageManager: 'pnpm@latest',
packageJsonPackageManager: 'npm@*',
lockfileVersion: 2,
env: {
FOO: 'bar',
@@ -177,7 +177,7 @@ describe('Test `getEnvForPackageManager()`', () => {
PATH: `/pnpm7/node_modules/.bin${delimiter}foo`,
},
consoleLogOutput:
'Detected `pnpm-lock.yaml` version 5.4 generated by pnpm 7',
'Detected `pnpm-lock.yaml` version 5.4 generated by pnpm@7.x',
consoleWarnOutput: null,
},
{
@@ -197,7 +197,7 @@ describe('Test `getEnvForPackageManager()`', () => {
PATH: `/pnpm8/node_modules/.bin${delimiter}foo`,
},
consoleLogOutput:
'Detected `pnpm-lock.yaml` version 6 generated by pnpm 8',
'Detected `pnpm-lock.yaml` version 6 generated by pnpm@8.x',
consoleWarnOutput: null,
},
{
@@ -217,7 +217,7 @@ describe('Test `getEnvForPackageManager()`', () => {
PATH: `/pnpm9/node_modules/.bin${delimiter}foo`,
},
consoleLogOutput:
'Detected `pnpm-lock.yaml` version 9 generated by pnpm 9',
'Detected `pnpm-lock.yaml` version 9 generated by pnpm@9.x',
consoleWarnOutput: null,
},
{
@@ -236,7 +236,7 @@ describe('Test `getEnvForPackageManager()`', () => {
FOO: 'bar',
PATH: `/bun1${delimiter}/usr/local/bin`,
},
consoleLogOutput: 'Detected `bun.lockb` generated by Bun',
consoleLogOutput: 'Detected `bun.lockb` generated by bun@1.x',
consoleWarnOutput:
'Warning: Bun is used as a package manager at build time only, not at runtime with Functions',
},
@@ -245,7 +245,7 @@ describe('Test `getEnvForPackageManager()`', () => {
args: {
cliType: 'pnpm',
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
packageJsonPackageManager: 'npm@latest',
packageJsonPackageManager: 'pnpm@*',
lockfileVersion: 5.4,
env: {
FOO: 'bar',
@@ -342,7 +342,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
},
want: {
detectedLockfile: 'package-lock.json',
detectedPackageManager: 'npm 7+',
detectedPackageManager: 'npm@7.x',
path: '/node16/bin-npm7',
},
},
@@ -351,7 +351,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
args: {
cliType: 'npm',
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
packageJsonPackageManager: 'pnpm@latest',
packageJsonPackageManager: 'npm@*',
lockfileVersion: 2,
env: {
FOO: 'bar',
@@ -415,7 +415,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
},
want: {
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm 7',
detectedPackageManager: 'pnpm@7.x',
path: '/pnpm7/node_modules/.bin',
},
},
@@ -433,7 +433,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
},
want: {
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm 8',
detectedPackageManager: 'pnpm@8.x',
path: '/pnpm8/node_modules/.bin',
},
},
@@ -451,7 +451,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
},
want: {
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm 9',
detectedPackageManager: 'pnpm@9.x',
path: '/pnpm9/node_modules/.bin',
},
},
@@ -469,7 +469,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
},
want: {
detectedLockfile: 'bun.lockb',
detectedPackageManager: 'Bun',
detectedPackageManager: 'bun@1.x',
path: '/bun1',
},
},
@@ -478,7 +478,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
args: {
cliType: 'pnpm',
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
packageJsonPackageManager: 'npm@latest',
packageJsonPackageManager: 'pnpm@*',
lockfileVersion: 5.4,
env: {
FOO: 'bar',
@@ -496,8 +496,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
getPathOverrideForPackageManager({
cliType: args.cliType,
lockfileVersion: args.lockfileVersion,
// naive assumption that enabling corepack as a feature means it's used, but this is fine for tests
corepackEnabled: Boolean(args.env.ENABLE_EXPERIMENTAL_COREPACK),
corepackPackageManager: args.packageJsonPackageManager,
nodeVersion: args.nodeVersion,
})
).toStrictEqual(want);
@@ -540,7 +539,7 @@ describe('Test `getPathForPackageManager()`', () => {
},
want: {
detectedLockfile: 'package-lock.json',
detectedPackageManager: 'npm 7+',
detectedPackageManager: 'npm@7.x',
path: '/node16/bin-npm7',
yarnNodeLinker: undefined,
},
@@ -647,7 +646,7 @@ describe('Test `getPathForPackageManager()`', () => {
},
want: {
detectedLockfile: 'pnpm-lock.yaml',
detectedPackageManager: 'pnpm 7',
detectedPackageManager: 'pnpm@7.x',
path: '/pnpm7/node_modules/.bin',
yarnNodeLinker: undefined,
},
@@ -665,7 +664,7 @@ describe('Test `getPathForPackageManager()`', () => {
},
want: {
detectedLockfile: 'bun.lockb',
detectedPackageManager: 'Bun',
detectedPackageManager: 'bun@1.x',
path: '/bun1',
yarnNodeLinker: undefined,
},

View File

@@ -286,7 +286,7 @@ it('should throw for discontinued versions', async () => {
// Mock a future date so that Node 16 becomes discontinued
const realDateNow = Date.now;
try {
global.Date.now = () => new Date('2025-03-01').getTime();
global.Date.now = () => new Date('2024-07-16').getTime();
expect(getSupportedNodeVersion('8.10.x', false)).rejects.toThrow();
expect(getSupportedNodeVersion('8.10.x', true)).rejects.toThrow();
@@ -356,8 +356,8 @@ it('should warn for deprecated versions, soon to be discontinued', async () => {
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2025-01-31 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2025-01-31 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2024-06-15 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2024-06-15 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
]);
} finally {
global.Date.now = realDateNow;

View File

@@ -1,65 +1,5 @@
# vercel
## 34.2.6
### Patch Changes
- [built-utils] Handle case of not having lockfile when corepack is enabled ([#11697](https://github.com/vercel/vercel/pull/11697))
- Updated dependencies [[`5c12ed695`](https://github.com/vercel/vercel/commit/5c12ed69500ceff6a9dc544eab0acd7af64c044a), [`21444a38e`](https://github.com/vercel/vercel/commit/21444a38e50ed680c91b0e3955f15e378eeda64b), [`fa9789a93`](https://github.com/vercel/vercel/commit/fa9789a93ebe64c4246f441590cb695d296af336), [`c925dc4a1`](https://github.com/vercel/vercel/commit/c925dc4a1bf3a47b684b5f7fd788ddd24ba1ed1e), [`06d2d860e`](https://github.com/vercel/vercel/commit/06d2d860e47aed792247bf929805b180ed6e2dab), [`b735f37fd`](https://github.com/vercel/vercel/commit/b735f37fd92c707040e72084b0fdb4f8fd01dd51)]:
- @vercel/build-utils@8.2.2
- @vercel/next@4.2.16
- @vercel/redwood@2.0.10
- @vercel/remix-builder@2.1.7
- @vercel/node@3.1.7
- @vercel/static-build@2.5.11
## 34.2.5
### Patch Changes
- Adds a route for the `.rsc` pathname as well when app has ppr enabled but not all routes. ([#11681](https://github.com/vercel/vercel/pull/11681))
- Updated dependencies [[`7457767a7`](https://github.com/vercel/vercel/commit/7457767a77b03662c103a658273a46cf78359068), [`4337ea065`](https://github.com/vercel/vercel/commit/4337ea0654c4ee2c91c4464540f879d43da6696f)]:
- @vercel/next@4.2.15
## 34.2.4
### Patch Changes
- Updated dependencies [[`3eb9d8c89`](https://github.com/vercel/vercel/commit/3eb9d8c8929592960d88e0395e2a2443f7304d6b), [`83741a0eb`](https://github.com/vercel/vercel/commit/83741a0eb9e44457b083e8790a11eb89984e6357)]:
- @vercel/python@4.3.0
- @vercel/build-utils@8.2.1
- @vercel/node@3.1.6
- @vercel/static-build@2.5.10
## 34.2.3
### Patch Changes
- Don't create streaming lambdas for pages router routes ([#11660](https://github.com/vercel/vercel/pull/11660))
- Updated dependencies [[`c9d53d4e3`](https://github.com/vercel/vercel/commit/c9d53d4e3e4591b9b6bde86100564c9ee4c6d1d4), [`5f561f8cf`](https://github.com/vercel/vercel/commit/5f561f8cfa4720801a5cf4598f193ab34539abb9)]:
- @vercel/next@4.2.14
## 34.2.2
### Patch Changes
- Fix related to erroring when a prefetch route is not provided but the route is PPR enabled ([#11638](https://github.com/vercel/vercel/pull/11638))
- Updated dependencies [[`8e44ef5b9`](https://github.com/vercel/vercel/commit/8e44ef5b9d2cdbe743c7f1e3534f182465fed9bf), [`61e6af374`](https://github.com/vercel/vercel/commit/61e6af3740296c11015d0c3da84ee205020b0ea6)]:
- @vercel/next@4.2.13
## 34.2.1
### Patch Changes
- Support incremental PPR for large applications ([#11625](https://github.com/vercel/vercel/pull/11625))
- Updated dependencies [[`73e558913`](https://github.com/vercel/vercel/commit/73e558913ab30ba097d7536a12fa8a7c967479f0)]:
- @vercel/next@4.2.12
## 34.2.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "34.2.6",
"version": "34.2.0",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -12,8 +12,8 @@
},
"scripts": {
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail",
"vitest-run": "vitest",
"vitest-unit": "jest test/unit/ --listTests",
"vitest-unit-run": "pnpm vitest",
"vitest-unit": "pnpm jest test/unit/ --listTests",
"test-e2e": "rimraf test/fixtures/integration && pnpm test test/integration-1.test.ts test/integration-2.test.ts test/integration-3.test.ts",
"test-dev": "pnpm test test/dev/",
"coverage": "codecov",
@@ -32,17 +32,17 @@
"node": ">= 16"
},
"dependencies": {
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"@vercel/fun": "1.1.0",
"@vercel/go": "3.1.1",
"@vercel/hydrogen": "1.0.2",
"@vercel/next": "4.2.16",
"@vercel/node": "3.1.7",
"@vercel/python": "4.3.0",
"@vercel/redwood": "2.0.10",
"@vercel/remix-builder": "2.1.7",
"@vercel/next": "4.2.11",
"@vercel/node": "3.1.5",
"@vercel/python": "4.2.0",
"@vercel/redwood": "2.0.9",
"@vercel/remix-builder": "2.1.6",
"@vercel/ruby": "2.1.0",
"@vercel/static-build": "2.5.11",
"@vercel/static-build": "2.5.9",
"chokidar": "3.3.1"
},
"devDependencies": {
@@ -92,11 +92,11 @@
"@types/yauzl-promise": "2.1.0",
"@vercel-internals/constants": "1.0.4",
"@vercel-internals/get-package-json": "1.0.0",
"@vercel-internals/types": "1.0.38",
"@vercel/client": "13.2.9",
"@vercel-internals/types": "1.0.36",
"@vercel/client": "13.2.7",
"@vercel/error-utils": "2.0.2",
"@vercel/frameworks": "3.0.2",
"@vercel/fs-detectors": "5.2.4",
"@vercel/fs-detectors": "5.2.3",
"@vercel/routing-utils": "3.1.0",
"@vitest/expect": "1.4.0",
"ajv": "6.12.2",

View File

@@ -263,7 +263,6 @@ test('[vc build] should build project with corepack and select pnpm@7.1.0', asyn
path.join(directory, '.vercel/cache/corepack')
);
expect(contents).toEqual(['home', 'shim']);
expect(output.stdout).toMatch(/Running "pnpm run build"/gm);
} finally {
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
}
@@ -292,7 +291,6 @@ test('[vc build] should build project with corepack and select yarn@2.4.3', asyn
path.join(directory, '.vercel/cache/corepack')
);
expect(contents).toEqual(['home', 'shim']);
expect(output.stdout).toMatch(/Running "yarn run build"/gm);
} finally {
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
}

View File

@@ -1,19 +1,5 @@
# @vercel/client
## 13.2.9
### Patch Changes
- Updated dependencies [[`5c12ed695`](https://github.com/vercel/vercel/commit/5c12ed69500ceff6a9dc544eab0acd7af64c044a), [`21444a38e`](https://github.com/vercel/vercel/commit/21444a38e50ed680c91b0e3955f15e378eeda64b), [`06d2d860e`](https://github.com/vercel/vercel/commit/06d2d860e47aed792247bf929805b180ed6e2dab)]:
- @vercel/build-utils@8.2.2
## 13.2.8
### Patch Changes
- Updated dependencies [[`83741a0eb`](https://github.com/vercel/vercel/commit/83741a0eb9e44457b083e8790a11eb89984e6357)]:
- @vercel/build-utils@8.2.1
## 13.2.7
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "13.2.9",
"version": "13.2.7",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -37,7 +37,7 @@
"typescript": "4.9.5"
},
"dependencies": {
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"@vercel/error-utils": "2.0.2",
"@vercel/routing-utils": "3.1.0",
"@zeit/fetch": "5.2.0",

View File

@@ -1,11 +1,5 @@
# @vercel/fs-detectors
## 5.2.4
### Patch Changes
- Add support for detecting Turborepo 2 ([#11680](https://github.com/vercel/vercel/pull/11680))
## 5.2.3
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/fs-detectors",
"version": "5.2.4",
"version": "5.2.3",
"description": "Vercel filesystem detectors",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -37,7 +37,7 @@
"@types/minimatch": "3.0.5",
"@types/node": "14.18.33",
"@types/semver": "7.3.10",
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"jest-junit": "16.0.0",
"typescript": "4.9.5"
}

View File

@@ -7,11 +7,10 @@ import JSON5 from 'json5';
import semver from 'semver';
export class MissingBuildPipeline extends Error {
constructor(usesTasks: boolean) {
const message = usesTasks
? 'Missing required `build` task in turbo.json.'
: 'Missing required `build` pipeline in turbo.json or package.json Turbo configuration.';
super(message);
constructor() {
super(
'Missing required `build` pipeline in turbo.json or package.json Turbo configuration.'
);
}
}
@@ -66,15 +65,12 @@ export async function getMonorepoDefaultSettings(
]);
let hasBuildPipeline = false;
let hasTurboTasks = false;
let turboSemVer = null;
if (turboJSONBuf !== null) {
const turboJSON = JSON5.parse(turboJSONBuf.toString('utf-8'));
hasTurboTasks = 'tasks' in (turboJSON || {});
if (turboJSON?.pipeline?.build || turboJSON?.tasks?.build) {
if (turboJSON?.pipeline?.build) {
hasBuildPipeline = true;
}
}
@@ -93,7 +89,7 @@ export async function getMonorepoDefaultSettings(
}
if (!hasBuildPipeline) {
throw new MissingBuildPipeline(hasTurboTasks);
throw new MissingBuildPipeline();
}
if (projectPath === '/') {

View File

@@ -1,9 +0,0 @@
{
"private": true,
"workspaces": [
"packages/*"
],
"devDependencies": {
"turbo": "latest"
}
}

View File

@@ -1,5 +0,0 @@
{
"name": "app-14",
"version": "0.0.1",
"main": "index.js"
}

View File

@@ -1,2 +0,0 @@
// TEST COMMENT TO VERIFY JSON5 SUPPORT
{ "tasks": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] } } }

View File

@@ -17,17 +17,11 @@ describe('getMonorepoDefaultSettings', () => {
);
});
test('MissingBuildPipeline is an error', () => {
const missingBuildPipeline = new MissingBuildPipeline(false);
const missingBuildPipeline = new MissingBuildPipeline();
expect(missingBuildPipeline).toBeInstanceOf(Error);
expect(missingBuildPipeline.message).toBe(
'Missing required `build` pipeline in turbo.json or package.json Turbo configuration.'
);
const missingBuildTask = new MissingBuildPipeline(true);
expect(missingBuildTask).toBeInstanceOf(Error);
expect(missingBuildTask.message).toBe(
'Missing required `build` task in turbo.json.'
);
});
test.each([
@@ -37,7 +31,6 @@ describe('getMonorepoDefaultSettings', () => {
['turbo-npm', 'turbo', true, 'app-15', false, false],
['turbo-npm-root-proj', 'turbo', true, 'app-root-proj', true, false],
['turbo-latest', 'turbo', false, 'app-14', false, false],
['turbo-2', 'turbo', false, 'app-14', false, false],
['nx', 'nx', false, 'app-12', false, false],
['nx-package-config', 'nx', false, 'app-11', false, false],
['nx-project-and-package-config-1', 'nx', false, 'app-10', false, false],

View File

@@ -1,19 +1,5 @@
# @vercel/gatsby-plugin-vercel-builder
## 2.0.33
### Patch Changes
- Updated dependencies [[`5c12ed695`](https://github.com/vercel/vercel/commit/5c12ed69500ceff6a9dc544eab0acd7af64c044a), [`21444a38e`](https://github.com/vercel/vercel/commit/21444a38e50ed680c91b0e3955f15e378eeda64b), [`06d2d860e`](https://github.com/vercel/vercel/commit/06d2d860e47aed792247bf929805b180ed6e2dab)]:
- @vercel/build-utils@8.2.2
## 2.0.32
### Patch Changes
- Updated dependencies [[`83741a0eb`](https://github.com/vercel/vercel/commit/83741a0eb9e44457b083e8790a11eb89984e6357)]:
- @vercel/build-utils@8.2.1
## 2.0.31
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/gatsby-plugin-vercel-builder",
"version": "2.0.33",
"version": "2.0.31",
"main": "dist/index.js",
"files": [
"dist",
@@ -20,7 +20,7 @@
},
"dependencies": {
"@sinclair/typebox": "0.25.24",
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"@vercel/routing-utils": "3.1.0",
"esbuild": "0.14.47",
"etag": "1.8.1",

View File

@@ -29,7 +29,7 @@
"@types/node-fetch": "^2.3.0",
"@types/tar": "6.1.5",
"@types/yauzl-promise": "2.1.0",
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"async-retry": "1.3.3",
"execa": "^1.0.0",
"fs-extra": "^7.0.0",

View File

@@ -26,7 +26,7 @@
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "14.18.33",
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"execa": "3.2.0",
"fs-extra": "11.1.0",
"jest-junit": "16.0.0"

View File

@@ -1,45 +1,5 @@
# @vercel/next
## 4.2.16
### Patch Changes
- prevent /index from being incorrectly normalized in rewrites ([#11707](https://github.com/vercel/vercel/pull/11707))
- Upgrade to @vercel/nft 0.27.2 with browser remapping support ([#11700](https://github.com/vercel/vercel/pull/11700))
- ensure unmatched rsc rewrites are routed to correct handler ([#11688](https://github.com/vercel/vercel/pull/11688))
## 4.2.15
### Patch Changes
- ensure unmatched action rewrites are routed to correct handler ([#11686](https://github.com/vercel/vercel/pull/11686))
- Adds a route for the `.rsc` pathname as well when app has ppr enabled but not all routes. ([#11681](https://github.com/vercel/vercel/pull/11681))
## 4.2.14
### Patch Changes
- Don't create streaming lambdas for pages router routes ([#11660](https://github.com/vercel/vercel/pull/11660))
- Ensure user rewrites still match to action outputs ([#11628](https://github.com/vercel/vercel/pull/11628))
## 4.2.13
### Patch Changes
- Fix static case for detecting when a page supports PPR ([#11635](https://github.com/vercel/vercel/pull/11635))
- Fix related to erroring when a prefetch route is not provided but the route is PPR enabled ([#11638](https://github.com/vercel/vercel/pull/11638))
## 4.2.12
### Patch Changes
- Support incremental PPR for large applications ([#11625](https://github.com/vercel/vercel/pull/11625))
## 4.2.11
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/next",
"version": "4.2.16",
"version": "4.2.11",
"license": "Apache-2.0",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -23,7 +23,7 @@
"dist"
],
"dependencies": {
"@vercel/nft": "0.27.2"
"@vercel/nft": "0.27.0"
},
"devDependencies": {
"@types/aws-lambda": "8.10.19",
@@ -40,7 +40,7 @@
"@types/semver": "6.0.0",
"@types/text-table": "0.2.1",
"@types/webpack-sources": "3.2.0",
"@vercel/build-utils": "8.2.2",
"@vercel/build-utils": "8.2.0",
"@vercel/routing-utils": "3.1.0",
"async-sema": "3.0.1",
"buffer-crc32": "0.2.13",

View File

@@ -1358,11 +1358,6 @@ export const build: BuildV2 = async ({
experimentalPPRRoutes.add(route);
}
const isAppPPREnabled = requiredServerFilesManifest
? requiredServerFilesManifest.config.experimental?.ppr === true ||
requiredServerFilesManifest.config.experimental?.ppr === 'incremental'
: false;
if (requiredServerFilesManifest) {
if (!routesManifest) {
throw new Error(
@@ -1418,7 +1413,6 @@ export const build: BuildV2 = async ({
hasIsr500Page,
variantsManifest,
experimentalPPRRoutes,
isAppPPREnabled,
});
}
@@ -1938,7 +1932,7 @@ export const build: BuildV2 = async ({
canUsePreviewMode,
bypassToken: prerenderManifest.bypassToken || '',
isServerMode,
isAppPPREnabled: false,
experimentalPPRRoutes,
hasActionOutputSupport: false,
}).then(arr =>
localizeDynamicRoutes(
@@ -1969,7 +1963,7 @@ export const build: BuildV2 = async ({
canUsePreviewMode,
bypassToken: prerenderManifest.bypassToken || '',
isServerMode,
isAppPPREnabled: false,
experimentalPPRRoutes,
hasActionOutputSupport: false,
}).then(arr =>
arr.map(route => {
@@ -2168,7 +2162,6 @@ export const build: BuildV2 = async ({
appPathRoutesManifest,
isSharedLambdas,
canUsePreviewMode,
isAppPPREnabled: false,
});
await Promise.all(

View File

@@ -144,7 +144,6 @@ export async function serverBuild({
requiredServerFilesManifest,
variantsManifest,
experimentalPPRRoutes,
isAppPPREnabled,
}: {
appPathRoutesManifest?: Record<string, string>;
dynamicPages: string[];
@@ -186,15 +185,7 @@ export async function serverBuild({
requiredServerFilesManifest: NextRequiredServerFilesManifest;
variantsManifest: VariantsManifest | null;
experimentalPPRRoutes: ReadonlySet<string>;
isAppPPREnabled: boolean;
}): Promise<BuildResult> {
if (isAppPPREnabled) {
debug(
'experimentalPPRRoutes',
JSON.stringify(Array.from(experimentalPPRRoutes))
);
}
lambdaPages = Object.assign({}, lambdaPages, lambdaAppPaths);
const experimentalAllowBundling = Boolean(
@@ -212,8 +203,7 @@ export async function serverBuild({
);
const hasActionOutputSupport =
semver.gte(nextVersion, ACTION_OUTPUT_SUPPORT_VERSION) &&
Boolean(process.env.NEXT_EXPERIMENTAL_STREAMING_ACTIONS) &&
!routesManifest.i18n;
Boolean(process.env.NEXT_EXPERIMENTAL_STREAMING_ACTIONS);
const projectDir = requiredServerFilesManifest.relativeAppDir
? path.join(baseDir, requiredServerFilesManifest.relativeAppDir)
: requiredServerFilesManifest.appDir || entryPath;
@@ -227,6 +217,12 @@ export async function serverBuild({
}
}
const experimental = {
ppr:
requiredServerFilesManifest.config.experimental?.ppr === true ||
requiredServerFilesManifest.config.experimental?.ppr === 'incremental',
};
let appRscPrefetches: UnwrapPromise<ReturnType<typeof glob>> = {};
let appBuildTraces: UnwrapPromise<ReturnType<typeof glob>> = {};
let appDir: string | null = null;
@@ -234,7 +230,7 @@ export async function serverBuild({
if (appPathRoutesManifest) {
appDir = path.join(pagesDir, '../app');
appBuildTraces = await glob('**/*.js.nft.json', appDir);
appRscPrefetches = isAppPPREnabled
appRscPrefetches = experimental.ppr
? {}
: await glob(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
@@ -253,19 +249,9 @@ export async function serverBuild({
for (const rewrite of afterFilesRewrites) {
if (rewrite.src && rewrite.dest) {
// ensures that userland rewrites are still correctly matched to their special outputs
// PPR should match .prefetch.rsc, .rsc, and .action
// non-PPR should match .rsc and .action
// we only add `.action` handling to the regex if flagged on in the build
const rscSuffix = isAppPPREnabled
? `(\\.prefetch)?\\.rsc${hasActionOutputSupport ? '|\\.action' : ''}`
: hasActionOutputSupport
? '(\\.action|\\.rsc)'
: '\\.rsc';
rewrite.src = rewrite.src.replace(
/\/?\(\?:\/\)\?/,
`(?<rscsuff>${rscSuffix})?(?:/)?`
`(?<rscsuff>${experimental.ppr ? '(\\.prefetch)?' : ''}\\.rsc)?(?:/)?`
);
let destQueryIndex = rewrite.dest.indexOf('?');
@@ -951,7 +937,6 @@ export async function serverBuild({
if (!group.isPrerenders || group.isExperimentalPPR) {
group.isStreaming = true;
}
group.isAppRouter = true;
// We create a streaming variant of the Prerender lambda group
@@ -999,24 +984,18 @@ export async function serverBuild({
apiLambdaGroups: apiLambdaGroups.map(group => ({
pages: group.pages,
isPrerender: group.isPrerenders,
isStreaming: group.isStreaming,
isExperimentalPPR: group.isExperimentalPPR,
pseudoLayerBytes: group.pseudoLayerBytes,
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
})),
pageLambdaGroups: pageLambdaGroups.map(group => ({
pages: group.pages,
isPrerender: group.isPrerenders,
isStreaming: group.isStreaming,
isExperimentalPPR: group.isExperimentalPPR,
pseudoLayerBytes: group.pseudoLayerBytes,
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
})),
appRouterLambdaGroups: appRouterLambdaGroups.map(group => ({
pages: group.pages,
isPrerender: group.isPrerenders,
isStreaming: group.isStreaming,
isExperimentalPPR: group.isExperimentalPPR,
pseudoLayerBytes: group.pseudoLayerBytes,
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
})),
@@ -1024,8 +1003,6 @@ export async function serverBuild({
appRouterStreamingActionLambdaGroups.map(group => ({
pages: group.pages,
isPrerender: group.isPrerenders,
isStreaming: group.isStreaming,
isExperimentalPPR: group.isExperimentalPPR,
pseudoLayerBytes: group.pseudoLayerBytes,
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
})),
@@ -1033,8 +1010,6 @@ export async function serverBuild({
group => ({
pages: group.pages,
isPrerender: group.isPrerenders,
isStreaming: group.isStreaming,
isExperimentalPPR: group.isExperimentalPPR,
pseudoLayerBytes: group.pseudoLayerBytes,
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
})
@@ -1214,10 +1189,15 @@ export async function serverBuild({
const lambda = await createLambdaFromPseudoLayers(options);
// This is a PPR lambda if it's an App Page with the PPR experimental flag
// enabled.
const isPPR =
experimental.ppr && group.isAppRouter && !group.isAppRouteHandler;
// If PPR is enabled and this is an App Page, create the non-streaming
// lambda for the page for revalidation.
let revalidate: NodejsLambda | undefined;
if (group.isExperimentalPPR) {
if (isPPR) {
if (!options.isStreaming) {
throw new Error("Invariant: PPR lambda isn't streaming");
}
@@ -1234,11 +1214,14 @@ export async function serverBuild({
// This is the name of the page, where the root is `index`.
const pageName = pageFilename.replace(/\.js$/, '');
// This is the name of the page prefixed with a `/`, where the root is
// `/index`.
const pagePath = path.posix.join('/', pageName);
// This is the routable pathname for the page, where the root is `/`.
const pagePathname = normalizePage(pageName);
const pagePathname = pagePath === '/index' ? '/' : pagePath;
let isPrerender = prerenderRoutes.has(pagePathname);
const isRoutePPREnabled = experimentalPPRRoutes.has(pagePathname);
if (!isPrerender && routesManifest?.i18n) {
isPrerender = routesManifest.i18n.locales.some(locale => {
@@ -1256,7 +1239,7 @@ export async function serverBuild({
}
// If this is a PPR page, then we should prefix the output name.
if (isRoutePPREnabled) {
if (isPPR) {
if (!revalidate) {
throw new Error("Invariant: PPR lambda isn't set");
}
@@ -1337,13 +1320,6 @@ export async function serverBuild({
console.timeEnd(lambdaCreationLabel);
}
if (isAppPPREnabled) {
debug(
'experimentalStreamingLambdaPaths',
JSON.stringify(Array.from(experimentalStreamingLambdaPaths))
);
}
const prerenderRoute = onPrerenderRoute({
appDir,
pagesDir,
@@ -1363,7 +1339,6 @@ export async function serverBuild({
hasPages404: routesManifest.pages404,
isCorrectNotFoundRoutes,
isEmptyAllowQueryForPrendered,
isAppPPREnabled,
});
await Promise.all(
@@ -1432,7 +1407,7 @@ export async function serverBuild({
bypassToken: prerenderManifest.bypassToken || '',
isServerMode: true,
dynamicMiddlewareRouteMap: middleware.dynamicRouteMap,
isAppPPREnabled,
experimentalPPRRoutes,
hasActionOutputSupport,
}).then(arr =>
localizeDynamicRoutes(
@@ -1614,7 +1589,7 @@ export async function serverBuild({
if (lambdas[pathname]) {
lambdas[`${pathname}.rsc`] = lambdas[pathname];
if (isAppPPREnabled) {
if (experimental.ppr) {
lambdas[`${pathname}${RSC_PREFETCH_SUFFIX}`] = lambdas[pathname];
}
}
@@ -1622,7 +1597,7 @@ export async function serverBuild({
if (edgeFunctions[pathname]) {
edgeFunctions[`${pathname}.rsc`] = edgeFunctions[pathname];
if (isAppPPREnabled) {
if (experimental.ppr) {
edgeFunctions[`${pathname}${RSC_PREFETCH_SUFFIX}`] =
edgeFunctions[pathname];
}
@@ -1641,7 +1616,7 @@ export async function serverBuild({
'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
const appNotFoundPath = path.posix.join('.', entryDirectory, '_not-found');
if (isAppPPREnabled && !rscPrefetchHeader) {
if (experimental.ppr && !rscPrefetchHeader) {
throw new Error("Invariant: cannot use PPR without 'rsc.prefetchHeader'");
}
@@ -1649,7 +1624,7 @@ export async function serverBuild({
// all the routes that support it (and are listed) have configured lambdas.
// This only applies to routes that do not have fallbacks enabled (these are
// routes that have `dynamicParams = false` defined.
if (isAppPPREnabled) {
if (experimental.ppr) {
for (const { srcRoute, dataRoute, experimentalPPR } of Object.values(
prerenderManifest.staticRoutes
)) {
@@ -1932,7 +1907,7 @@ export async function serverBuild({
...(appDir
? [
...(rscPrefetchHeader && isAppPPREnabled
...(rscPrefetchHeader && experimental.ppr
? [
{
src: `^${path.posix.join('/', entryDirectory, '/')}`,
@@ -2086,45 +2061,10 @@ export async function serverBuild({
]
: []),
// before processing rewrites, remove any special `/index` routes that were added
// as these won't be properly normalized by `afterFilesRewrites` / `dynamicRoutes`
...(appPathRoutesManifest
? [
{
src: path.posix.join(
'/',
entryDirectory,
'/index(\\.action|\\.rsc)'
),
dest: path.posix.join('/', entryDirectory),
continue: true,
},
]
: []),
// These need to come before handle: miss or else they are grouped
// with that routing section
...afterFilesRewrites,
// Ensure that after we normalize `afterFilesRewrites`, unmatched actions are routed to the correct handler
// e.g. /foo/.action -> /foo.action. This should only ever match in cases where we're routing to an action handler
// and the rewrite normalization led to something like /foo/$1$rscsuff, and $1 had no match.
// This is meant to have parity with the .rsc handling below.
...(hasActionOutputSupport
? [
{
src: `${path.posix.join('/', entryDirectory, '/\\.action$')}`,
dest: `${path.posix.join('/', entryDirectory, '/index.action')}`,
check: true,
},
{
src: `${path.posix.join('/', entryDirectory, '(.+)/\\.action$')}`,
dest: `${path.posix.join('/', entryDirectory, '$1.action')}`,
check: true,
},
]
: []),
// ensure non-normalized /.rsc from rewrites is handled
...(appPathRoutesManifest
? [
@@ -2137,29 +2077,11 @@ export async function serverBuild({
),
check: true,
},
{
src: path.posix.join(
'/',
entryDirectory,
'(.+)/\\.prefetch\\.rsc$'
),
dest: path.posix.join(
'/',
entryDirectory,
`$1${RSC_PREFETCH_SUFFIX}`
),
check: true,
},
{
src: path.posix.join('/', entryDirectory, '/\\.rsc$'),
dest: path.posix.join('/', entryDirectory, `/index.rsc`),
check: true,
},
{
src: path.posix.join('/', entryDirectory, '(.+)/\\.rsc$'),
dest: path.posix.join('/', entryDirectory, '$1.rsc'),
check: true,
},
]
: []),

View File

@@ -192,12 +192,8 @@ function normalizePage(page: string): string {
if (!page.startsWith('/')) {
page = `/${page}`;
}
// Replace the `/index` with `/`
if (page === '/index') {
page = '/';
}
// remove '/index' from the end
page = page.replace(/\/index$/, '/');
return page;
}
@@ -324,8 +320,8 @@ export async function getDynamicRoutes({
bypassToken,
isServerMode,
dynamicMiddlewareRouteMap,
experimentalPPRRoutes,
hasActionOutputSupport,
isAppPPREnabled,
}: {
entryPath: string;
entryDirectory: string;
@@ -337,8 +333,8 @@ export async function getDynamicRoutes({
bypassToken?: string;
isServerMode?: boolean;
dynamicMiddlewareRouteMap?: ReadonlyMap<string, RouteWithSrc>;
experimentalPPRRoutes: ReadonlySet<string>;
hasActionOutputSupport: boolean;
isAppPPREnabled: boolean;
}): Promise<RouteWithSrc[]> {
if (routesManifest) {
switch (routesManifest.version) {
@@ -412,7 +408,7 @@ export async function getDynamicRoutes({
];
}
if (isAppPPREnabled) {
if (experimentalPPRRoutes.has(page)) {
let dest = route.dest?.replace(/($|\?)/, '.prefetch.rsc$1');
if (page === '/' || page === '/index') {
@@ -1509,8 +1505,8 @@ export type LambdaGroup = {
isAppRouter?: boolean;
isAppRouteHandler?: boolean;
isStreaming?: boolean;
readonly isPrerenders: boolean;
readonly isExperimentalPPR: boolean;
isPrerenders?: boolean;
isExperimentalPPR?: boolean;
isActionLambda?: boolean;
isPages?: boolean;
isApiLambda: boolean;
@@ -1952,7 +1948,6 @@ type OnPrerenderRouteArgs = {
routesManifest?: RoutesManifest;
isCorrectNotFoundRoutes?: boolean;
isEmptyAllowQueryForPrendered?: boolean;
isAppPPREnabled: boolean;
};
let prerenderGroup = 1;
@@ -1989,7 +1984,6 @@ export const onPrerenderRoute =
routesManifest,
isCorrectNotFoundRoutes,
isEmptyAllowQueryForPrendered,
isAppPPREnabled,
} = prerenderRouteArgs;
if (isBlocking && isFallback) {
@@ -2110,14 +2104,14 @@ export const onPrerenderRoute =
// If enabled, try to get the postponed route information from the file
// system and use it to assemble the prerender.
let postponedPrerender: string | undefined;
let prerender: string | undefined;
if (experimentalPPR && appDir) {
const htmlPath = path.join(appDir, `${routeFileNoExt}.html`);
const metaPath = path.join(appDir, `${routeFileNoExt}.meta`);
if (fs.existsSync(htmlPath) && fs.existsSync(metaPath)) {
const meta = JSON.parse(await fs.readFile(metaPath, 'utf8'));
if ('postponed' in meta && typeof meta.postponed === 'string') {
postponedPrerender = meta.postponed;
prerender = meta.postponed;
// Assign the headers Content-Type header to the prerendered type.
initialHeaders ??= {};
@@ -2127,7 +2121,7 @@ export const onPrerenderRoute =
// Read the HTML file and append it to the prerendered content.
const html = await fs.readFileSync(htmlPath, 'utf8');
postponedPrerender += html;
prerender += html;
}
}
@@ -2144,14 +2138,14 @@ export const onPrerenderRoute =
}
}
if (postponedPrerender) {
if (prerender) {
const contentType = initialHeaders?.['content-type'];
if (!contentType) {
throw new Error("Invariant: contentType can't be undefined");
}
// Assemble the prerendered file.
htmlFsRef = new FileBlob({ contentType, data: postponedPrerender });
htmlFsRef = new FileBlob({ contentType, data: prerender });
} else if (
appDir &&
!dataRoute &&
@@ -2215,14 +2209,7 @@ export const onPrerenderRoute =
? addLocaleOrDefault('/404.html', routesManifest, locale)
: '/404.html'
: isAppPathRoute
? // When experimental PPR is enabled, we expect that the data
// that should be served as a part of the prerender should
// be from the prefetch data route. If this isn't enabled
// for ppr, the only way to get the data is from the data
// route.
experimentalPPR
? prefetchDataRoute
: dataRoute
? prefetchDataRoute || dataRoute
: routeFileNoExt + '.json'
}`
),
@@ -2232,6 +2219,22 @@ export const onPrerenderRoute =
initialStatus = 404;
}
/**
* If the route key had an `/index` suffix added, we need to note it so we
* can remove it from the output path later accurately.
*/
let addedIndexSuffix = false;
if (isAppPathRoute) {
// for literal index routes we need to append an additional /index
// due to the proxy's normalizing for /index routes
if (routeKey !== '/index' && routeKey.endsWith('/index')) {
routeKey = `${routeKey}/index`;
routeFileNoExt = routeKey;
addedIndexSuffix = true;
}
}
let outputPathPage = path.posix.join(entryDirectory, routeFileNoExt);
if (!isAppPathRoute) {
@@ -2268,7 +2271,7 @@ export const onPrerenderRoute =
let outputPathPrefetchData: null | string = null;
if (prefetchDataRoute) {
if (!isAppPPREnabled) {
if (!experimentalPPR) {
throw new Error(
"Invariant: prefetchDataRoute can't be set without PPR"
);
@@ -2279,6 +2282,10 @@ export const onPrerenderRoute =
throw new Error('Invariant: expected to find prefetch data route PPR');
}
// When the prefetch data path is available, use it for the prerender,
// otherwise use the data path.
const outputPrerenderPathData = outputPathPrefetchData || outputPathData;
if (isSharedLambdas) {
const outputSrcPathPage = normalizeIndexOutput(
path.join(
@@ -2331,14 +2338,8 @@ export const onPrerenderRoute =
htmlFsRef.contentType = htmlContentType;
prerenders[outputPathPage] = htmlFsRef;
if (outputPathPrefetchData) {
prerenders[outputPathPrefetchData] = jsonFsRef;
}
// If experimental ppr is not enabled for this route, then add the data
// route as a target for the prerender as well.
if (outputPathData && !experimentalPPR) {
prerenders[outputPathData] = jsonFsRef;
if (outputPrerenderPathData) {
prerenders[outputPrerenderPathData] = jsonFsRef;
}
}
}
@@ -2427,7 +2428,7 @@ export const onPrerenderRoute =
// static route first, then try the srcRoute if it doesn't exist. If we
// can't find it at all, this constitutes an error.
experimentalStreamingLambdaPath = experimentalStreamingLambdaPaths.get(
pathnameToOutputName(entryDirectory, routeKey)
pathnameToOutputName(entryDirectory, routeKey, addedIndexSuffix)
);
if (!experimentalStreamingLambdaPath && srcRoute) {
experimentalStreamingLambdaPath =
@@ -2474,20 +2475,21 @@ export const onPrerenderRoute =
: {}),
});
const normalizePathData = (pathData: string) => {
if (outputPrerenderPathData) {
let normalizedPathData = outputPrerenderPathData;
if (
(srcRoute === '/' || srcRoute == '/index') &&
pathData.endsWith(RSC_PREFETCH_SUFFIX)
outputPrerenderPathData.endsWith(RSC_PREFETCH_SUFFIX)
) {
delete lambdas[pathData];
return pathData.replace(/([^/]+\.prefetch\.rsc)$/, '__$1');
delete lambdas[normalizedPathData];
normalizedPathData = normalizedPathData.replace(
/([^/]+\.prefetch\.rsc)$/,
'__$1'
);
}
return pathData;
};
if (outputPathData || outputPathPrefetchData) {
const prerender = new Prerender({
prerenders[normalizedPathData] = new Prerender({
expiration: initialRevalidate,
lambda,
allowQuery,
@@ -2508,30 +2510,21 @@ export const onPrerenderRoute =
...initialHeaders,
'content-type': rscContentTypeHeader,
vary: rscVaryHeader,
...(postponedPrerender && rscDidPostponeHeader
// If it contains a pre-render, then it was postponed.
...(prerender && rscDidPostponeHeader
? { [rscDidPostponeHeader]: '1' }
: {}),
},
}
: {}),
});
if (outputPathPrefetchData) {
prerenders[normalizePathData(outputPathPrefetchData)] = prerender;
}
// If experimental ppr is not enabled for this route, then add the data
// route as a target for the prerender as well.
if (outputPathData && !experimentalPPR) {
prerenders[normalizePathData(outputPathData)] = prerender;
}
}
// we need to ensure all prerenders have a matching .rsc output
// otherwise routing could fall through unexpectedly for the
// fallback: false case as it doesn't have a dynamic route
// to catch the `.rsc` request for app -> pages routing
if (outputPathData?.endsWith('.json') && appDir) {
if (outputPrerenderPathData?.endsWith('.json') && appDir) {
const dummyOutput = new FileBlob({
data: '{}',
contentType: 'application/json',
@@ -2696,10 +2689,19 @@ export function getNextServerPath(nextVersion: string) {
: 'next/dist/next-server/server';
}
function pathnameToOutputName(entryDirectory: string, pathname: string) {
function pathnameToOutputName(
entryDirectory: string,
pathname: string,
addedIndexSuffix = false
) {
if (pathname === '/') {
pathname = '/index';
}
// If the `/index` was added for a route that ended in `/index` we need to
// strip the second one off before joining it with the entryDirectory.
else if (addedIndexSuffix) {
pathname = pathname.replace(/\/index$/, '');
}
return path.posix.join(entryDirectory, pathname);
}

View File

@@ -1,6 +0,0 @@
'use server';
export async function increment(value) {
await new Promise(resolve => setTimeout(resolve, 500));
return value + 1;
}

View File

@@ -1,10 +0,0 @@
export default function Root({ children }) {
return (
<html>
<head>
<title>Hello World</title>
</head>
<body>{children}</body>
</html>
);
}

View File

@@ -1,25 +0,0 @@
"use client";
import { useState } from "react";
import { increment } from "../actions";
export default function Home() {
const [count, setCount] = useState(0);
return (
<div>
{count}
<button
onClick={async () => {
const actionResult = await increment(count);
// @ts-ignore
setCount(actionResult);
console.log(actionResult);
}}
>
Trigger
</button>
Static
</div>
);
}

View File

@@ -1,55 +0,0 @@
/* eslint-env jest */
const path = require('path');
const { deployAndTest } = require('../../utils');
const fetch = require('../../../../../test/lib/deployment/fetch-retry');
const ctx = {};
function findActionId(page, runtime) {
page = `app${page}/page`; // add /app prefix and /page suffix
for (const [actionId, details] of Object.entries(
ctx.actionManifest[runtime]
)) {
if (details.workers[page]) {
return actionId;
}
}
throw new Error("Couldn't find action ID");
}
describe(`${__dirname.split(path.sep).pop()}`, () => {
beforeAll(async () => {
const info = await deployAndTest(__dirname);
const actionManifest = await fetch(
`${info.deploymentUrl}/server-reference-manifest.json`
).then(res => res.json());
ctx.actionManifest = actionManifest;
Object.assign(ctx, info);
});
it('should work when there is a rewrite targeting the root page', async () => {
const actionId = findActionId('/static', 'node');
const res = await fetch(ctx.deploymentUrl, {
method: 'POST',
body: JSON.stringify([1337]),
headers: {
'Content-Type': 'text/plain;charset=UTF-8',
'Next-Action': actionId,
},
});
expect(res.status).toEqual(200);
expect(res.headers.get('x-matched-path')).toBe('/static/');
expect(res.headers.get('x-vercel-cache')).toBe('BYPASS');
const body = await res.text();
// The action incremented the provided count by 1
expect(body).toContain('1338');
});
});

View File

@@ -1,10 +0,0 @@
module.exports = {
rewrites() {
return [
{
source: '/:path*',
destination: '/static/:path*',
},
];
},
};

View File

@@ -1,9 +0,0 @@
{
"dependencies": {
"next": "canary"
},
"scripts": {
"build": "next build && cp .next/server/server-reference-manifest.json public/"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,14 +0,0 @@
{
"builds": [
{
"src": "package.json",
"use": "@vercel/next"
}
],
"build": {
"env": {
"NEXT_EXPERIMENTAL_STREAMING_ACTIONS": "1"
}
},
"probes": []
}

View File

@@ -1,25 +0,0 @@
"use client";
import { useState } from "react";
import { increment } from "../../actions";
export default function Home() {
const [count, setCount] = useState(0);
return (
<div>
{count}
<button
onClick={async () => {
const actionResult = await increment(count);
// @ts-ignore
setCount(actionResult);
console.log(actionResult);
}}
>
Trigger
</button>
Static
</div>
);
}

View File

@@ -1,25 +0,0 @@
"use client";
import { useState } from "react";
import { increment } from "./actions";
export default function Home() {
const [count, setCount] = useState(0);
return (
<div>
{count}
<button
onClick={async () => {
const actionResult = await increment(count);
// @ts-ignore
setCount(actionResult);
console.log(actionResult);
}}
>
Trigger
</button>
Static
</div>
);
}

View File

@@ -1,25 +0,0 @@
"use client";
import { useState } from "react";
import { increment } from "../actions";
export default function Home() {
const [count, setCount] = useState(0);
return (
<div>
{count}
<button
onClick={async () => {
const actionResult = await increment(count);
// @ts-ignore
setCount(actionResult);
console.log(actionResult);
}}
>
Trigger
</button>
Static
</div>
);
}

View File

@@ -15,8 +15,7 @@ function findActionId(page, runtime) {
return actionId;
}
}
throw new Error("Couldn't find action ID");
return null;
}
function generateFormDataPayload(actionId) {
@@ -274,100 +273,6 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
expect(body).toContain(JSON.stringify(['id', '1', 'd']));
expect(body).not.toContain(JSON.stringify(['id', '1.action', 'd']));
});
it('should work when a rewrite targets an action', async () => {
const targetPath = `${basePath}/rsc/static`;
const canonicalPath = `/rewrite/${basePath}/rsc/static`;
const actionId = findActionId(targetPath, runtime);
const res = await fetch(
`${ctx.deploymentUrl}${canonicalPath}`,
generateFormDataPayload(actionId)
);
expect(res.status).toEqual(200);
expect(res.headers.get('x-matched-path')).toBe(targetPath + '.action');
expect(res.headers.get('content-type')).toBe('text/x-component');
if (runtime === 'node') {
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
} else {
expect(res.headers.get('x-edge-runtime')).toBe('1');
}
});
it('should work when a rewrite greedy matches an action rewrite', async () => {
const targetPath = `${basePath}/static`;
const canonicalPath = `/greedy-rewrite/${basePath}/static`;
const actionId = findActionId(targetPath, runtime);
const res = await fetch(
`${ctx.deploymentUrl}${canonicalPath}`,
generateFormDataPayload(actionId)
);
expect(res.status).toEqual(200);
expect(res.headers.get('x-matched-path')).toBe(targetPath + '.action');
expect(res.headers.get('content-type')).toBe('text/x-component');
if (runtime === 'node') {
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
} else {
expect(res.headers.get('x-edge-runtime')).toBe('1');
}
});
it('should work on the index route', async () => {
const canonicalPath = '/';
const actionId = findActionId('', 'node');
const res = await fetch(
`${ctx.deploymentUrl}${canonicalPath}`,
generateFormDataPayload(actionId)
);
expect(res.status).toEqual(200);
expect(res.headers.get('x-matched-path')).toBe('/index.action');
expect(res.headers.get('content-type')).toBe('text/x-component');
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
});
});
describe('rewrite to index', () => {
it('should work when user has a rewrite to the index route', async () => {
const canonicalPath = '/rewritten-to-index';
const actionId = findActionId('', 'node');
const res = await fetch(
`${ctx.deploymentUrl}${canonicalPath}`,
generateFormDataPayload(actionId)
);
expect(res.status).toEqual(200);
expect(res.headers.get('x-matched-path')).toBe('/index.action');
expect(res.headers.get('content-type')).toBe('text/x-component');
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
});
it('should work when entire path is rewritten', async () => {
const actionId = findActionId('/static', 'node');
const res = await fetch(ctx.deploymentUrl, {
method: 'POST',
body: JSON.stringify([1337]),
headers: {
'Content-Type': 'text/plain;charset=UTF-8',
'Next-Action': actionId,
'x-rewrite-me': '1',
},
});
expect(res.status).toEqual(200);
expect(res.headers.get('x-matched-path')).toBe('/index.action');
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
const body = await res.text();
// The action incremented the provided count by 1
expect(body).toContain('1338');
});
});
describe('pages', () => {

View File

@@ -1,36 +1 @@
module.exports = {
rewrites() {
return [
{
source: '/rewrite/rsc/static',
destination: '/rsc/static',
},
{
source: '/rewrite/edge/rsc/static',
destination: '/edge/rsc/static',
},
{
source: '/greedy-rewrite/static/:path*',
destination: '/static/:path*',
},
{
source: '/greedy-rewrite/edge/static/:path*',
destination: '/edge/static/:path*',
},
{
source: '/rewritten-to-index',
destination: '/?fromRewrite=1',
},
{
source: '/:path*',
destination: '/static/:path*',
has: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
},
];
},
};
module.exports = {};

View File

@@ -1,14 +0,0 @@
import Link from 'next/link';
const Page = ({ params }) => {
return (
<div>
<div id="page-param">page-param-{params.slug?.[0] ?? ''}</div>
<Link href="/">Home</Link>
<Link href="/foo">Foo</Link>
<Link href="/bar">Bar</Link>
</div>
);
};
export default Page;

View File

@@ -1,10 +0,0 @@
export default function Root({ children }) {
return (
<html>
<head>
<title>Hello World</title>
</head>
<body>{children}</body>
</html>
);
}

View File

@@ -1,12 +0,0 @@
/* eslint-env jest */
const path = require('path');
const { deployAndTest } = require('../../utils');
const ctx = {};
describe(`${__dirname.split(path.sep).pop()}`, () => {
it('should deploy and pass probe checks', async () => {
const info = await deployAndTest(__dirname);
Object.assign(ctx, info);
});
});

View File

@@ -1 +0,0 @@
module.exports = {};

View File

@@ -1,8 +0,0 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,27 +0,0 @@
{
"builds": [
{
"src": "package.json",
"use": "@vercel/next"
}
],
"probes": [
{
"path": "/",
"status": 200,
"mustContain": "\"page-param-\",\"\"",
"mustNotContain": "\"page-param-\",\"index\"",
"headers": {
"RSC": "1"
}
},
{
"path": "/foo",
"status": 200,
"mustContain": "\"page-param-\",\"foo\"",
"headers": {
"RSC": "1"
}
}
]
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true,
"scripts": {

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -7,8 +7,8 @@
},
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,3 +0,0 @@
export default function Page() {
return <div id="sentinel:static">Static</div>;
}

View File

@@ -4,7 +4,8 @@ const { deployAndTest } = require('../../utils');
const ctx = {};
describe(`${__dirname.split(path.sep).pop()}`, () => {
// TODO: investigate invariant
describe.skip(`${__dirname.split(path.sep).pop()}`, () => {
it('should deploy and pass probe checks', async () => {
const info = await deployAndTest(__dirname);
Object.assign(ctx, info);

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -56,28 +56,6 @@
"status": 200,
"mustContain": "sentinel:dynamic"
},
{
"path": "/static",
"status": 200,
"mustContain": "sentinel:static"
},
{
"path": "/static",
"status": 200,
"mustContain": "sentinel:static",
"headers": {
"RSC": "1"
}
},
{
"path": "/static",
"status": 200,
"mustContain": "sentinel:static",
"headers": {
"RSC": "1",
"Next-Router-Prefetch": "1"
}
},
{
"path": "/disabled",
"headers": {
@@ -85,7 +63,7 @@
"Next-Router-Prefetch": "1"
},
"status": 200,
"mustNotContain": "sentinel:dynamic"
"mustContain": "sentinel:dynamic"
},
{
"path": "/disabled",

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,3 +1,7 @@
export const metadata = {
metadataBase: new URL(process.env.VERCEL_PROJECT_PRODUCTION_URL ?? 'http://localhost:3000'),
};
export default function Root({ children }) {
return (
<html className="this-is-the-document-html">

View File

@@ -17,10 +17,6 @@ module.exports = {
source: '/to-product/:productId.html',
destination: '/products/:productId',
},
{
source: '/greedy-rewrite/test-page/:path*',
destination: '/test-page/:path*',
}
];
},
};

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -429,31 +429,6 @@
},
"mustContain": ":{",
"mustNotContain": "<html"
},
{
"path": "/greedy-rewrite/test-page",
"status": 200,
"mustContain": ":{",
"mustNotContain": "<html",
"responseHeaders": {
"x-matched-path": "/test-page.rsc"
},
"headers": {
"RSC": "1"
}
},
{
"path": "/greedy-rewrite/test-page",
"status": 200,
"mustContain": ":{",
"mustNotContain": "<html",
"responseHeaders": {
"x-matched-path": "/test-page.rsc"
},
"headers": {
"RSC": "1",
"Next-Router-Prefetch": "1"
}
}
]
}

View File

@@ -7,8 +7,8 @@
},
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"devDependencies": {
"@types/node": "20.4.5",

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,3 +0,0 @@
export default function Page() {
return <p>static page</p>;
}

View File

@@ -14,10 +14,6 @@ module.exports = {
source: '/rewritten-to-index',
destination: '/?fromRewrite=1',
},
{
source: '/greedy-rewrite/test-page/:path*',
destination: '/test-page/:path*',
}
];
},
};

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -349,55 +349,6 @@
"path": "/api/pages-headers",
"status": 200,
"mustContain": "{\"port\":\"443\"}"
},
{
"path": "/greedy-rewrite/test-page",
"status": 200,
"mustContain": ":{",
"mustNotContain": "<html",
"responseHeaders": {
"x-matched-path": "/test-page.rsc"
},
"headers": {
"RSC": 1
}
},
{
"path": "/greedy-rewrite/test-page",
"status": 200,
"mustContain": ":{",
"mustNotContain": "<html",
"responseHeaders": {
"x-matched-path": "/test-page.prefetch.rsc"
},
"headers": {
"RSC": "1",
"Next-Router-Prefetch": "1"
}
},
{
"path": "/static",
"status": 200,
"mustContain": "static page"
},
{
"path": "/static",
"status": 200,
"headers": {
"RSC": "1"
},
"mustContain": ":{",
"mustNotContain": "<html"
},
{
"path": "/static",
"status": 200,
"headers": {
"RSC": "1",
"Next-Router-Prefetch": "1"
},
"mustContain": ":{",
"mustNotContain": "<html"
}
]
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -10,8 +10,8 @@
},
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -5,8 +5,8 @@
},
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -6,8 +6,8 @@
},
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -9,8 +9,8 @@
},
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -1,8 +1,8 @@
{
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

View File

@@ -8,8 +8,8 @@
},
"dependencies": {
"next": "canary",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522"
"react": "19.0.0-beta-4508873393-20240430",
"react-dom": "19.0.0-beta-4508873393-20240430"
},
"ignoreNextjsUpdates": true
}

Some files were not shown because too many files have changed in this diff Show More