mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-26 03:39:11 +00:00
Compare commits
23 Commits
@vercel/ne
...
@vercel/ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81011df816 | ||
|
|
c8d31bdcf7 | ||
|
|
5e7f1158ad | ||
|
|
df5aa1f10d | ||
|
|
eb1ba97309 | ||
|
|
8047d6de49 | ||
|
|
7470ff3724 | ||
|
|
8340d9327c | ||
|
|
d278425810 | ||
|
|
8b26bbe643 | ||
|
|
fa8e1e73c8 | ||
|
|
f8abcbcd9f | ||
|
|
e18ff683b2 | ||
|
|
f28293a5a8 | ||
|
|
a4963a89c7 | ||
|
|
21df39fe8c | ||
|
|
5ad9d61451 | ||
|
|
8b5a2aa44f | ||
|
|
d0da1ce195 | ||
|
|
fd5d3b2921 | ||
|
|
d22bdeb8d0 | ||
|
|
c120fd82f9 | ||
|
|
2474a80ff1 |
@@ -56,7 +56,13 @@
|
||||
"outputDirectory": {
|
||||
"placeholder": "Next.js default"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recommendedIntegrations": [
|
||||
{
|
||||
"id": "oac_5lUsiANun1DEzgLg0NZx5Es3",
|
||||
"dependencies": ["next-plugin-sentry", "next-sentry-source-maps"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Gatsby.js",
|
||||
|
||||
4
packages/frameworks/index.d.ts
vendored
4
packages/frameworks/index.d.ts
vendored
@@ -31,4 +31,8 @@ export interface Framework {
|
||||
devCommand: Setting;
|
||||
outputDirectory: Setting;
|
||||
};
|
||||
recommendedIntegrations?: {
|
||||
id: string;
|
||||
dependencies: string[];
|
||||
}[];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/frameworks",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2-canary.0",
|
||||
"main": "frameworks.json",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
|
||||
19
packages/frameworks/test/frameworks.unit.test.ts
vendored
19
packages/frameworks/test/frameworks.unit.test.ts
vendored
@@ -97,6 +97,25 @@ const Schema = {
|
||||
outputDirectory: SchemaSettings,
|
||||
},
|
||||
},
|
||||
recommendedIntegrations: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['id', 'dependencies'],
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
},
|
||||
dependencies: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "2.5.4",
|
||||
"version": "2.5.5-canary.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
@@ -29,7 +29,7 @@
|
||||
"@types/node-fetch": "^2.1.6",
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/yazl": "^2.4.1",
|
||||
"@vercel/frameworks": "0.1.1",
|
||||
"@vercel/frameworks": "0.1.2-canary.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"aggregate-error": "3.0.1",
|
||||
"async-retry": "1.2.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "20.1.2",
|
||||
"version": "20.1.3-canary.0",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -61,7 +61,7 @@
|
||||
"node": ">= 10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.5.4",
|
||||
"@vercel/build-utils": "2.5.5-canary.0",
|
||||
"@vercel/go": "1.1.6",
|
||||
"@vercel/node": "1.8.4",
|
||||
"@vercel/python": "1.2.3",
|
||||
@@ -100,7 +100,7 @@
|
||||
"@types/universal-analytics": "0.4.2",
|
||||
"@types/which": "1.3.2",
|
||||
"@types/write-json-file": "2.2.1",
|
||||
"@vercel/frameworks": "0.1.1",
|
||||
"@vercel/frameworks": "0.1.2-canary.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@zeit/fun": "0.11.2",
|
||||
"@zeit/source-map-support": "0.6.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "9.0.3",
|
||||
"version": "9.0.4-canary.0",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -37,7 +37,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.5.4",
|
||||
"@vercel/build-utils": "2.5.5-canary.0",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
"async-sema": "3.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "2.6.29",
|
||||
"version": "2.6.34",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
PrepareCacheOptions,
|
||||
Prerender,
|
||||
} from '@vercel/build-utils';
|
||||
import { Handler, Route } from '@vercel/routing-utils';
|
||||
import { Handler, Route, Source } from '@vercel/routing-utils';
|
||||
import {
|
||||
convertHeaders,
|
||||
convertRedirects,
|
||||
@@ -655,12 +655,13 @@ export const build = async ({
|
||||
|
||||
return {
|
||||
output,
|
||||
images: imagesManifest?.images
|
||||
? {
|
||||
domains: imagesManifest.images.domains,
|
||||
sizes: imagesManifest.images.sizes,
|
||||
}
|
||||
: undefined,
|
||||
images:
|
||||
imagesManifest?.images?.loader === 'default'
|
||||
? {
|
||||
domains: imagesManifest.images.domains,
|
||||
sizes: imagesManifest.images.sizes,
|
||||
}
|
||||
: undefined,
|
||||
routes: [
|
||||
// User headers
|
||||
...headers,
|
||||
@@ -879,7 +880,9 @@ export const build = async ({
|
||||
// Next.js versions so we need to also not treat it as a static page here.
|
||||
if (
|
||||
prerenderManifest.staticRoutes[routeName] ||
|
||||
prerenderManifest.fallbackRoutes[routeName]
|
||||
prerenderManifest.fallbackRoutes[routeName] ||
|
||||
prerenderManifest.staticRoutes[normalizePage(pathname)] ||
|
||||
prerenderManifest.fallbackRoutes[normalizePage(pathname)]
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -1390,17 +1393,19 @@ export const build = async ({
|
||||
if (i18n) {
|
||||
const { pathname } = url.parse(route.dest!);
|
||||
const isFallback = prerenderManifest.fallbackRoutes[pathname!];
|
||||
const isBlocking =
|
||||
prerenderManifest.blockingFallbackRoutes[pathname!];
|
||||
|
||||
route.src = route.src.replace(
|
||||
'^',
|
||||
`^${dynamicPrefix ? `${dynamicPrefix}[/]?` : '[/]?'}(?${
|
||||
isFallback ? '<nextLocale>' : ':'
|
||||
isFallback || isBlocking ? '<nextLocale>' : ':'
|
||||
}${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})?`
|
||||
);
|
||||
|
||||
if (isFallback) {
|
||||
if (isFallback || isBlocking) {
|
||||
// ensure destination has locale prefix to match prerender output
|
||||
// path so that the prerender object is used
|
||||
route.dest = route.dest!.replace(
|
||||
@@ -1456,7 +1461,7 @@ export const build = async ({
|
||||
)}).some((locale) => {
|
||||
if (pathnameParts[1].toLowerCase() === locale.toLowerCase()) {
|
||||
pathnameParts.splice(1, 1)
|
||||
pathname = pathnameParts.join('/') || '/'
|
||||
pathname = pathnameParts.join('/') || '/index'
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -1492,7 +1497,7 @@ export const build = async ({
|
||||
if (!toRender) {
|
||||
try {
|
||||
const { pathname } = url.parse(req.url)
|
||||
toRender = stripLocalePath(pathname).replace(/\\/$/, '')
|
||||
toRender = stripLocalePath(pathname).replace(/\\/$/, '') || '/index'
|
||||
} catch (_) {
|
||||
// handle failing to parse url
|
||||
res.statusCode = 400
|
||||
@@ -1511,7 +1516,7 @@ export const build = async ({
|
||||
.replace(new RegExp('/_next/data/${escapedBuildId}/'), '/')
|
||||
.replace(/\\.json$/, '')
|
||||
|
||||
toRender = stripLocalePath(toRender)
|
||||
toRender = stripLocalePath(toRender) || '/index'
|
||||
currentPage = pages[toRender]
|
||||
}
|
||||
|
||||
@@ -1539,7 +1544,7 @@ export const build = async ({
|
||||
|
||||
if (!currentPage) {
|
||||
console.error(
|
||||
"Failed to find matching page for", toRender, "in lambda"
|
||||
"Failed to find matching page for", {toRender, header: req.headers['x-nextjs-page'], url: req.url, pages: Object.keys(pages) }, "in lambda"
|
||||
)
|
||||
res.statusCode = 500
|
||||
return res.end('internal server error')
|
||||
@@ -1651,12 +1656,17 @@ export const build = async ({
|
||||
// if there isn't a srcRoute then it's a non-dynamic SSG page and
|
||||
if (nonDynamicSsg || isFallback) {
|
||||
routeFileNoExt = addLocaleOrDefault(
|
||||
// root index files are located without folder/index.html
|
||||
routeFileNoExt,
|
||||
routesManifest,
|
||||
locale
|
||||
);
|
||||
}
|
||||
|
||||
const isNotFound = prerenderManifest.notFoundRoutes.includes(
|
||||
routeFileNoExt
|
||||
);
|
||||
|
||||
const htmlFsRef = isBlocking
|
||||
? // Blocking pages do not have an HTML fallback
|
||||
null
|
||||
@@ -1718,7 +1728,12 @@ export const build = async ({
|
||||
if (nonDynamicSsg || isFallback) {
|
||||
outputPathData = outputPathData.replace(
|
||||
new RegExp(`${escapeStringRegexp(origRouteFileNoExt)}.json$`),
|
||||
`${routeFileNoExt}.json`
|
||||
`${routeFileNoExt}${
|
||||
routeFileNoExt !== origRouteFileNoExt &&
|
||||
origRouteFileNoExt === '/index'
|
||||
? '/index'
|
||||
: ''
|
||||
}.json`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1744,7 +1759,7 @@ export const build = async ({
|
||||
lambda = lambdas[outputSrcPathPage];
|
||||
}
|
||||
|
||||
if (initialRevalidate === false) {
|
||||
if (!isNotFound && initialRevalidate === false) {
|
||||
if (htmlFsRef == null || jsonFsRef == null) {
|
||||
throw new NowBuildError({
|
||||
code: 'NEXT_HTMLFSREF_JSONFSREF',
|
||||
@@ -1759,7 +1774,7 @@ export const build = async ({
|
||||
}
|
||||
}
|
||||
|
||||
if (prerenders[outputPathPage] == null) {
|
||||
if (prerenders[outputPathPage] == null && !isNotFound) {
|
||||
if (lambda == null) {
|
||||
throw new NowBuildError({
|
||||
code: 'NEXT_MISSING_LAMBDA',
|
||||
@@ -1783,6 +1798,44 @@ export const build = async ({
|
||||
});
|
||||
|
||||
++prerenderGroup;
|
||||
|
||||
if (routesManifest?.i18n && isBlocking) {
|
||||
for (const locale of routesManifest.i18n.locales) {
|
||||
const localeRouteFileNoExt = addLocaleOrDefault(
|
||||
routeFileNoExt,
|
||||
routesManifest,
|
||||
locale
|
||||
);
|
||||
const localeOutputPathPage = path.posix.join(
|
||||
entryDirectory,
|
||||
localeRouteFileNoExt
|
||||
);
|
||||
const localeOutputPathData = outputPathData.replace(
|
||||
new RegExp(`${escapeStringRegexp(origRouteFileNoExt)}.json$`),
|
||||
`${localeRouteFileNoExt}${
|
||||
localeRouteFileNoExt !== origRouteFileNoExt &&
|
||||
origRouteFileNoExt === '/index'
|
||||
? '/index'
|
||||
: ''
|
||||
}.json`
|
||||
);
|
||||
|
||||
const origPrerenderPage = prerenders[outputPathPage];
|
||||
const origPrerenderData = prerenders[outputPathData];
|
||||
|
||||
prerenders[localeOutputPathPage] = {
|
||||
...origPrerenderPage,
|
||||
group: prerenderGroup,
|
||||
} as Prerender;
|
||||
|
||||
prerenders[localeOutputPathData] = {
|
||||
...origPrerenderData,
|
||||
group: prerenderGroup,
|
||||
} as Prerender;
|
||||
|
||||
++prerenderGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((nonDynamicSsg || isFallback) && routesManifest?.i18n && !locale) {
|
||||
@@ -1947,12 +2000,13 @@ export const build = async ({
|
||||
};
|
||||
})
|
||||
: undefined,
|
||||
images: imagesManifest?.images
|
||||
? {
|
||||
domains: imagesManifest.images.domains,
|
||||
sizes: imagesManifest.images.sizes,
|
||||
}
|
||||
: undefined,
|
||||
images:
|
||||
imagesManifest?.images?.loader === 'default'
|
||||
? {
|
||||
domains: imagesManifest.images.domains,
|
||||
sizes: imagesManifest.images.sizes,
|
||||
}
|
||||
: undefined,
|
||||
/*
|
||||
Desired routes order
|
||||
- Runtime headers
|
||||
@@ -1968,22 +2022,27 @@ export const build = async ({
|
||||
...headers,
|
||||
|
||||
// redirects
|
||||
...redirects.map(redir => {
|
||||
...redirects.map(_redir => {
|
||||
if (i18n) {
|
||||
const redir = _redir as Source;
|
||||
// detect the trailing slash redirect and make sure it's
|
||||
// kept above the wildcard mapping to prevent erroneous redirects
|
||||
// since non-continue routes come after continue the $wildcard
|
||||
// route will come before the redirect otherwise and if the
|
||||
// redirect is triggered it breaks locale mapping
|
||||
|
||||
const location =
|
||||
redir.headers && (redir.headers.location || redir.headers.Location);
|
||||
|
||||
if (
|
||||
redir.status === 308 &&
|
||||
(redir.dest === '/$1' || redir.dest === '/$1/')
|
||||
(location === '/$1' || location === '/$1/')
|
||||
) {
|
||||
// we set continue true
|
||||
(redir as any).continue = true;
|
||||
redir.continue = true;
|
||||
}
|
||||
}
|
||||
return redir;
|
||||
return _redir;
|
||||
}),
|
||||
|
||||
...(i18n
|
||||
@@ -2009,13 +2068,26 @@ export const build = async ({
|
||||
{
|
||||
// TODO: enable redirecting between domains, will require
|
||||
// updating the src with the desired locales to redirect
|
||||
src: '/',
|
||||
src: `^${path.join(
|
||||
'/',
|
||||
entryDirectory
|
||||
)}/?(?:${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})?/?$`,
|
||||
locale: {
|
||||
redirect: i18n.domains.reduce(
|
||||
(prev: Record<string, string>, item) => {
|
||||
prev[item.defaultLocale] = `http${
|
||||
item.http ? '' : 's'
|
||||
}://${item.domain}/`;
|
||||
|
||||
if (item.locales) {
|
||||
item.locales.map(locale => {
|
||||
prev[locale] = `http${item.http ? '' : 's'}://${
|
||||
item.domain
|
||||
}/${locale}`;
|
||||
});
|
||||
}
|
||||
return prev;
|
||||
},
|
||||
{}
|
||||
|
||||
@@ -332,6 +332,7 @@ export type RoutesManifest = {
|
||||
domains?: Array<{
|
||||
http?: boolean;
|
||||
domain: string;
|
||||
locales?: string[];
|
||||
defaultLocale: string;
|
||||
}>;
|
||||
};
|
||||
@@ -511,9 +512,12 @@ export async function getDynamicRoutes(
|
||||
return routes;
|
||||
}
|
||||
|
||||
type LoaderKey = 'imgix' | 'cloudinary' | 'akamai' | 'default';
|
||||
|
||||
type ImagesManifest = {
|
||||
version: number;
|
||||
images: {
|
||||
loader: LoaderKey;
|
||||
sizes: number[];
|
||||
domains: string[];
|
||||
};
|
||||
@@ -752,6 +756,8 @@ export type NextPrerenderedRoutes = {
|
||||
};
|
||||
|
||||
omittedRoutes: string[];
|
||||
|
||||
notFoundRoutes: string[];
|
||||
};
|
||||
|
||||
export async function getExportIntent(
|
||||
@@ -842,6 +848,7 @@ export async function getPrerenderManifest(
|
||||
fallbackRoutes: {},
|
||||
bypassToken: null,
|
||||
omittedRoutes: [],
|
||||
notFoundRoutes: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -887,6 +894,7 @@ export async function getPrerenderManifest(
|
||||
preview: {
|
||||
previewModeId: string;
|
||||
};
|
||||
notFoundRoutes?: string[];
|
||||
} = JSON.parse(await fs.readFile(pathPrerenderManifest, 'utf8'));
|
||||
|
||||
switch (manifest.version) {
|
||||
@@ -901,6 +909,7 @@ export async function getPrerenderManifest(
|
||||
bypassToken:
|
||||
(manifest.preview && manifest.preview.previewModeId) || null,
|
||||
omittedRoutes: [],
|
||||
notFoundRoutes: [],
|
||||
};
|
||||
|
||||
routes.forEach(route => {
|
||||
@@ -955,8 +964,13 @@ export async function getPrerenderManifest(
|
||||
fallbackRoutes: {},
|
||||
bypassToken: manifest.preview.previewModeId,
|
||||
omittedRoutes: [],
|
||||
notFoundRoutes: [],
|
||||
};
|
||||
|
||||
if (manifest.notFoundRoutes) {
|
||||
ret.notFoundRoutes.push(...manifest.notFoundRoutes);
|
||||
}
|
||||
|
||||
routes.forEach(route => {
|
||||
const {
|
||||
initialRevalidateSeconds,
|
||||
@@ -1010,6 +1024,7 @@ export async function getPrerenderManifest(
|
||||
fallbackRoutes: {},
|
||||
bypassToken: null,
|
||||
omittedRoutes: [],
|
||||
notFoundRoutes: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1110,7 +1125,9 @@ export function addLocaleOrDefault(
|
||||
if (!routesManifest?.i18n) return pathname;
|
||||
if (!locale) locale = routesManifest.i18n.defaultLocale;
|
||||
|
||||
return locale ? `/${locale}${pathname}` : pathname;
|
||||
return locale
|
||||
? `/${locale}${pathname === '/index' ? '' : pathname}`
|
||||
: pathname;
|
||||
}
|
||||
|
||||
export {
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
module.exports = {
|
||||
experimental: {
|
||||
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',
|
||||
},
|
||||
],
|
||||
},
|
||||
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',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
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,
|
||||
};
|
||||
};
|
||||
37
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/not-found/index.js
vendored
Normal file
37
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/not-found/index.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
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,
|
||||
},
|
||||
};
|
||||
};
|
||||
224
packages/now-next/test/fixtures/00-i18n-support/additional.js
vendored
Normal file
224
packages/now-next/test/fixtures/00-i18n-support/additional.js
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
/* eslint-env jest */
|
||||
const fetch = require('node-fetch');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = function (ctx) {
|
||||
it('should revalidate content properly from /', async () => {
|
||||
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 () => {
|
||||
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 () => {
|
||||
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 /gsp/fallback/new-page', async () => {
|
||||
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');
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
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');
|
||||
|
||||
// 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');
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /gsp/no-fallback/first', async () => {
|
||||
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');
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /fr/gsp/no-fallback/first', async () => {
|
||||
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');
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /nl-NL/gsp/no-fallback/second', async () => {
|
||||
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');
|
||||
|
||||
// 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');
|
||||
});
|
||||
};
|
||||
@@ -1,20 +1,21 @@
|
||||
module.exports = {
|
||||
experimental: {
|
||||
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',
|
||||
},
|
||||
],
|
||||
},
|
||||
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',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -310,6 +310,169 @@
|
||||
"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\""
|
||||
},
|
||||
{
|
||||
"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\""
|
||||
},
|
||||
{
|
||||
"path": "/fr/not-found/fallback/first",
|
||||
"status": 200,
|
||||
"mustContain": "gsp page"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en-US/index.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en-US\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/en/index.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"en\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fr/index.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"locale\":\"fr\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nl/index.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\""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
43
packages/now-next/test/fixtures/00-i18n-support/pages/gsp/blocking/[[...slug]].js
vendored
Normal file
43
packages/now-next/test/fixtures/00-i18n-support/pages/gsp/blocking/[[...slug]].js
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
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;
|
||||
@@ -26,10 +26,12 @@ export default function Page(props) {
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -26,10 +26,12 @@ export default function Page(props) {
|
||||
export const getStaticProps = ({ params, locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -40,6 +42,7 @@ export const getStaticPaths = () => {
|
||||
'/gsp/no-fallback/second',
|
||||
{ params: { slug: 'first' }, locale: 'en-US' },
|
||||
'/nl-NL/gsp/no-fallback/second',
|
||||
'/fr/gsp/no-fallback/first',
|
||||
],
|
||||
fallback: false,
|
||||
};
|
||||
|
||||
@@ -44,3 +44,14 @@ export default function Page(props) {
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = ({ locale, locales }) => {
|
||||
return {
|
||||
props: {
|
||||
random: Math.random(),
|
||||
locale,
|
||||
locales,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
50
packages/now-next/test/fixtures/00-i18n-support/pages/not-found/fallback/[slug].js
vendored
Normal file
50
packages/now-next/test/fixtures/00-i18n-support/pages/not-found/fallback/[slug].js
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
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,
|
||||
};
|
||||
};
|
||||
37
packages/now-next/test/fixtures/00-i18n-support/pages/not-found/index.js
vendored
Normal file
37
packages/now-next/test/fixtures/00-i18n-support/pages/not-found/index.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
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,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -152,6 +152,16 @@
|
||||
"x-vercel-cache": "/HIT|STALE|PRERENDER/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "Hi"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/index.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"hello\":\"index\""
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/api-docs/second.json",
|
||||
"status": 200
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
export default () => 'Hi';
|
||||
|
||||
export const getStaticProps = () => {
|
||||
return {
|
||||
props: {
|
||||
hello: 'index',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,5 +19,5 @@ export function getStaticProps({ params }) {
|
||||
}
|
||||
|
||||
export function getStaticPaths() {
|
||||
return { paths: [], fallback: 'unstable_blocking' };
|
||||
return { paths: [], fallback: 'blocking' };
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ export function getStaticProps({ params }) {
|
||||
}
|
||||
|
||||
export function getStaticPaths() {
|
||||
return { paths: [], fallback: 'unstable_blocking' };
|
||||
return { paths: [], fallback: 'blocking' };
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/redwood",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2-canary.0",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -19,7 +19,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@netlify/zip-it-and-ship-it": "1.2.0",
|
||||
"@vercel/frameworks": "0.1.1"
|
||||
"@vercel/frameworks": "0.1.2-canary.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/aws-lambda": "8.10.19",
|
||||
|
||||
Reference in New Issue
Block a user