mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 12:57:46 +00:00
Compare commits
63 Commits
vercel@21.
...
@vercel/py
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b60467d2f | ||
|
|
4384a6104f | ||
|
|
f40f95ff37 | ||
|
|
90c05250b0 | ||
|
|
030880fe74 | ||
|
|
02bc88f33b | ||
|
|
38ff557cad | ||
|
|
47c34842d5 | ||
|
|
d21b215ad0 | ||
|
|
5827737fd5 | ||
|
|
a9e078d410 | ||
|
|
b4d9b17fb8 | ||
|
|
02c55bf634 | ||
|
|
08af15055f | ||
|
|
0597aaa5e4 | ||
|
|
176856a1ea | ||
|
|
375a55ebed | ||
|
|
7d33a05581 | ||
|
|
0377c8b737 | ||
|
|
662d546388 | ||
|
|
8c514b5608 | ||
|
|
a6ec53d9d3 | ||
|
|
3ad5903f70 | ||
|
|
3cf155e999 | ||
|
|
d9a298d97c | ||
|
|
487d3c8554 | ||
|
|
9d0bfd3656 | ||
|
|
ec75333569 | ||
|
|
51aab912a2 | ||
|
|
670b2653c0 | ||
|
|
f71686fdad | ||
|
|
ec9c8ce150 | ||
|
|
a2048fc6d3 | ||
|
|
09ff9cda9f | ||
|
|
3a4d6f7848 | ||
|
|
9a0d676c0d | ||
|
|
25cd7b9e6e | ||
|
|
f926d5516c | ||
|
|
4603383850 | ||
|
|
c0c57889c8 | ||
|
|
85908a0524 | ||
|
|
503b9a2429 | ||
|
|
eac8f32ae7 | ||
|
|
3f76fefde6 | ||
|
|
79ddc5746b | ||
|
|
9a14615b43 | ||
|
|
6d6ccbdc25 | ||
|
|
704424ec58 | ||
|
|
c471127c69 | ||
|
|
c02dc9ac49 | ||
|
|
dd10e8cc77 | ||
|
|
cf69c2398c | ||
|
|
e48707571f | ||
|
|
6051fe6f0c | ||
|
|
2b3ba8a14f | ||
|
|
25bea3f83e | ||
|
|
b3e1828ebe | ||
|
|
e0e2a8e87e | ||
|
|
37ec89796d | ||
|
|
d3e2a4c4db | ||
|
|
ece3645914 | ||
|
|
fee386493b | ||
|
|
d95ed184ab |
9
.github/CONTRIBUTING.md
vendored
9
.github/CONTRIBUTING.md
vendored
@@ -94,12 +94,3 @@ Sometimes you want to test changes to a Builder against an existing project, may
|
||||
4. Run `vercel *.tgz` to upload the tarball file and get a URL
|
||||
5. Edit any existing `vercel.json` project and replace `use` with the URL
|
||||
6. Run `vercel` or `vercel dev` to deploy with the experimental Builder
|
||||
|
||||
## Add a New Framework
|
||||
|
||||
You can add support for a new Framework by creating a Pull Request for this repository and following the steps below:
|
||||
|
||||
1. Add the Framework to the `@vercel/frameworks` package: The file is located in `./packages/frameworks/frameworks.json`. You can copy the structure of an existing one and adjust the required fields. Note that the `settings` property either contains a `value` or a `placeholder`. The `value` property is used when something is not configurable, the `placeholder` is used when something is configurable and can be changed with configuration. An example would be the Output Directory for Hugo, it's `public` by default but can be changed through its config file, so we use `placeholder` with an explanation of what can be used.
|
||||
2. Add an example to the `./examples` directory: The name of the directory should equal the slug of the framework used in `@vercel/frameworks`. The `.github/EXAMPLE_README_TEMPLATE.md` file can be used to create a `README.md` file for the example.
|
||||
3. Update the `@vercel/static-build` package: The file `./packages/now-static-build/src/frameworks.ts` has to be extended. You can add default routes that will always be applied to projects that use this Framework or specify some paths that will be cached to speed up the build process.
|
||||
4. After your Pull Request has been merged and released, other users can select the example on the Vercel dashboard and deploy it.
|
||||
|
||||
@@ -6,5 +6,5 @@ You're running Vercel CLI in a non-terminal context and there are no credentials
|
||||
|
||||
#### Possible Ways to Fix It
|
||||
|
||||
- Specify a value for the `--token` flag (this needs to be the token of the user account as which you'd like to act). You can either get the token from the `./vercel/auth.json` file located in your user directory or [from the dashboard](https://vercel.com/account/tokens).
|
||||
- Ensure that both `~/vercel/auth.json` and `~/vercel/config.json` exist
|
||||
- Specify a value for the `--token` flag (this needs to be the token of the user account as which you'd like to act). You can create a new token on your [Settings page](https://vercel.com/account/tokens).
|
||||
- Run `vercel login` to sign in and generate a new token
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NowRequest, NowResponse } from '@now/node';
|
||||
import { NowRequest, NowResponse } from '@vercel/node';
|
||||
|
||||
export default (_req: NowRequest, res: NowResponse) => {
|
||||
const date = new Date().toString();
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"react-helmet": "^5.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@now/node": "^1.3.0"
|
||||
"@vercel/node": "1.8.5"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "gatsby develop",
|
||||
|
||||
@@ -1107,15 +1107,6 @@
|
||||
"@nodelib/fs.scandir" "2.1.3"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@now/node@^1.3.0":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@now/node/-/node-1.7.1.tgz#764a0c6bcb24967f8014c4f73ad238c292996fe3"
|
||||
integrity sha512-+srVKopsVTPDR3u9eOjJryZroLTrPp8XEOuIDGBdfFcJuS7qpAomctSbfyA7WNyjC0ExtUxELqBg5sAedG5+2g==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
ts-node "8.9.1"
|
||||
typescript "3.9.3"
|
||||
|
||||
"@pieh/friendly-errors-webpack-plugin@1.7.0-chalk-2":
|
||||
version "1.7.0-chalk-2"
|
||||
resolved "https://registry.yarnpkg.com/@pieh/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0-chalk-2.tgz#2e9da9d3ade9d18d013333eb408c457d04eabac0"
|
||||
@@ -1409,6 +1400,15 @@
|
||||
dependencies:
|
||||
wonka "^4.0.14"
|
||||
|
||||
"@vercel/node@1.8.5":
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/@vercel/node/-/node-1.8.5.tgz#2c8b9532f1bb25734a9964c52973386ed78022d4"
|
||||
integrity sha512-1iw7FSR8Oau6vZB1MWfBnA5q2a/IqRHiSZSbt8lz0dyTF599q8pc5GcSv/TvmrYaEGzh3+N0S4cbmuMCqVlwJg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
ts-node "8.9.1"
|
||||
typescript "3.9.3"
|
||||
|
||||
"@webassemblyjs/ast@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
|
||||
|
||||
@@ -14,6 +14,10 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the
|
||||
|
||||
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
|
||||
|
||||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
|
||||
|
||||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "10.0.0",
|
||||
"next": "10.0.5",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1"
|
||||
}
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
max-width: 800px;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "2.6.1-canary.0",
|
||||
"version": "2.7.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -43,9 +43,8 @@ export function sortFiles(fileA: string, fileB: string) {
|
||||
export function detectApiExtensions(builders: Builder[]): Set<string> {
|
||||
return new Set<string>(
|
||||
builders
|
||||
.filter(
|
||||
b =>
|
||||
b.config && b.config.zeroConfig && b.src && b.src.startsWith('api/')
|
||||
.filter((b): b is Builder & { src: string } =>
|
||||
Boolean(b.config && b.config.zeroConfig && b.src?.startsWith('api/'))
|
||||
)
|
||||
.map(b => extname(b.src))
|
||||
.filter(Boolean)
|
||||
@@ -56,22 +55,28 @@ export function detectApiDirectory(builders: Builder[]): string | null {
|
||||
// TODO: We eventually want to save the api directory to
|
||||
// builder.config.apiDirectory so it is only detected once
|
||||
const found = builders.some(
|
||||
b => b.config && b.config.zeroConfig && b.src.startsWith('api/')
|
||||
b => b.config && b.config.zeroConfig && b.src?.startsWith('api/')
|
||||
);
|
||||
return found ? 'api' : null;
|
||||
}
|
||||
|
||||
// TODO: Replace this function with `config.outputDirectory`
|
||||
function getPublicBuilder(builders: Builder[]): Builder | null {
|
||||
const builder = builders.find(
|
||||
builder =>
|
||||
function getPublicBuilder(
|
||||
builders: Builder[]
|
||||
): (Builder & { src: string }) | null {
|
||||
for (const builder of builders) {
|
||||
if (
|
||||
typeof builder.src === 'string' &&
|
||||
isOfficialRuntime('static', builder.use) &&
|
||||
/^.*\/\*\*\/\*$/.test(builder.src) &&
|
||||
builder.config &&
|
||||
builder.config.zeroConfig === true
|
||||
);
|
||||
) {
|
||||
return builder as Builder & { src: string };
|
||||
}
|
||||
}
|
||||
|
||||
return builder || null;
|
||||
return null;
|
||||
}
|
||||
export function detectOutputDirectory(builders: Builder[]): string | null {
|
||||
// TODO: We eventually want to save the output directory to
|
||||
@@ -361,7 +366,7 @@ function maybeGetApiBuilder(
|
||||
return null;
|
||||
}
|
||||
|
||||
const match = apiMatches.find(({ src }) => {
|
||||
const match = apiMatches.find(({ src = '**' }) => {
|
||||
return src === fileName || minimatch(fileName, src);
|
||||
});
|
||||
|
||||
|
||||
@@ -292,6 +292,11 @@ export async function runNpmInstall(
|
||||
opts.prettyCommand = 'yarn install';
|
||||
command = 'yarn';
|
||||
commandArgs = ['install', ...args];
|
||||
|
||||
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
|
||||
if (!env.YARN_NODE_LINKER) {
|
||||
env.YARN_NODE_LINKER = 'node-modules';
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NPM_ONLY_PRODUCTION) {
|
||||
@@ -388,10 +393,17 @@ export async function runPackageJsonScript(
|
||||
prettyCommand,
|
||||
});
|
||||
} else {
|
||||
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
|
||||
const env: typeof process.env = { ...spawnOpts?.env };
|
||||
if (!env.YARN_NODE_LINKER) {
|
||||
env.YARN_NODE_LINKER = 'node-modules';
|
||||
}
|
||||
|
||||
const prettyCommand = `yarn run ${scriptName}`;
|
||||
console.log(`Running "${prettyCommand}"`);
|
||||
await spawnAsync('yarn', ['run', scriptName], {
|
||||
...spawnOpts,
|
||||
env,
|
||||
cwd: destPath,
|
||||
prettyCommand,
|
||||
});
|
||||
|
||||
@@ -336,7 +336,7 @@ export interface NodeVersion {
|
||||
|
||||
export interface Builder {
|
||||
use: string;
|
||||
src: string;
|
||||
src?: string;
|
||||
config?: Config;
|
||||
}
|
||||
|
||||
|
||||
5
packages/now-build-utils/test/fixtures/19-yarn-v2/api/index.js
vendored
Normal file
5
packages/now-build-utils/test/fixtures/19-yarn-v2/api/index.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const { camelCase } = require('camel-case');
|
||||
|
||||
module.exports = (req, res) => {
|
||||
res.end(camelCase('camel-case module is working'));
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
|
||||
"probes": [{ "path": "/", "mustContain": "Svelte app" }]
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
"svelte": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camel-case": "^4.1.2",
|
||||
"sirv-cli": "^0.4.4"
|
||||
}
|
||||
}
|
||||
|
||||
11
packages/now-build-utils/test/fixtures/19-yarn-v2/vercel.json
vendored
Normal file
11
packages/now-build-utils/test/fixtures/19-yarn-v2/vercel.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{ "src": "package.json", "use": "@vercel/static-build" },
|
||||
{ "src": "api/index.js", "use": "@vercel/node" }
|
||||
],
|
||||
"probes": [
|
||||
{ "path": "/", "mustContain": "Svelte app" },
|
||||
{ "path": "/api", "mustContain": "camelCaseModuleIsWorking" }
|
||||
]
|
||||
}
|
||||
@@ -270,6 +270,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"camel-case@npm:^4.1.2":
|
||||
version: 4.1.2
|
||||
resolution: "camel-case@npm:4.1.2"
|
||||
dependencies:
|
||||
pascal-case: ^3.1.2
|
||||
tslib: ^2.0.3
|
||||
checksum: 3/0b8dcfb424c9497e45984b88ef005c66bdf8e877e36365aedfc3cf73182684fde5a14cf2c526579c0351a5f27dc39a00f1edecc25d43606075fea948c504e37f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"caseless@npm:~0.12.0":
|
||||
version: 0.12.0
|
||||
resolution: "caseless@npm:0.12.0"
|
||||
@@ -850,6 +860,15 @@ fsevents@~2.1.2:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lower-case@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "lower-case@npm:2.0.2"
|
||||
dependencies:
|
||||
tslib: ^2.0.3
|
||||
checksum: 3/aabaca9cef65f7564a1005b625664527e4d169e363101e65773f8f6ff2fdcf09884a3bc02990cd7a62cf05f3538114af25ee7bef553f1ca3208c8a77ac75cbfa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"magic-string@npm:^0.25.2":
|
||||
version: 0.25.7
|
||||
resolution: "magic-string@npm:0.25.7"
|
||||
@@ -944,6 +963,16 @@ fsevents@~2.1.2:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"no-case@npm:^3.0.4":
|
||||
version: 3.0.4
|
||||
resolution: "no-case@npm:3.0.4"
|
||||
dependencies:
|
||||
lower-case: ^2.0.2
|
||||
tslib: ^2.0.3
|
||||
checksum: 3/84db4909caec37504c6655f995a004067f8733be8cd8d849f1578661b60a1685e086325fa4e1a5e8ce94e7416c1d0f037e2a00f635a14457183de80ab4fc7612
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-gyp@npm:latest":
|
||||
version: 6.1.0
|
||||
resolution: "node-gyp@npm:6.1.0"
|
||||
@@ -1057,6 +1086,16 @@ fsevents@~2.1.2:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pascal-case@npm:^3.1.2":
|
||||
version: 3.1.2
|
||||
resolution: "pascal-case@npm:3.1.2"
|
||||
dependencies:
|
||||
no-case: ^3.0.4
|
||||
tslib: ^2.0.3
|
||||
checksum: 3/31708cecab221482edc81e2bd9b9d8282d72d4f1443b31f39725aa23768c5e42d93c4c014f1bc90f7f074e2a70d5091e4892ea370e550affc9ccf1d33c900bcd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-is-absolute@npm:^1.0.0":
|
||||
version: 1.0.1
|
||||
resolution: "path-is-absolute@npm:1.0.1"
|
||||
@@ -1447,6 +1486,7 @@ fsevents@~2.1.2:
|
||||
dependencies:
|
||||
"@rollup/plugin-commonjs": ^12.0.0
|
||||
"@rollup/plugin-node-resolve": ^8.0.0
|
||||
camel-case: ^4.1.2
|
||||
rollup: ^2.3.4
|
||||
rollup-plugin-livereload: ^1.0.0
|
||||
rollup-plugin-svelte: ^5.0.3
|
||||
@@ -1517,6 +1557,13 @@ fsevents@~2.1.2:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tslib@npm:^2.0.3":
|
||||
version: 2.0.3
|
||||
resolution: "tslib@npm:2.0.3"
|
||||
checksum: 3/447bfca5deaa157806c3f77eaba74d05dd0b38b014e47ce79d98b5c77ce7d91b00a687ba13ca1b5a74d35ca1098ac7a072c0a97fad06f0266612f2a03a6c8e8f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tunnel-agent@npm:^0.6.0":
|
||||
version: 0.6.0
|
||||
resolution: "tunnel-agent@npm:0.6.0"
|
||||
|
||||
@@ -182,7 +182,7 @@ describe('Test `detectBuilders`', () => {
|
||||
|
||||
const { builders } = await detectBuilders(files);
|
||||
expect(builders!.length).toBe(7);
|
||||
expect(builders!.some(b => b.src.endsWith('_test.go'))).toBe(false);
|
||||
expect(builders!.some(b => b.src!.endsWith('_test.go'))).toBe(false);
|
||||
});
|
||||
|
||||
it('just public', async () => {
|
||||
@@ -1341,7 +1341,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
|
||||
featHandleMiss,
|
||||
});
|
||||
expect(builders!.length).toBe(7);
|
||||
expect(builders!.some(b => b.src.endsWith('_test.go'))).toBe(false);
|
||||
expect(builders!.some(b => b.src!.endsWith('_test.go'))).toBe(false);
|
||||
expect(errorRoutes!.length).toBe(1);
|
||||
expect((errorRoutes![0] as Source).status).toBe(404);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "21.0.1",
|
||||
"version": "21.1.0",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -61,11 +61,11 @@
|
||||
"node": ">= 10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.6.1-canary.0",
|
||||
"@vercel/go": "1.1.6",
|
||||
"@vercel/node": "1.8.5",
|
||||
"@vercel/python": "1.2.3",
|
||||
"@vercel/ruby": "1.2.4",
|
||||
"@vercel/build-utils": "2.7.0",
|
||||
"@vercel/go": "1.1.7",
|
||||
"@vercel/node": "1.9.0",
|
||||
"@vercel/python": "1.2.4",
|
||||
"@vercel/ruby": "1.2.5",
|
||||
"update-notifier": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -51,12 +51,6 @@ const help = () => {
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} ls my-app`)}
|
||||
|
||||
${chalk.gray(
|
||||
'–'
|
||||
)} List all deployments and all instances for the app ${chalk.dim('`my-app`')}
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} ls my-app --all`)}
|
||||
|
||||
${chalk.gray('–')} Filter deployments by metadata
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} ls -m key1=value1 -m key2=value2`)}
|
||||
|
||||
@@ -324,7 +324,7 @@ function printLogRaw(log) {
|
||||
|
||||
if (log.object) {
|
||||
console.log(log.object);
|
||||
} else {
|
||||
} else if (typeof log.text === 'string') {
|
||||
console.log(
|
||||
log.text
|
||||
.replace(/\n$/, '')
|
||||
|
||||
@@ -231,6 +231,7 @@ export interface ProjectSettings {
|
||||
outputDirectory?: string | null;
|
||||
rootDirectory?: string | null;
|
||||
autoExposeSystemEnvs?: boolean;
|
||||
directoryListing?: boolean;
|
||||
}
|
||||
|
||||
export interface Project extends ProjectSettings {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import chalk from 'chalk';
|
||||
import execa from 'execa';
|
||||
import semver from 'semver';
|
||||
import npa from 'npm-package-arg';
|
||||
@@ -8,9 +9,10 @@ import { mkdirp, readJSON, writeJSON } from 'fs-extra';
|
||||
import { NowBuildError, PackageJson } from '@vercel/build-utils';
|
||||
import cliPkg from '../pkg';
|
||||
|
||||
import { NoBuilderCacheError } from '../errors-ts';
|
||||
import cmd from '../output/cmd';
|
||||
import { Output } from '../output';
|
||||
import { getDistTag } from '../get-dist-tag';
|
||||
import { NoBuilderCacheError } from '../errors-ts';
|
||||
|
||||
import * as staticBuilder from './static-builder';
|
||||
import { BuilderWithPackage } from './types';
|
||||
@@ -261,7 +263,9 @@ async function npmInstall(
|
||||
throw new NowBuildError({
|
||||
message:
|
||||
(result as any).code === 'ENOENT'
|
||||
? '`npm` is not installed'
|
||||
? `Command not found: ${chalk.cyan(
|
||||
'npm'
|
||||
)}\nPlease ensure that ${cmd('npm')} is properly installed`
|
||||
: 'Failed to install `vercel dev` dependencies',
|
||||
code: 'NPM_INSTALL_ERROR',
|
||||
link: 'https://vercel.link/npm-install-failed-dev',
|
||||
|
||||
@@ -402,7 +402,7 @@ export async function getBuildMatches(
|
||||
const builds = nowConfig.builds || [{ src: '**', use: '@vercel/static' }];
|
||||
|
||||
for (const buildConfig of builds) {
|
||||
let { src, use } = buildConfig;
|
||||
let { src = '**', use } = buildConfig;
|
||||
|
||||
if (!use) {
|
||||
continue;
|
||||
|
||||
@@ -43,6 +43,7 @@ import {
|
||||
} from '@vercel/build-utils';
|
||||
import _frameworks, { Framework } from '@vercel/frameworks';
|
||||
|
||||
import cmd from '../output/cmd';
|
||||
import link from '../output/link';
|
||||
import { Output } from '../output';
|
||||
import { relative } from '../path-helpers';
|
||||
@@ -650,7 +651,7 @@ export default class DevServer {
|
||||
const cloudEnv = exposeSystemEnvs(
|
||||
this.projectEnvs || [],
|
||||
this.systemEnvValues || [],
|
||||
this.projectSettings && this.projectSettings.autoExposeSystemEnvs,
|
||||
this.projectSettings?.autoExposeSystemEnvs,
|
||||
new URL(this.address).host
|
||||
);
|
||||
|
||||
@@ -667,7 +668,7 @@ export default class DevServer {
|
||||
// mirror how VERCEL_REGION is injected in prod/preview
|
||||
// only inject in `runEnvs`, because `allEnvs` is exposed to dev command
|
||||
// and should not contain VERCEL_REGION
|
||||
if (this.projectSettings && this.projectSettings.autoExposeSystemEnvs) {
|
||||
if (this.projectSettings?.autoExposeSystemEnvs) {
|
||||
runEnv['VERCEL_REGION'] = 'dev1';
|
||||
}
|
||||
|
||||
@@ -886,7 +887,7 @@ export default class DevServer {
|
||||
})
|
||||
.catch(err => {
|
||||
this.updateBuildersPromise = null;
|
||||
this.output.error(`Failed to update builders: ${err.message}`);
|
||||
this.output.prettyError(err);
|
||||
this.output.debug(err.stack);
|
||||
});
|
||||
}, ms('30s'));
|
||||
@@ -1681,7 +1682,16 @@ export default class DevServer {
|
||||
// `startDevServer()` threw an error. Most likely this means the dev
|
||||
// server process exited before sending the port information message
|
||||
// (missing dependency at runtime, for example).
|
||||
debug(`Error starting "${builderPkg.name}" dev server: ${err}`);
|
||||
if (err.code === 'ENOENT') {
|
||||
err.message = `Command not found: ${chalk.cyan(
|
||||
err.path,
|
||||
...err.spawnargs
|
||||
)}\nPlease ensure that ${cmd(err.path)} is properly installed`;
|
||||
err.link = 'https://vercel.link/command-not-found';
|
||||
}
|
||||
|
||||
this.output.prettyError(err);
|
||||
|
||||
await this.sendError(
|
||||
req,
|
||||
res,
|
||||
@@ -1894,6 +1904,12 @@ export default class DevServer {
|
||||
requestPath: string,
|
||||
nowRequestId: string
|
||||
): boolean {
|
||||
// If the "directory listing" feature is disabled in the
|
||||
// Project's settings, then don't render the directory listing
|
||||
if (this.projectSettings?.directoryListing === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let prefix = requestPath;
|
||||
if (prefix.length > 0 && !prefix.endsWith('/')) {
|
||||
prefix += '/';
|
||||
|
||||
@@ -50,6 +50,7 @@ export interface EnvConfigs {
|
||||
|
||||
export interface BuildMatch extends BuildConfig {
|
||||
entrypoint: string;
|
||||
src: string;
|
||||
builderWithPkg: BuilderWithPackage;
|
||||
buildOutput: BuilderOutputs;
|
||||
buildResults: Map<string | null, BuildResult>;
|
||||
|
||||
4
packages/now-cli/test/dev/fixtures/missing-src-property/.gitignore
vendored
Normal file
4
packages/now-cli/test/dev/fixtures/missing-src-property/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
package.json
|
||||
yarn.lock
|
||||
.now
|
||||
.vercel
|
||||
@@ -0,0 +1 @@
|
||||
hello:index.txt
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"builds": [
|
||||
{
|
||||
"use": "@vercel/static"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -232,7 +232,7 @@ async function testFixture(directory, opts = {}, args = []) {
|
||||
function testFixtureStdio(
|
||||
directory,
|
||||
fn,
|
||||
{ expectedCode = 0, skipDeploy, isExample } = {}
|
||||
{ expectedCode = 0, skipDeploy, isExample, projectSettings } = {}
|
||||
) {
|
||||
return async t => {
|
||||
const nodeMajor = Number(process.versions.node.split('.')[0]);
|
||||
@@ -249,24 +249,51 @@ function testFixtureStdio(
|
||||
|
||||
// Deploy fixture and link project
|
||||
if (!skipDeploy) {
|
||||
const project = join(cwd, '.vercel', 'project.json');
|
||||
if (await fs.exists(project)) {
|
||||
await fs.unlink(project);
|
||||
}
|
||||
const projectJsonPath = join(cwd, '.vercel', 'project.json');
|
||||
await fs.remove(projectJsonPath);
|
||||
const gitignore = join(cwd, '.gitignore');
|
||||
const gitignoreOrig = await fs.exists(gitignore);
|
||||
let { stdout, stderr, exitCode } = await execa(
|
||||
binaryPath,
|
||||
['-t', token, '--confirm', '--public', '--no-clipboard', '--debug'],
|
||||
{ cwd, reject: false }
|
||||
);
|
||||
console.log({ stdout, stderr, exitCode });
|
||||
if (!gitignoreOrig && (await fs.exists(gitignore))) {
|
||||
await fs.unlink(gitignore);
|
||||
}
|
||||
t.is(exitCode, expectedCode);
|
||||
if (expectedCode === 0) {
|
||||
deploymentUrl = new URL(stdout).host;
|
||||
const hasGitignore = await fs.exists(gitignore);
|
||||
|
||||
try {
|
||||
// Run `vc link`
|
||||
const { exitCode: linkExitCode } = await execa(
|
||||
binaryPath,
|
||||
['-t', token, 'link', '--confirm'],
|
||||
{ cwd, stdio: 'inherit', reject: false }
|
||||
);
|
||||
t.is(linkExitCode, 0);
|
||||
|
||||
// Patch the project with any non-default properties
|
||||
if (projectSettings) {
|
||||
const { projectId } = await fs.readJson(projectJsonPath);
|
||||
const res = await fetch(
|
||||
`https://api.vercel.com/v2/projects/${projectId}`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify(projectSettings),
|
||||
}
|
||||
);
|
||||
t.is(res.status, 200);
|
||||
}
|
||||
|
||||
// Run `vc deploy`
|
||||
let { exitCode, stdout } = await execa(
|
||||
binaryPath,
|
||||
['-t', token, 'deploy', '--public', '--no-clipboard', '--debug'],
|
||||
{ cwd, stdio: ['ignore', 'pipe', 'inherit'], reject: false }
|
||||
);
|
||||
console.log({ exitCode, stdout });
|
||||
t.is(exitCode, expectedCode);
|
||||
if (expectedCode === 0) {
|
||||
deploymentUrl = new URL(stdout).host;
|
||||
}
|
||||
} finally {
|
||||
if (!hasGitignore) {
|
||||
await fs.remove(gitignore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,14 +649,6 @@ test(
|
||||
});
|
||||
})
|
||||
);
|
||||
/*
|
||||
test(
|
||||
'[vercel dev] displays directory listing after miss',
|
||||
testFixtureStdio('handle-miss-display-dir-list', async (testPath) => {
|
||||
await testPath(404, '/post', /one.html/m);
|
||||
})
|
||||
);
|
||||
*/
|
||||
|
||||
test(
|
||||
'[vercel dev] does not display directory listing after 404',
|
||||
@@ -1056,12 +1075,16 @@ test(
|
||||
|
||||
test(
|
||||
'[vercel dev] 00-list-directory',
|
||||
testFixtureStdio('00-list-directory', async testPath => {
|
||||
await testPath(200, '/', /Files within/m);
|
||||
await testPath(200, '/', /test[0-3]\.txt/m);
|
||||
await testPath(200, '/', /\.well-known/m);
|
||||
await testPath(200, '/.well-known/keybase.txt', 'proof goes here');
|
||||
})
|
||||
testFixtureStdio(
|
||||
'00-list-directory',
|
||||
async testPath => {
|
||||
await testPath(200, '/', /Files within/m);
|
||||
await testPath(200, '/', /test[0-3]\.txt/m);
|
||||
await testPath(200, '/', /\.well-known/m);
|
||||
await testPath(200, '/.well-known/keybase.txt', 'proof goes here');
|
||||
},
|
||||
{ projectSettings: { directoryListing: true } }
|
||||
)
|
||||
);
|
||||
|
||||
test(
|
||||
@@ -1756,3 +1779,11 @@ test(
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[vercel dev] Do not fail if `src` is missing',
|
||||
testFixtureStdio('missing-src-property', async testPath => {
|
||||
await testPath(200, '/', /hello:index.txt/m);
|
||||
await testPath(404, '/i-do-not-exist');
|
||||
})
|
||||
);
|
||||
|
||||
102
packages/now-cli/test/integration.js
vendored
102
packages/now-cli/test/integration.js
vendored
@@ -602,6 +602,41 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
t.regex(systemEnvs[0], /Production, Preview, Development/gm);
|
||||
}
|
||||
|
||||
// we create a "legacy" env variable that contains a decryptable secret
|
||||
// to check that vc env pull and vc dev work correctly with decryptable secrets
|
||||
async function createEnvWithDecryptableSecret() {
|
||||
console.log('creating an env variable with a decryptable secret');
|
||||
|
||||
const name = `my-secret${Math.floor(Math.random() * 10000)}`;
|
||||
|
||||
const res = await apiFetch('/v2/now/secrets', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
name,
|
||||
value: 'decryptable value',
|
||||
decryptable: true,
|
||||
}),
|
||||
});
|
||||
|
||||
t.is(res.status, 200);
|
||||
|
||||
const json = await res.json();
|
||||
|
||||
const link = require(path.join(target, '.vercel/project.json'));
|
||||
|
||||
const resEnv = await apiFetch(`/v4/projects/${link.projectId}/env`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
key: 'MY_DECRYPTABLE_SECRET_ENV',
|
||||
value: json.uid,
|
||||
target: ['development'],
|
||||
type: 'secret',
|
||||
}),
|
||||
});
|
||||
|
||||
t.is(resEnv.status, 200);
|
||||
}
|
||||
|
||||
async function nowEnvPull() {
|
||||
const { exitCode, stderr, stdout } = await execa(
|
||||
binaryPath,
|
||||
@@ -622,6 +657,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
t.true(lines.has('MY_PLAINTEXT_ENV_VAR="my plaintext value"'));
|
||||
t.true(lines.has('MY_STDIN_VAR="{"expect":"quotes"}"'));
|
||||
t.true(lines.has('NEXT_PUBLIC_VERCEL_URL=""'));
|
||||
t.true(lines.has('MY_DECRYPTABLE_SECRET_ENV="decryptable value"'));
|
||||
}
|
||||
|
||||
async function nowEnvPullOverwrite() {
|
||||
@@ -711,6 +747,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
|
||||
t.is(apiJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||
t.is(apiJson['NEXT_PUBLIC_VERCEL_URL'], '');
|
||||
t.is(apiJson['MY_DECRYPTABLE_SECRET_ENV'], 'decryptable value');
|
||||
|
||||
const homeUrl = localhost[0];
|
||||
|
||||
@@ -718,6 +755,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
const homeJson = await homeRes.json();
|
||||
t.is(homeJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||
t.is(homeJson['NEXT_PUBLIC_VERCEL_URL'], '');
|
||||
t.is(homeJson['MY_DECRYPTABLE_SECRET_ENV'], 'decryptable value');
|
||||
|
||||
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
||||
|
||||
@@ -752,6 +790,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
t.is(apiJson['NEXT_PUBLIC_VERCEL_URL'], localhostNoProtocol);
|
||||
t.is(apiJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||
t.is(apiJson['MY_STDIN_VAR'], '{"expect":"quotes"}');
|
||||
t.is(apiJson['MY_DECRYPTABLE_SECRET_ENV'], 'decryptable value');
|
||||
|
||||
const homeUrl = localhost[0];
|
||||
const homeRes = await fetch(homeUrl);
|
||||
@@ -759,10 +798,11 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
t.is(homeJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||
t.is(homeJson['NEXT_PUBLIC_VERCEL_URL'], localhostNoProtocol);
|
||||
t.is(homeJson['MY_STDIN_VAR'], '{"expect":"quotes"}');
|
||||
t.is(homeJson['MY_DECRYPTABLE_SECRET_ENV'], 'decryptable value');
|
||||
|
||||
// system env vars are not automatically exposed
|
||||
t.is(apiJson['VERCEL'], undefined);
|
||||
t.is(homeJson['VERCEL'], undefined);
|
||||
// system env vars are automatically exposed
|
||||
t.is(apiJson['VERCEL'], '1');
|
||||
t.is(homeJson['VERCEL'], '1');
|
||||
|
||||
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
||||
|
||||
@@ -916,6 +956,28 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
);
|
||||
|
||||
t.is(exitCode2, 0, formatOutput({ stderr2, stdout2 }));
|
||||
|
||||
const {
|
||||
exitCode: exitCode3,
|
||||
stderr: stderr3,
|
||||
stdout: stdout3,
|
||||
} = await execa(
|
||||
binaryPath,
|
||||
[
|
||||
'env',
|
||||
'rm',
|
||||
'MY_DECRYPTABLE_SECRET_ENV',
|
||||
'development',
|
||||
'-y',
|
||||
...defaultArgs,
|
||||
],
|
||||
{
|
||||
reject: false,
|
||||
cwd: target,
|
||||
}
|
||||
);
|
||||
|
||||
t.is(exitCode3, 0, formatOutput({ stderr3, stdout3 }));
|
||||
}
|
||||
|
||||
async function nowEnvRemoveWithNameOnly() {
|
||||
@@ -948,6 +1010,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
await nowEnvAddFromStdin();
|
||||
await nowEnvAddSystemEnv();
|
||||
await nowEnvLsIncludesVar();
|
||||
await createEnvWithDecryptableSecret();
|
||||
await nowEnvPull();
|
||||
await nowEnvPullOverwrite();
|
||||
await nowEnvPullConfirm();
|
||||
@@ -1503,7 +1566,7 @@ test('ensure we render a warning for deployments with no files', async t => {
|
||||
t.is(res.status, 404);
|
||||
});
|
||||
|
||||
test('output logs of a 2.0 deployment', async t => {
|
||||
test('output logs with "short" output', async t => {
|
||||
const { stderr, stdout, exitCode } = await execa(
|
||||
binaryPath,
|
||||
['logs', context.deployment, ...defaultArgs],
|
||||
@@ -1520,13 +1583,21 @@ test('output logs of a 2.0 deployment', async t => {
|
||||
stderr.includes(`Fetched deployment "${context.deployment}"`),
|
||||
formatOutput({ stderr, stdout })
|
||||
);
|
||||
|
||||
// "short" format includes timestamps
|
||||
t.truthy(
|
||||
stdout.match(
|
||||
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/
|
||||
)
|
||||
);
|
||||
|
||||
t.is(exitCode, 0);
|
||||
});
|
||||
|
||||
test('output logs of a 2.0 deployment without annotate', async t => {
|
||||
test('output logs with "raw" output', async t => {
|
||||
const { stderr, stdout, exitCode } = await execa(
|
||||
binaryPath,
|
||||
['logs', context.deployment, ...defaultArgs],
|
||||
['logs', context.deployment, ...defaultArgs, '--output', 'raw'],
|
||||
{
|
||||
reject: false,
|
||||
}
|
||||
@@ -1536,12 +1607,19 @@ test('output logs of a 2.0 deployment without annotate', async t => {
|
||||
console.log(stdout);
|
||||
console.log(exitCode);
|
||||
|
||||
t.true(!stderr.includes('[now-builder-debug]'));
|
||||
t.true(!stderr.includes('START RequestId'));
|
||||
t.true(!stderr.includes('END RequestId'));
|
||||
t.true(!stderr.includes('REPORT RequestId'));
|
||||
t.true(!stderr.includes('Init Duration'));
|
||||
t.true(!stderr.includes('XRAY TraceId'));
|
||||
t.true(
|
||||
stderr.includes(`Fetched deployment "${context.deployment}"`),
|
||||
formatOutput({ stderr, stdout })
|
||||
);
|
||||
|
||||
// "raw" format does not include timestamps
|
||||
t.is(
|
||||
null,
|
||||
stdout.match(
|
||||
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/
|
||||
)
|
||||
);
|
||||
|
||||
t.is(exitCode, 0);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "9.0.5-canary.0",
|
||||
"version": "9.0.5",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -37,7 +37,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.6.1-canary.0",
|
||||
"@vercel/build-utils": "2.7.0",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
"async-sema": "3.0.0",
|
||||
|
||||
@@ -285,8 +285,8 @@ Learn more: https://vercel.com/docs/runtimes#official-runtimes/go
|
||||
}
|
||||
|
||||
const mainModGoContents = modMainGoContents
|
||||
.replace('__NOW_HANDLER_PACKAGE_NAME', goPackageName)
|
||||
.replace('__NOW_HANDLER_FUNC_NAME', goFuncName);
|
||||
.replace('__VC_HANDLER_PACKAGE_NAME', goPackageName)
|
||||
.replace('__VC_HANDLER_FUNC_NAME', goFuncName);
|
||||
|
||||
if (isGoModExist && isGoModInRootDir) {
|
||||
debug('[mod-root] Write main file to ' + downloadPath);
|
||||
@@ -405,13 +405,13 @@ Learn more: https://vercel.com/docs/runtimes#official-runtimes/go
|
||||
'utf8'
|
||||
);
|
||||
const mainGoContents = origianlMainGoContents.replace(
|
||||
'__NOW_HANDLER_FUNC_NAME',
|
||||
'__VC_HANDLER_FUNC_NAME',
|
||||
handlerFunctionName
|
||||
);
|
||||
|
||||
// in order to allow the user to have `main.go`,
|
||||
// we need our `main.go` to be called something else
|
||||
const mainGoFileName = 'main__now__go__.go';
|
||||
const mainGoFileName = 'main__vc__go__.go';
|
||||
|
||||
// Go doesn't like to build files in different directories,
|
||||
// so now we place `main.go` together with the user code
|
||||
@@ -580,9 +580,9 @@ Learn more: https://vercel.com/docs/runtimes#official-runtimes/go`
|
||||
};
|
||||
} else if (Array.isArray(result)) {
|
||||
// Got "exit" event from child process
|
||||
throw new Error(
|
||||
`Failed to start dev server for "${entrypointWithExt}" (code=${result[0]}, signal=${result[1]})`
|
||||
);
|
||||
const [exitCode, signal] = result;
|
||||
const reason = signal ? `"${signal}" signal` : `exit code ${exitCode}`;
|
||||
throw new Error(`\`go run ${entrypointWithExt}\` failed with ${reason}`);
|
||||
} else {
|
||||
throw new Error(`Unexpected result type: ${typeof result}`);
|
||||
}
|
||||
|
||||
@@ -6,5 +6,5 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
vc.Start(http.HandlerFunc(__NOW_HANDLER_FUNC_NAME))
|
||||
vc.Start(http.HandlerFunc(__VC_HANDLER_FUNC_NAME))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"__NOW_HANDLER_PACKAGE_NAME"
|
||||
"__VC_HANDLER_PACKAGE_NAME"
|
||||
"net/http"
|
||||
|
||||
vc "github.com/vercel/go-bridge/go/bridge"
|
||||
)
|
||||
|
||||
func main() {
|
||||
vc.Start(http.HandlerFunc(__NOW_HANDLER_FUNC_NAME))
|
||||
vc.Start(http.HandlerFunc(__VC_HANDLER_FUNC_NAME))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/go",
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
|
||||
|
||||
2
packages/now-next/.gitignore
vendored
2
packages/now-next/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
/dist
|
||||
/src/now__bridge.ts
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
bridge_defs="$(dirname $(pwd))/now-node-bridge/src/bridge.ts"
|
||||
|
||||
cp -v "$bridge_defs" src/now__bridge.ts
|
||||
|
||||
tsc
|
||||
|
||||
ncc build src/dev-server.ts -e @vercel/build-utils -e @now/build-utils -o dist/dev
|
||||
mv dist/dev/index.js dist/dev-server.js
|
||||
rm -rf dist/dev
|
||||
|
||||
ncc build src/index.ts -e @vercel/build-utils -e @now/build-utils -o dist/main
|
||||
mv dist/main/index.js dist/index.js
|
||||
rm -rf dist/main
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "2.7.3",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
"scripts": {
|
||||
"build": "./build.sh",
|
||||
"test-integration-once": "jest --env node --verbose --runInBand --bail",
|
||||
"prepublishOnly": "./build.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vercel/vercel.git",
|
||||
"directory": "packages/now-next"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/aws-lambda": "8.10.19",
|
||||
"@types/buffer-crc32": "0.2.0",
|
||||
"@types/find-up": "4.0.0",
|
||||
"@types/fs-extra": "8.0.0",
|
||||
"@types/next-server": "8.0.0",
|
||||
"@types/resolve-from": "5.0.1",
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/yazl": "2.4.1",
|
||||
"@vercel/nft": "0.9.2",
|
||||
"async-sema": "3.0.1",
|
||||
"buffer-crc32": "0.2.13",
|
||||
"escape-string-regexp": "2.0.0",
|
||||
"execa": "2.0.4",
|
||||
"find-up": "4.1.0",
|
||||
"fs-extra": "7.0.0",
|
||||
"get-port": "5.0.0",
|
||||
"resolve-from": "5.0.0",
|
||||
"semver": "6.1.1",
|
||||
"set-cookie-parser": "2.4.6",
|
||||
"typescript": "3.9.3",
|
||||
"yazl": "https://github.com/ijjk/yazl#70949c55b482647669ce37023017b1514c42b33c"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
let buildUtils: typeof import('@vercel/build-utils');
|
||||
|
||||
try {
|
||||
buildUtils = require('@vercel/build-utils');
|
||||
} catch (e) {
|
||||
// Fallback for older CLI versions
|
||||
buildUtils = require('@now/build-utils');
|
||||
}
|
||||
|
||||
export default buildUtils;
|
||||
@@ -1,90 +0,0 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
|
||||
import { ExperimentalTraceVersion } from './utils';
|
||||
|
||||
function getCustomData(importName: string, target: string) {
|
||||
return `
|
||||
module.exports = function(...args) {
|
||||
let original = require('./${importName}');
|
||||
|
||||
const finalConfig = {};
|
||||
const target = { target: '${target}' };
|
||||
|
||||
if (typeof original === 'function' && original.constructor.name === 'AsyncFunction') {
|
||||
// AsyncFunctions will become promises
|
||||
original = original(...args);
|
||||
}
|
||||
|
||||
if (original instanceof Promise) {
|
||||
// Special case for promises, as it's currently not supported
|
||||
// and will just error later on
|
||||
return original
|
||||
.then((orignalConfig) => Object.assign(finalConfig, orignalConfig))
|
||||
.then((config) => Object.assign(config, target));
|
||||
} else if (typeof original === 'function') {
|
||||
Object.assign(finalConfig, original(...args));
|
||||
} else if (typeof original === 'object') {
|
||||
Object.assign(finalConfig, original);
|
||||
}
|
||||
|
||||
Object.assign(finalConfig, target);
|
||||
|
||||
return finalConfig;
|
||||
}
|
||||
`.trim();
|
||||
}
|
||||
|
||||
function getDefaultData(target: string) {
|
||||
return `module.exports = { target: '${target}' };`;
|
||||
}
|
||||
|
||||
export default async function createServerlessConfig(
|
||||
workPath: string,
|
||||
entryPath: string,
|
||||
nextVersion: string | undefined
|
||||
) {
|
||||
let target = 'serverless';
|
||||
if (nextVersion) {
|
||||
try {
|
||||
if (semver.gte(nextVersion, ExperimentalTraceVersion)) {
|
||||
target = 'experimental-serverless-trace';
|
||||
}
|
||||
} catch (
|
||||
_ignored
|
||||
// eslint-disable-next-line
|
||||
) {}
|
||||
}
|
||||
|
||||
const primaryConfigPath = path.join(entryPath, 'next.config.js');
|
||||
const secondaryConfigPath = path.join(workPath, 'next.config.js');
|
||||
const backupConfigName = `next.config.__vercel_builder_backup__.js`;
|
||||
|
||||
const hasPrimaryConfig = fs.existsSync(primaryConfigPath);
|
||||
const hasSecondaryConfig = fs.existsSync(secondaryConfigPath);
|
||||
|
||||
let configPath: string;
|
||||
let backupConfigPath: string;
|
||||
|
||||
if (hasPrimaryConfig) {
|
||||
// Prefer primary path
|
||||
configPath = primaryConfigPath;
|
||||
backupConfigPath = path.join(entryPath, backupConfigName);
|
||||
} else if (hasSecondaryConfig) {
|
||||
// Work with secondary path (some monorepo setups)
|
||||
configPath = secondaryConfigPath;
|
||||
backupConfigPath = path.join(workPath, backupConfigName);
|
||||
} else {
|
||||
// Default to primary path for creation
|
||||
configPath = primaryConfigPath;
|
||||
backupConfigPath = path.join(entryPath, backupConfigName);
|
||||
}
|
||||
|
||||
if (fs.existsSync(configPath)) {
|
||||
await fs.rename(configPath, backupConfigPath);
|
||||
await fs.writeFile(configPath, getCustomData(backupConfigName, target));
|
||||
} else {
|
||||
await fs.writeFile(configPath, getDefaultData(target));
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import resolveFrom from 'resolve-from';
|
||||
import { parse } from 'url';
|
||||
import getPort from 'get-port';
|
||||
import { createServer } from 'http';
|
||||
import { syncEnvVars } from './utils';
|
||||
|
||||
process.on('unhandledRejection', err => {
|
||||
console.error('Exiting builder due to build error:');
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.once('message', async ({ dir, runtimeEnv }) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const next = require(resolveFrom(dir, 'next'));
|
||||
const app = next({ dev: true, dir });
|
||||
const handler = app.getRequestHandler();
|
||||
|
||||
const [openPort] = await Promise.all([getPort(), app.prepare()]);
|
||||
const url = `http://localhost:${openPort}`;
|
||||
|
||||
syncEnvVars(process.env, process.env, runtimeEnv);
|
||||
|
||||
createServer((req, res) => {
|
||||
const parsedUrl = parse(req.url || '', true);
|
||||
handler(req, res, parsedUrl);
|
||||
}).listen(openPort, () => {
|
||||
if (process.send) {
|
||||
process.send(url);
|
||||
}
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
import { Server } from 'http';
|
||||
import next from 'next-server';
|
||||
import url from 'url';
|
||||
import { Bridge } from './now__bridge';
|
||||
|
||||
if (!process.env.NODE_ENV) {
|
||||
const region = process.env.VERCEL_REGION || process.env.NOW_REGION;
|
||||
process.env.NODE_ENV = region === 'dev1' ? 'development' : 'production';
|
||||
}
|
||||
|
||||
const app = next({});
|
||||
|
||||
const server = new Server((req, res) => {
|
||||
const parsedUrl = url.parse(req.url || '', true);
|
||||
app.render(req, res, 'PATHNAME_PLACEHOLDER', parsedUrl.query, parsedUrl);
|
||||
});
|
||||
|
||||
const bridge = new Bridge(server);
|
||||
bridge.listen();
|
||||
|
||||
exports.launcher = bridge.launcher;
|
||||
@@ -1,336 +0,0 @@
|
||||
export default [
|
||||
'0.1.0',
|
||||
'0.1.1',
|
||||
'0.2.0',
|
||||
'0.2.1',
|
||||
'0.2.2',
|
||||
'0.2.3',
|
||||
'0.2.4',
|
||||
'0.2.5',
|
||||
'0.2.6',
|
||||
'0.2.7',
|
||||
'0.2.8',
|
||||
'0.2.9',
|
||||
'0.2.10',
|
||||
'0.2.11',
|
||||
'0.2.12',
|
||||
'0.2.13',
|
||||
'0.2.14',
|
||||
'0.3.0',
|
||||
'0.3.1',
|
||||
'0.3.2',
|
||||
'0.3.3',
|
||||
'0.4.0',
|
||||
'0.4.1',
|
||||
'0.9.9',
|
||||
'0.9.10',
|
||||
'0.9.11',
|
||||
'1.0.0',
|
||||
'1.0.1',
|
||||
'1.0.2',
|
||||
'1.1.0',
|
||||
'1.1.1',
|
||||
'1.1.2',
|
||||
'1.2.0',
|
||||
'1.2.1',
|
||||
'1.2.2',
|
||||
'1.2.3',
|
||||
'2.0.0-beta.0',
|
||||
'2.0.0-beta.1',
|
||||
'2.0.0-beta.2',
|
||||
'2.0.0-beta.3',
|
||||
'2.0.0-beta.4',
|
||||
'2.0.0-beta.5',
|
||||
'2.0.0-beta.6',
|
||||
'2.0.0-beta.7',
|
||||
'2.0.0-beta.8',
|
||||
'2.0.0-beta.9',
|
||||
'2.0.0-beta.10',
|
||||
'2.0.0-beta.11',
|
||||
'2.0.0-beta.12',
|
||||
'2.0.0-beta.13',
|
||||
'2.0.0-beta.14',
|
||||
'2.0.0-beta.15',
|
||||
'2.0.0-beta.16',
|
||||
'2.0.0-beta.17',
|
||||
'2.0.0-beta.18',
|
||||
'2.0.0-beta.19',
|
||||
'2.0.0-beta.20',
|
||||
'2.0.0-beta.21',
|
||||
'2.0.0-beta.22',
|
||||
'2.0.0-beta.23',
|
||||
'2.0.0-beta.24',
|
||||
'2.0.0-beta.25',
|
||||
'2.0.0-beta.26',
|
||||
'2.0.0-beta.27',
|
||||
'2.0.0-beta.28',
|
||||
'2.0.0-beta.29',
|
||||
'2.0.0-beta.30',
|
||||
'2.0.0-beta.31',
|
||||
'2.0.0-beta.32',
|
||||
'2.0.0-beta.33',
|
||||
'2.0.0-beta.34',
|
||||
'2.0.0-beta.35',
|
||||
'2.0.0-beta.36',
|
||||
'2.0.0-beta.37',
|
||||
'2.0.0-beta.38',
|
||||
'2.0.0-beta.39',
|
||||
'2.0.0-beta.40',
|
||||
'2.0.0-beta.41',
|
||||
'2.0.0-beta.42',
|
||||
'2.0.0',
|
||||
'2.0.1',
|
||||
'2.1.0',
|
||||
'2.1.1',
|
||||
'2.2.0',
|
||||
'2.3.0-alpha1',
|
||||
'2.3.0',
|
||||
'2.3.1',
|
||||
'2.4.0',
|
||||
'2.4.1',
|
||||
'2.4.2',
|
||||
'2.4.3',
|
||||
'2.4.4',
|
||||
'2.4.5',
|
||||
'2.4.6',
|
||||
'2.4.7',
|
||||
'2.4.8',
|
||||
'2.4.9',
|
||||
'3.0.0-beta1',
|
||||
'3.0.0-beta10',
|
||||
'3.0.0-beta11',
|
||||
'3.0.0-beta12',
|
||||
'3.0.0-beta13',
|
||||
'3.0.0-beta14',
|
||||
'3.0.0-beta15',
|
||||
'3.0.0-beta16',
|
||||
'3.0.0-beta2',
|
||||
'3.0.0-beta3',
|
||||
'3.0.0-beta4',
|
||||
'3.0.0-beta5',
|
||||
'3.0.0-beta6',
|
||||
'3.0.0-beta7',
|
||||
'3.0.0-beta8',
|
||||
'3.0.0-beta9',
|
||||
'3.0.1-beta.1',
|
||||
'3.0.1-beta.2',
|
||||
'3.0.1-beta.3',
|
||||
'3.0.1-beta.4',
|
||||
'3.0.1-beta.5',
|
||||
'3.0.1-beta.6',
|
||||
'3.0.1-beta.7',
|
||||
'3.0.1-beta.8',
|
||||
'3.0.1-beta.9',
|
||||
'3.0.1-beta.10',
|
||||
'3.0.1-beta.11',
|
||||
'3.0.1-beta.12',
|
||||
'3.0.1-beta.13',
|
||||
'3.0.1-beta.14',
|
||||
'3.0.1-beta.15',
|
||||
'3.0.1-beta.16',
|
||||
'3.0.1-beta.17',
|
||||
'3.0.1-beta.18',
|
||||
'3.0.1-beta.19',
|
||||
'3.0.1-beta.20',
|
||||
'3.0.1-beta.21',
|
||||
'3.0.1',
|
||||
'3.0.2',
|
||||
'3.0.3',
|
||||
'3.0.4',
|
||||
'3.0.5',
|
||||
'3.0.6',
|
||||
'3.1.0',
|
||||
'3.2.0',
|
||||
'3.2.1',
|
||||
'3.2.2',
|
||||
'3.2.3',
|
||||
'4.0.0-beta.1',
|
||||
'4.0.0-beta.2',
|
||||
'4.0.0-beta.3',
|
||||
'4.0.0-beta.4',
|
||||
'4.0.0-beta.5',
|
||||
'4.0.0-beta.6',
|
||||
'4.0.0',
|
||||
'4.0.1',
|
||||
'4.0.2',
|
||||
'4.0.3',
|
||||
'4.0.4',
|
||||
'4.0.5',
|
||||
'4.1.0',
|
||||
'4.1.1',
|
||||
'4.1.2',
|
||||
'4.1.3',
|
||||
'4.1.4-canary.1',
|
||||
'4.1.4-canary.2',
|
||||
'4.1.4',
|
||||
'4.2.0-canary.1',
|
||||
'4.2.0-zones.2',
|
||||
'4.2.0',
|
||||
'4.2.1',
|
||||
'4.2.2',
|
||||
'4.2.3',
|
||||
'4.3.0-canary.1',
|
||||
'4.3.0-universal-alpha.1',
|
||||
'4.3.0-universal-alpha.2',
|
||||
'4.3.0-universal-alpha.3',
|
||||
'4.3.0-universal-alpha.4',
|
||||
'4.3.0-zones.1',
|
||||
'4.4.0-canary.2',
|
||||
'4.4.0-canary.3',
|
||||
'5.0.0-universal-alpha.1',
|
||||
'5.0.0-universal-alpha.2',
|
||||
'5.0.0-universal-alpha.3',
|
||||
'5.0.0-universal-alpha.4',
|
||||
'5.0.0-universal-alpha.5',
|
||||
'5.0.0-universal-alpha.6',
|
||||
'5.0.0-universal-alpha.7',
|
||||
'5.0.0-universal-alpha.8',
|
||||
'5.0.0-universal-alpha.9',
|
||||
'5.0.0-universal-alpha.10',
|
||||
'5.0.0-universal-alpha.11',
|
||||
'5.0.0-universal-alpha.12',
|
||||
'5.0.0-universal-alpha.13',
|
||||
'5.0.0-universal-alpha.14',
|
||||
'5.0.0-universal-alpha.15',
|
||||
'5.0.0-universal-alpha.16',
|
||||
'5.0.0-universal-alpha.17',
|
||||
'5.0.0-universal-alpha.18',
|
||||
'5.0.0-universal-alpha.19',
|
||||
'5.0.0-universal-alpha.20',
|
||||
'5.0.0-universal-alpha.21',
|
||||
'5.0.0-universal-alpha.22',
|
||||
'5.0.0-universal-alpha.23',
|
||||
'5.0.0-zones.1',
|
||||
'5.0.0',
|
||||
'5.0.1-canary.1',
|
||||
'5.0.1-canary.2',
|
||||
'5.0.1-canary.3',
|
||||
'5.0.1-canary.4',
|
||||
'5.0.1-canary.5',
|
||||
'5.0.1-canary.6',
|
||||
'5.0.1-canary.7',
|
||||
'5.0.1-canary.8',
|
||||
'5.0.1-canary.9',
|
||||
'5.0.1-canary.10',
|
||||
'5.0.1-canary.11',
|
||||
'5.0.1-canary.12',
|
||||
'5.0.1-canary.13',
|
||||
'5.0.1-canary.14',
|
||||
'5.0.1-canary.15',
|
||||
'5.0.1-canary.16',
|
||||
'5.0.1-canary.17',
|
||||
'5.1.0',
|
||||
'6.0.0-canary.1',
|
||||
'6.0.0-canary.2',
|
||||
'6.0.0-canary.3',
|
||||
'6.0.0-canary.4',
|
||||
'6.0.0-canary.5',
|
||||
'6.0.0-canary.6',
|
||||
'6.0.0-canary.7',
|
||||
'6.0.0',
|
||||
'6.0.1-canary.0',
|
||||
'6.0.1-canary.1',
|
||||
'6.0.1-canary.2',
|
||||
'6.0.1',
|
||||
'6.0.2-canary.0',
|
||||
'6.0.2',
|
||||
'6.0.3-canary.0',
|
||||
'6.0.3-canary.1',
|
||||
'6.0.3',
|
||||
'6.0.4-canary.0',
|
||||
'6.0.4-canary.1',
|
||||
'6.0.4-canary.2',
|
||||
'6.0.4-canary.3',
|
||||
'6.0.4-canary.4',
|
||||
'6.0.4-canary.5',
|
||||
'6.0.4-canary.6',
|
||||
'6.0.4-canary.7',
|
||||
'6.0.4-canary.8',
|
||||
'6.0.4-canary.9',
|
||||
'6.1.0-canary.0',
|
||||
'6.1.0',
|
||||
'6.1.1-canary.0',
|
||||
'6.1.1-canary.1',
|
||||
'6.1.1-canary.2',
|
||||
'6.1.1-canary.3',
|
||||
'6.1.1-canary.4',
|
||||
'6.1.1-canary.5',
|
||||
'6.1.1',
|
||||
'6.1.2',
|
||||
'7.0.0-canary.0',
|
||||
'7.0.0-canary.1',
|
||||
'7.0.0-canary.2',
|
||||
'7.0.0-canary.3',
|
||||
'7.0.0-canary.4',
|
||||
'7.0.0-canary.5',
|
||||
'7.0.0-canary.6',
|
||||
'7.0.0-canary.7',
|
||||
'7.0.0-canary.8',
|
||||
'7.0.0-canary.9',
|
||||
'7.0.0-canary.10',
|
||||
'7.0.0-canary.11',
|
||||
'7.0.0-canary.12',
|
||||
'7.0.0-canary.13',
|
||||
'7.0.0-canary.14',
|
||||
'7.0.0-canary.15',
|
||||
'7.0.0-canary.16',
|
||||
'7.0.0-canary.18',
|
||||
'7.0.0-canary.19',
|
||||
'7.0.0-canary.20',
|
||||
'7.0.0',
|
||||
'7.0.1-canary.0',
|
||||
'7.0.1-canary.1',
|
||||
'7.0.1-canary.2',
|
||||
'7.0.1-canary.3',
|
||||
'7.0.1-canary.4',
|
||||
'7.0.1-canary.5',
|
||||
'7.0.1-canary.6',
|
||||
'7.0.1',
|
||||
'7.0.2-alpha.1',
|
||||
'7.0.2-alpha.3',
|
||||
'7.0.2-canary.5',
|
||||
'7.0.2-canary.6',
|
||||
'7.0.2-canary.7',
|
||||
'7.0.2-canary.8',
|
||||
'7.0.2-canary.9',
|
||||
'7.0.2-canary.10',
|
||||
'7.0.2-canary.11',
|
||||
'7.0.2-canary.12',
|
||||
'7.0.2-canary.13',
|
||||
'7.0.2-canary.14',
|
||||
'7.0.2-canary.15',
|
||||
'7.0.2-canary.16',
|
||||
'7.0.2-canary.17',
|
||||
'7.0.2-canary.18',
|
||||
'7.0.2-canary.19',
|
||||
'7.0.2-canary.20',
|
||||
'7.0.2-canary.21',
|
||||
'7.0.2-canary.22',
|
||||
'7.0.2-canary.23',
|
||||
'7.0.2-canary.24',
|
||||
'7.0.2-canary.25',
|
||||
'7.0.2-canary.26',
|
||||
'7.0.2-canary.27',
|
||||
'7.0.2-canary.28',
|
||||
'7.0.2-canary.29',
|
||||
'7.0.2-canary.31',
|
||||
'7.0.2-canary.33',
|
||||
'7.0.2-canary.34',
|
||||
'7.0.2-canary.35',
|
||||
'7.0.2-canary.36',
|
||||
'7.0.2-canary.37',
|
||||
'7.0.2-canary.38',
|
||||
'7.0.2-canary.39',
|
||||
'7.0.2-canary.40',
|
||||
'7.0.2-canary.41',
|
||||
'7.0.2-canary.42',
|
||||
'7.0.2-canary.43',
|
||||
'7.0.2-canary.44',
|
||||
'7.0.2-canary.45',
|
||||
'7.0.2-canary.46',
|
||||
'7.0.2-canary.47',
|
||||
'7.0.2-canary.48',
|
||||
'7.0.2-canary.49',
|
||||
'7.0.2-canary.50',
|
||||
'7.0.2',
|
||||
];
|
||||
@@ -1,25 +0,0 @@
|
||||
// The Next.js builder can emit the project in a subdirectory depending on how
|
||||
// many folder levels of `node_modules` are traced. To ensure `process.cwd()`
|
||||
// returns the proper path, we change the directory to the folder with the
|
||||
// launcher. This mimics `yarn workspace run` behavior.
|
||||
process.chdir(__dirname);
|
||||
|
||||
if (!process.env.NODE_ENV) {
|
||||
const region = process.env.VERCEL_REGION || process.env.NOW_REGION;
|
||||
process.env.NODE_ENV = region === 'dev1' ? 'development' : 'production';
|
||||
}
|
||||
|
||||
import { Server } from 'http';
|
||||
import { Bridge } from './now__bridge';
|
||||
// eslint-disable-next-line
|
||||
let page: any = {};
|
||||
// __LAUNCHER_PAGE_HANDLER__
|
||||
|
||||
// page.render is for React rendering
|
||||
// page.default is for /api rendering
|
||||
// page is for module.exports in /api
|
||||
const server = new Server(page.render || page.default || page);
|
||||
const bridge = new Bridge(server);
|
||||
bridge.listen();
|
||||
|
||||
exports.launcher = bridge.launcher;
|
||||
@@ -1,25 +0,0 @@
|
||||
// The Next.js builder can emit the project in a subdirectory depending on how
|
||||
// many folder levels of `node_modules` are traced. To ensure `process.cwd()`
|
||||
// returns the proper path, we change the directory to the folder with the
|
||||
// launcher. This mimics `yarn workspace run` behavior.
|
||||
process.chdir(__dirname);
|
||||
|
||||
if (!process.env.NODE_ENV) {
|
||||
const region = process.env.VERCEL_REGION || process.env.NOW_REGION;
|
||||
process.env.NODE_ENV = region === 'dev1' ? 'development' : 'production';
|
||||
}
|
||||
|
||||
import { Server } from 'http';
|
||||
import { Bridge } from './now__bridge';
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const page = require(__LAUNCHER_PAGE_PATH__);
|
||||
|
||||
// page.render is for React rendering
|
||||
// page.default is for /api rendering
|
||||
// page is for module.exports in /api
|
||||
const server = new Server(page.render || page.default || page);
|
||||
const bridge = new Bridge(server);
|
||||
bridge.listen();
|
||||
|
||||
exports.launcher = bridge.launcher;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
i18n: {
|
||||
localeDetection: false,
|
||||
locales: ['nl-NL', 'nl-BE', 'nl', 'fr-BE', 'fr', 'en-US', 'en'],
|
||||
defaultLocale: 'en-US',
|
||||
// TODO: testing locale domains support, will require custom
|
||||
// testing set-up as test accounts are used currently
|
||||
domains: [
|
||||
{
|
||||
domain: 'example.be',
|
||||
defaultLocale: 'nl-BE',
|
||||
},
|
||||
{
|
||||
domain: 'example.fr',
|
||||
defaultLocale: 'fr',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,517 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "en;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "nl;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "nl-NL;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "fr;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "en-US;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/en-US",
|
||||
"headers": {
|
||||
"accept-language": "nl;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/en",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/fr",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/fr",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
{
|
||||
"path": "/nl",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/nl",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL",
|
||||
"status": 200,
|
||||
"mustContain": ">nl-NL<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/non-existent",
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/fr/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/en/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/en-US/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"nl\""
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"nl-NL\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/hello.txt",
|
||||
"status": 200,
|
||||
"mustContain": "hello world!"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/en/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/en/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"nl\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"fr\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
|
||||
// TODO: update when directory listing is disabled
|
||||
// and these are proper 404s
|
||||
{
|
||||
"path": "/en/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "Index of"
|
||||
},
|
||||
{
|
||||
"path": "/nl/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "Index of"
|
||||
},
|
||||
{
|
||||
"path": "/en-US/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"nl-NL\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
|
||||
// this will always be a 200 unless fallback: blocking is used
|
||||
// since the static fallback page is served before the 404
|
||||
// page is rendered
|
||||
{
|
||||
"path": "/en/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en\""
|
||||
},
|
||||
{
|
||||
"delay": 2000
|
||||
},
|
||||
{
|
||||
"path": "/en/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustNotContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en/not-found/fallback/first.json",
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/en/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/en/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustNotContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr/not-found/fallback/first.json",
|
||||
"status": 200
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"delay": 2000
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en-US.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nl.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"nl\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en-US/gsp.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en/gsp.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr/gsp.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nl/gsp.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"nl\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall"
|
||||
},
|
||||
{
|
||||
"path": "/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en-US/gsp/blocking/first.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"catchall\":\"yes\""
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"nl-NL\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nl-NL/gsp/blocking/first.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"catchall\":\"yes\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr/gsp/blocking/first.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"catchall\":\"yes\""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="another">another page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="auto-export">auto-export page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Dynamic(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>dynamic page</p>
|
||||
<p id="query">{JSON.stringify(router.query)}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
const Slug = props => {
|
||||
return (
|
||||
<div>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<Link href="/gsp/blocking/hallo-wereld" locale={'nl-NL'}>
|
||||
<a>/nl-NL/gsp/blocking/hallo-wereld</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/42" locale={'nl-NL'}>
|
||||
<a>/nl-NL/gsp/blocking/42</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/hallo-welt" locale={'fr'}>
|
||||
<a>/fr/gsp/blocking/hallo-welt</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/42" locale={'fr'}>
|
||||
<a>/fr/gsp/blocking/42</a>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStaticProps = () => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
catchall: 'yes',
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
paths: [],
|
||||
fallback: 'blocking',
|
||||
};
|
||||
};
|
||||
|
||||
export default Slug;
|
||||
@@ -1,51 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) return 'Loading...';
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = ({ locales }) => {
|
||||
const paths = [];
|
||||
|
||||
for (const locale of locales) {
|
||||
paths.push({ params: { slug: 'first' }, locale });
|
||||
paths.push({ params: { slug: 'second' }, locale });
|
||||
}
|
||||
|
||||
return {
|
||||
// the default locale will be used since one isn't defined here
|
||||
paths,
|
||||
fallback: true,
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: should non-dynamic GSP pages pre-render for each locale?
|
||||
export const getStaticProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) return 'Loading...';
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
paths: [
|
||||
{ params: { slug: 'first' } },
|
||||
'/gsp/no-fallback/second',
|
||||
{ params: { slug: 'first' }, locale: 'en-US' },
|
||||
'/nl-NL/gsp/no-fallback/second',
|
||||
'/fr/gsp/no-fallback/first',
|
||||
],
|
||||
fallback: false,
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gssp">gssp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gssp">gssp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="index">index page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/another">
|
||||
<a id="to-another">to /another</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp">
|
||||
<a id="to-gsp">to /gsp</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/fallback/first">
|
||||
<a id="to-fallback-first">to /gsp/fallback/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/fallback/hello">
|
||||
<a id="to-fallback-hello">to /gsp/fallback/hello</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/no-fallback/first">
|
||||
<a id="to-no-fallback-first">to /gsp/no-fallback/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gssp">
|
||||
<a id="to-gssp">to /gssp</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gssp/first">
|
||||
<a id="to-gssp-slug">to /gssp/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
const { nextLocale } = router.query;
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="links">links page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/another" locale={nextLocale}>
|
||||
<a id="to-another">to /another</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp" locale={nextLocale}>
|
||||
<a id="to-gsp">to /gsp</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/fallback/first" locale={nextLocale}>
|
||||
<a id="to-fallback-first">to /gsp/fallback/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/fallback/hello" locale={nextLocale}>
|
||||
<a id="to-fallback-hello">to /gsp/fallback/hello</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/no-fallback/first" locale={nextLocale}>
|
||||
<a id="to-no-fallback-first">to /gsp/no-fallback/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gssp" locale={nextLocale}>
|
||||
<a id="to-gssp">to /gssp</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gssp/first" locale={nextLocale}>
|
||||
<a id="to-gssp-slug">to /gssp/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// make SSR page so we have query values immediately
|
||||
export const getServerSideProps = () => {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) return 'Loading...';
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
if (locale === 'en' || locale === 'nl') {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
// the default locale will be used since one isn't defined here
|
||||
paths: ['first', 'second'].map(slug => ({
|
||||
params: { slug },
|
||||
})),
|
||||
fallback: true,
|
||||
};
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ locale, locales }) => {
|
||||
if (locale === 'en' || locale === 'nl') {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
hello world!
|
||||
@@ -1,21 +0,0 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
i18n: {
|
||||
locales: ['nl-NL', 'nl-BE', 'nl', 'fr-BE', 'fr', 'en-US', 'en'],
|
||||
defaultLocale: 'en-US',
|
||||
// TODO: testing locale domains support, will require custom
|
||||
// testing set-up as test accounts are used currently
|
||||
domains: [
|
||||
{
|
||||
domain: 'example.be',
|
||||
defaultLocale: 'nl-BE',
|
||||
},
|
||||
{
|
||||
domain: 'example.fr',
|
||||
defaultLocale: 'fr',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,359 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next",
|
||||
"config": {
|
||||
"sharedLambdas": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "en;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//en/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "nl;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//nl/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "nl-NL;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//nl-NL/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "fr;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//fr/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "en-US;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/en-US",
|
||||
"headers": {
|
||||
"accept-language": "nl;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/en",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/fr",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/fr",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
{
|
||||
"path": "/nl",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/nl",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL",
|
||||
"status": 200,
|
||||
"mustContain": ">nl-NL<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/non-existent",
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/fr/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/en/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/en-US/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"nl\""
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"nl-NL\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/hello.txt",
|
||||
"status": 200,
|
||||
"mustContain": "hello world!"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/en/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/en/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"nl\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"fr\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="another">another page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="auto-export">auto-export page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Dynamic(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>dynamic page</p>
|
||||
<p id="query">{JSON.stringify(router.query)}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) return 'Loading...';
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
// the default locale will be used since one isn't defined here
|
||||
paths: ['first', 'second'].map(slug => ({
|
||||
params: { slug },
|
||||
})),
|
||||
fallback: true,
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: should non-dynamic GSP pages pre-render for each locale?
|
||||
export const getStaticProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) return 'Loading...';
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
paths: [
|
||||
{ params: { slug: 'first' } },
|
||||
'/gsp/no-fallback/second',
|
||||
{ params: { slug: 'first' }, locale: 'en-US' },
|
||||
'/nl-NL/gsp/no-fallback/second',
|
||||
],
|
||||
fallback: false,
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gssp">gssp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gssp">gssp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="index">index page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/another">
|
||||
<a id="to-another">to /another</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp">
|
||||
<a id="to-gsp">to /gsp</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/fallback/first">
|
||||
<a id="to-fallback-first">to /gsp/fallback/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/fallback/hello">
|
||||
<a id="to-fallback-hello">to /gsp/fallback/hello</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/no-fallback/first">
|
||||
<a id="to-no-fallback-first">to /gsp/no-fallback/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gssp">
|
||||
<a id="to-gssp">to /gssp</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gssp/first">
|
||||
<a id="to-gssp-slug">to /gssp/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
const { nextLocale } = router.query;
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="links">links page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/another" locale={nextLocale}>
|
||||
<a id="to-another">to /another</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp" locale={nextLocale}>
|
||||
<a id="to-gsp">to /gsp</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/fallback/first" locale={nextLocale}>
|
||||
<a id="to-fallback-first">to /gsp/fallback/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/fallback/hello" locale={nextLocale}>
|
||||
<a id="to-fallback-hello">to /gsp/fallback/hello</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/no-fallback/first" locale={nextLocale}>
|
||||
<a id="to-no-fallback-first">to /gsp/no-fallback/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gssp" locale={nextLocale}>
|
||||
<a id="to-gssp">to /gssp</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gssp/first" locale={nextLocale}>
|
||||
<a id="to-gssp-slug">to /gssp/first</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// make SSR page so we have query values immediately
|
||||
export const getServerSideProps = () => {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) return 'Loading...';
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
if (locale === 'en' || locale === 'nl') {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
// the default locale will be used since one isn't defined here
|
||||
paths: ['first', 'second'].map(slug => ({
|
||||
params: { slug },
|
||||
})),
|
||||
fallback: true,
|
||||
};
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ locale, locales }) => {
|
||||
if (locale === 'en' || locale === 'nl') {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
hello world!
|
||||
@@ -1,182 +0,0 @@
|
||||
/* eslint-env jest */
|
||||
const fetch = require('node-fetch');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = function (ctx) {
|
||||
it('should revalidate content properly from /', async () => {
|
||||
// we have to hit the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/en-US.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /fr', async () => {
|
||||
// we have to hit the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/fr.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/fr`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/fr`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /nl-NL', async () => {
|
||||
// we have to hit the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/nl-NL/index.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/nl-NL`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /second', async () => {
|
||||
// we have to hit the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/en-US/second.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/second`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/second`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /fr/second', async () => {
|
||||
// we have to hit the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/fr/second.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/fr/second`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/fr/second`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /nl-NL/second', async () => {
|
||||
// we have to hit the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/nl-NL/second.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/nl-NL/second`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL/second`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
});
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
i18n: {
|
||||
locales: ['nl-NL', 'nl-BE', 'nl', 'fr-BE', 'fr', 'en-US', 'en'],
|
||||
defaultLocale: 'en-US',
|
||||
// TODO: testing locale domains support, will require custom
|
||||
// testing set-up as test accounts are used currently
|
||||
domains: [
|
||||
{
|
||||
domain: 'example.be',
|
||||
defaultLocale: 'nl-BE',
|
||||
},
|
||||
{
|
||||
domain: 'example.fr',
|
||||
defaultLocale: 'fr',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,192 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/hello.txt",
|
||||
"status": 200,
|
||||
"mustContain": "hello world!"
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "en;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//en/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "nl;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//nl/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "nl-NL;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//nl-NL/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "fr;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//fr/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "en-US;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/en-US",
|
||||
"headers": {
|
||||
"accept-language": "nl;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/en",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/fr",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/fr",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
{
|
||||
"path": "/nl",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/nl",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL",
|
||||
"status": 200,
|
||||
"mustContain": ">nl-NL<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/first",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/en/first",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/first",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/first",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall page"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/first",
|
||||
"status": 200,
|
||||
"mustContain": ">nl-NL<"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
const Slug = props => {
|
||||
const router = useRouter();
|
||||
|
||||
// invariant ensuring fallback is never accidentally flipped
|
||||
if (router.isFallback) {
|
||||
return 'Loading...';
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>catchall page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/gsp/blocking/hallo-wereld" locale={'nl-NL'}>
|
||||
<a>/nl-NL/gsp/blocking/hallo-wereld</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/42" locale={'nl-NL'}>
|
||||
<a>/nl-NL/gsp/blocking/42</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/hallo-welt" locale={'fr'}>
|
||||
<a>/fr/gsp/blocking/hallo-welt</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/42" locale={'fr'}>
|
||||
<a>/fr/gsp/blocking/42</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/">
|
||||
<a>/</a>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStaticProps = ({ params }) => {
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
random: Math.random(),
|
||||
catchall: 'yes',
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = ({ locales }) => {
|
||||
const paths = [];
|
||||
|
||||
for (const locale of locales) {
|
||||
paths.push({ params: { slug: ['first'] }, locale });
|
||||
paths.push({ params: { slug: ['first'] }, locale });
|
||||
}
|
||||
|
||||
return {
|
||||
paths,
|
||||
fallback: 'blocking',
|
||||
};
|
||||
};
|
||||
|
||||
export default Slug;
|
||||
@@ -1 +0,0 @@
|
||||
hello world!
|
||||
@@ -1,412 +0,0 @@
|
||||
/* eslint-env jest */
|
||||
const fetch = require('node-fetch');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = function (ctx) {
|
||||
it('should revalidate content properly from /', async () => {
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/en-US.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({});
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({});
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /fr', async () => {
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/fr.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/fr`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({});
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/fr`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({});
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /nl-NL', async () => {
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/nl-NL.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/nl-NL`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({});
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({});
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /gsp/fallback/first', async () => {
|
||||
// check the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/en-US/gsp/fallback/first.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/gsp/fallback/first`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
expect(props.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/gsp/fallback/first`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
expect(props2.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /fr/gsp/fallback/first', async () => {
|
||||
// check the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/fr/gsp/fallback/first.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/first`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
expect(props.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/first`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
expect(props2.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /nl-NL/gsp/fallback/first', async () => {
|
||||
// check the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/nl-NL/gsp/fallback/first.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/first`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
expect(props.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/first`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
expect(props2.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
});
|
||||
//
|
||||
|
||||
it('should revalidate content properly from /gsp/fallback/new-page', async () => {
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/en-US/gsp/fallback/new-page.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
const initRes = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`);
|
||||
expect(initRes.status).toBe(200);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
expect(props.params).toEqual({ slug: 'new-page' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
expect(props2.params).toEqual({ slug: 'new-page' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /fr/gsp/fallback/new-page', async () => {
|
||||
// we have to hit the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/fr/gsp/fallback/new-page.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/new-page`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
expect(props.params).toEqual({ slug: 'new-page' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/new-page`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /nl-NL/gsp/fallback/new-page', async () => {
|
||||
// we have to hit the _next/data URL first
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/nl-NL/gsp/fallback/new-page.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/new-page`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
expect(props.params).toEqual({ slug: 'new-page' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(
|
||||
`${ctx.deploymentUrl}/nl-NL/gsp/fallback/new-page`
|
||||
);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
expect(props2.params).toEqual({ slug: 'new-page' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /gsp/no-fallback/first', async () => {
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/en-US/gsp/no-fallback/first.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/gsp/no-fallback/first`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
expect(props.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/gsp/no-fallback/first`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('en-US');
|
||||
expect(props2.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /fr/gsp/no-fallback/first', async () => {
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/fr/gsp/no-fallback/first.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/no-fallback/first`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
expect(props.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/no-fallback/first`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('fr');
|
||||
expect(props2.params).toEqual({ slug: 'first' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /nl-NL/gsp/no-fallback/second', async () => {
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/nl-NL/gsp/no-fallback/second.json`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
await dataRes.json();
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(
|
||||
`${ctx.deploymentUrl}/nl-NL/gsp/no-fallback/second`
|
||||
);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
const initialRandom = props.random;
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
expect(props.params).toEqual({ slug: 'second' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'second' });
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(
|
||||
`${ctx.deploymentUrl}/nl-NL/gsp/no-fallback/second`
|
||||
);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
const props2 = JSON.parse($('#props').text());
|
||||
expect(initialRandom).not.toBe(props2.random);
|
||||
expect($('#router-locale').text()).toBe('nl-NL');
|
||||
expect(props2.params).toEqual({ slug: 'second' });
|
||||
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'second' });
|
||||
});
|
||||
};
|
||||
@@ -1,98 +0,0 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
i18n: {
|
||||
locales: ['nl-NL', 'nl-BE', 'nl', 'fr-BE', 'fr', 'en-US', 'en'],
|
||||
defaultLocale: 'en-US',
|
||||
// TODO: testing locale domains support, will require custom
|
||||
// testing set-up as test accounts are used currently
|
||||
domains: [
|
||||
{
|
||||
domain: 'example.be',
|
||||
defaultLocale: 'nl-BE',
|
||||
},
|
||||
{
|
||||
domain: 'example.fr',
|
||||
defaultLocale: 'fr',
|
||||
},
|
||||
],
|
||||
},
|
||||
async redirects() {
|
||||
return [
|
||||
{
|
||||
source: '/en-US/redirect-1',
|
||||
destination: '/somewhere-else',
|
||||
permanent: false,
|
||||
locale: false,
|
||||
},
|
||||
{
|
||||
source: '/nl/redirect-2',
|
||||
destination: '/somewhere-else',
|
||||
permanent: false,
|
||||
locale: false,
|
||||
},
|
||||
{
|
||||
source: '/redirect-3',
|
||||
destination: '/somewhere-else',
|
||||
permanent: false,
|
||||
},
|
||||
];
|
||||
},
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: '/en-US/rewrite-1',
|
||||
destination: '/another',
|
||||
locale: false,
|
||||
},
|
||||
{
|
||||
source: '/nl/rewrite-2',
|
||||
destination: '/nl/another',
|
||||
locale: false,
|
||||
},
|
||||
{
|
||||
source: '/fr/rewrite-3',
|
||||
destination: '/nl/another',
|
||||
locale: false,
|
||||
},
|
||||
{
|
||||
source: '/rewrite-4',
|
||||
destination: '/another',
|
||||
},
|
||||
];
|
||||
},
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
source: '/en-US/add-header-1',
|
||||
locale: false,
|
||||
headers: [
|
||||
{
|
||||
key: 'x-hello',
|
||||
value: 'world',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
source: '/nl/add-header-2',
|
||||
locale: false,
|
||||
headers: [
|
||||
{
|
||||
key: 'x-hello',
|
||||
value: 'world',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
source: '/add-header-3',
|
||||
headers: [
|
||||
{
|
||||
key: 'x-hello',
|
||||
value: 'world',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
@@ -1,799 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "en;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//en/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "nl;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//nl/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "nl-NL;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//nl-NL/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "fr;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//fr/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"headers": {
|
||||
"accept-language": "en-US;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/en-US",
|
||||
"headers": {
|
||||
"accept-language": "nl;q=0.9"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/en",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/fr",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/fr",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
{
|
||||
"path": "/nl",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/nl",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL",
|
||||
"status": 200,
|
||||
"mustContain": ">nl-NL<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/non-existent",
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/fr/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/en/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/en-US/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"nl\""
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/non-existent",
|
||||
"status": 404,
|
||||
"mustContain": "lang=\"nl-NL\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/hello.txt",
|
||||
"status": 200,
|
||||
"mustContain": "hello world!"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/en/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/en/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"nl\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "dynamic page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/dynamic/hello",
|
||||
"status": 200,
|
||||
"mustContain": "\"fr\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">en-US<"
|
||||
},
|
||||
{
|
||||
"path": "/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">en<"
|
||||
},
|
||||
{
|
||||
"path": "/en/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">nl<"
|
||||
},
|
||||
{
|
||||
"path": "/nl/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "gssp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": ">fr<"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gssp/first",
|
||||
"status": 200,
|
||||
"mustContain": "slug\":\"first\""
|
||||
},
|
||||
|
||||
// TODO: update when directory listing is disabled
|
||||
// and these are proper 404s
|
||||
{
|
||||
"path": "/en/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "Index of"
|
||||
},
|
||||
{
|
||||
"path": "/nl/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "Index of"
|
||||
},
|
||||
{
|
||||
"path": "/en-US/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"nl-NL\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
|
||||
// this will always be a 200 unless fallback: blocking is used
|
||||
// since the static fallback page is served before the 404
|
||||
// page is rendered
|
||||
{
|
||||
"path": "/en/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en\""
|
||||
},
|
||||
{
|
||||
"delay": 2000
|
||||
},
|
||||
{
|
||||
"path": "/en/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustNotContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en/not-found/fallback/first.json",
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/en/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/en/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustNotContain": "gsp page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr/not-found/fallback/first.json",
|
||||
"status": 200
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"delay": 2000
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en-US.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nl.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"nl\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en-US/gsp.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en/gsp.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr/gsp.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nl/gsp.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"nl\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall"
|
||||
},
|
||||
{
|
||||
"path": "/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en-US/gsp/blocking/first.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"catchall\":\"yes\""
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall"
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"nl-NL\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nl-NL/gsp/blocking/first.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"catchall\":\"yes\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "catchall"
|
||||
},
|
||||
{
|
||||
"path": "/fr/gsp/blocking/first",
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr/gsp/blocking/first.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"catchall\":\"yes\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/en-US/redirect-1",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//somewhere-else/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/en/redirect-1",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/nl/redirect-2",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//somewhere-else/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/en-US/redirect-2",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/redirect-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//somewhere-else/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/en-US/redirect-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//somewhere-else/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/fr/redirect-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//somewhere-else/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/redirect-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"location": "//somewhere-else/"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/en-US/rewrite-1",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "another page"
|
||||
},
|
||||
{
|
||||
"path": "/en-US/rewrite-1",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/nl/rewrite-1",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/nl/rewrite-2",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "another page"
|
||||
},
|
||||
{
|
||||
"path": "/nl/rewrite-2",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"nl\""
|
||||
},
|
||||
{
|
||||
"path": "/rewrite-2",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/fr/rewrite-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "another page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/rewrite-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"nl\""
|
||||
},
|
||||
{
|
||||
"path": "/rewrite-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/rewrite-4",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "another page"
|
||||
},
|
||||
{
|
||||
"path": "/rewrite-4",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/en/rewrite-4",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "another page"
|
||||
},
|
||||
{
|
||||
"path": "/en/rewrite-4",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/rewrite-4",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "another page"
|
||||
},
|
||||
{
|
||||
"path": "/fr/rewrite-4",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "lang=\"fr\""
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/en-US/add-header-1",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404,
|
||||
"responseHeaders": {
|
||||
"x-hello": "world"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/en/add-header-1",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404,
|
||||
"responseHeaders": {
|
||||
"x-hello": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/nl/add-header-2",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404,
|
||||
"responseHeaders": {
|
||||
"x-hello": "world"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/en-US/add-header-2",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404,
|
||||
"responseHeaders": {
|
||||
"x-hello": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/add-header-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404,
|
||||
"responseHeaders": {
|
||||
"x-hello": "world"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/en-US/add-header-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404,
|
||||
"responseHeaders": {
|
||||
"x-hello": "world"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/fr/add-header-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404,
|
||||
"responseHeaders": {
|
||||
"x-hello": "world"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/nl-NL/add-header-3",
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
},
|
||||
"status": 404,
|
||||
"responseHeaders": {
|
||||
"x-hello": "world"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="another">another page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="auto-export">auto-export page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Dynamic(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>dynamic page</p>
|
||||
<p id="query">{JSON.stringify(router.query)}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
const Slug = props => {
|
||||
return (
|
||||
<div>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<Link href="/gsp/blocking/hallo-wereld" locale={'nl-NL'}>
|
||||
<a>/nl-NL/gsp/blocking/hallo-wereld</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/42" locale={'nl-NL'}>
|
||||
<a>/nl-NL/gsp/blocking/42</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/hallo-welt" locale={'fr'}>
|
||||
<a>/fr/gsp/blocking/hallo-welt</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/gsp/blocking/42" locale={'fr'}>
|
||||
<a>/fr/gsp/blocking/42</a>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStaticProps = () => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
catchall: 'yes',
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
paths: [],
|
||||
fallback: 'blocking',
|
||||
};
|
||||
};
|
||||
|
||||
export default Slug;
|
||||
@@ -1,51 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) return 'Loading...';
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = ({ locales }) => {
|
||||
const paths = [];
|
||||
|
||||
for (const locale of locales) {
|
||||
paths.push({ params: { slug: 'first' }, locale });
|
||||
paths.push({ params: { slug: 'second' }, locale });
|
||||
}
|
||||
|
||||
return {
|
||||
// the default locale will be used since one isn't defined here
|
||||
paths,
|
||||
fallback: true,
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: should non-dynamic GSP pages pre-render for each locale?
|
||||
export const getStaticProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) return 'Loading...';
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gsp">gsp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
paths: [
|
||||
{ params: { slug: 'first' } },
|
||||
'/gsp/no-fallback/second',
|
||||
{ params: { slug: 'first' }, locale: 'en-US' },
|
||||
'/nl-NL/gsp/no-fallback/second',
|
||||
'/fr/gsp/no-fallback/first',
|
||||
],
|
||||
fallback: false,
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gssp">gssp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function Page(props) {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="gssp">gssp page</p>
|
||||
<p id="props">{JSON.stringify(props)}</p>
|
||||
<p id="router-locale">{router.locale}</p>
|
||||
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||
<p id="router-pathname">{router.pathname}</p>
|
||||
<p id="router-as-path">{router.asPath}</p>
|
||||
<Link href="/">
|
||||
<a id="to-index">to /</a>
|
||||
</Link>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
};
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user