diff --git a/data.sqlite b/data.sqlite
new file mode 100644
index 000000000000000..e69de29bb2d1d64
diff --git a/docs/api-reference/create-next-app.md b/docs/api-reference/create-next-app.md
index 1b96f94179d2016..24f4255df576c35 100644
--- a/docs/api-reference/create-next-app.md
+++ b/docs/api-reference/create-next-app.md
@@ -18,7 +18,7 @@ yarn create next-app
- **-e, --example [name]|[github-url]** - An example to bootstrap the app with. You can use an example name from the [Next.js repo](https://github.com/vercel/next.js/tree/master/examples) or a GitHub URL. The URL can use any branch and/or subdirectory.
- **--example-path [path-to-example]** - In a rare case, your GitHub URL might contain a branch name with a slash (e.g. bug/fix-1) and the path to the example (e.g. foo/bar). In this case, you must specify the path to the example separately: `--example-path foo/bar`
-- **--use-npm** - Explicitly tell the CLI to bootstrap the app using npm. Yarn will be used by default if it's installed
+- **--use-npm** - Explicitly tell the CLI to bootstrap the app using npm. To bootstrap using yarn we recommend to run `yarn create next-app`
### Why use Create Next App?
diff --git a/docs/api-reference/next.config.js/rewrites.md b/docs/api-reference/next.config.js/rewrites.md
index 1d5e0c5592fb599..927fc23778c2763 100644
--- a/docs/api-reference/next.config.js/rewrites.md
+++ b/docs/api-reference/next.config.js/rewrites.md
@@ -25,8 +25,6 @@ Rewrites allow you to map an incoming request path to a different destination pa
Rewrites act as a URL proxy and mask the destination path, making it appear the user hasn't changed their location on the site. In contrast, [redirects](/docs/api-reference/next.config.js/redirects.md) will reroute to a new page a show the URL changes.
-Rewrites are only available on the Node.js environment and do not affect client-side routing.
-
To use rewrites you can use the `rewrites` key in `next.config.js`:
```js
@@ -42,6 +40,8 @@ module.exports = {
}
```
+Rewrites are applied to client-side routing, a ` ` will have the rewrite applied in the above example.
+
`rewrites` is an async function that expects an array to be returned holding objects with `source` and `destination` properties:
- `source`: `String` - is the incoming request path pattern.
@@ -58,8 +58,8 @@ module.exports = {
return {
beforeFiles: [
// These rewrites are checked after headers/redirects
- // and before pages/public files which allows overriding
- // page files
+ // and before all files including _next/public files which
+ // allows overriding page files
{
source: '/some-page',
destination: '/somewhere-else',
diff --git a/docs/basic-features/data-fetching.md b/docs/basic-features/data-fetching.md
index cf0dbe880712e5c..ef4c057382cdf5a 100644
--- a/docs/basic-features/data-fetching.md
+++ b/docs/basic-features/data-fetching.md
@@ -72,7 +72,7 @@ The `context` parameter is an object containing the following keys:
`getStaticProps` should return an object with:
-- `props` - A **required** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
+- `props` - An **optional** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
- `revalidate` - An **optional** amount in seconds after which a page re-generation can occur. More on [Incremental Static Regeneration](#incremental-static-regeneration)
- `notFound` - An **optional** boolean value to allow the page to return a 404 status and page. Below is an example of how it works:
@@ -672,7 +672,7 @@ The `context` parameter is an object containing the following keys:
`getServerSideProps` should return an object with:
-- `props` - A **required** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
+- `props` - An **optional** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
- `notFound` - An **optional** boolean value to allow the page to return a 404 status and page. Below is an example of how it works:
```js
diff --git a/errors/no-sync-scripts.md b/errors/no-sync-scripts.md
index 4af7ef58b521138..1788236d85df141 100644
--- a/errors/no-sync-scripts.md
+++ b/errors/no-sync-scripts.md
@@ -16,7 +16,7 @@ import Script from 'next/experimental-script'
const Home = () => {
return (
)
diff --git a/examples/with-supertokens/package.json b/examples/with-supertokens/package.json
index ac40d1262d1a431..b98f6ca22612f95 100644
--- a/examples/with-supertokens/package.json
+++ b/examples/with-supertokens/package.json
@@ -11,7 +11,7 @@
"next": "latest",
"react": "17.0.1",
"react-dom": "17.0.1",
- "supertokens-auth-react": "^0.12.0",
+ "supertokens-auth-react": "^0.13.0",
"supertokens-node": "^5.0.0"
},
"license": "MIT"
diff --git a/examples/with-supertokens/pages/index.js b/examples/with-supertokens/pages/index.js
index 00284df70e94cff..befe0d5d5cb9429 100644
--- a/examples/with-supertokens/pages/index.js
+++ b/examples/with-supertokens/pages/index.js
@@ -42,13 +42,17 @@ export default function Home(props) {
function ProtectedPage({ userId }) {
async function logoutClicked() {
await ThirdPartyEmailPassword.signOut()
- window.location.href = '/auth'
+ ThirdPartyEmailPassword.redirectToAuth()
}
async function fetchUserData() {
const res = await fetch('/api/user')
- const json = await res.json()
- alert(JSON.stringify(json))
+ if (res.status === 401) {
+ ThirdPartyEmailPassword.redirectToAuth()
+ } else {
+ const json = await res.json()
+ alert(JSON.stringify(json))
+ }
}
return (
diff --git a/lerna.json b/lerna.json
index 86d8e732e8b56c6..a3862230b7a83c8 100644
--- a/lerna.json
+++ b/lerna.json
@@ -17,5 +17,5 @@
"registry": "https://registry.npmjs.org/"
}
},
- "version": "10.2.1-canary.5"
+ "version": "10.2.1-canary.7"
}
diff --git a/package.json b/package.json
index 02d0e7044949964..30f33b5a997bb13 100644
--- a/package.json
+++ b/package.json
@@ -87,6 +87,7 @@
"image-size": "0.9.3",
"is-animated": "2.0.0",
"isomorphic-unfetch": "3.0.0",
+ "jest": "27.0.0-next.8",
"ky": "0.19.1",
"ky-universal": "0.6.0",
"lerna": "4.0.0",
@@ -119,6 +120,8 @@
"selenium-standalone": "6.18.0",
"selenium-webdriver": "4.0.0-alpha.7",
"shell-quote": "1.7.2",
+ "sqlite": "4.0.22",
+ "sqlite3": "5.0.2",
"styled-components": "5.1.0",
"styled-jsx-plugin-postcss": "3.0.2",
"tailwindcss": "1.1.3",
@@ -128,8 +131,7 @@
"wait-port": "0.2.2",
"web-streams-polyfill": "2.1.1",
"webpack-bundle-analyzer": "4.3.0",
- "worker-loader": "3.0.7",
- "jest": "27.0.0-next.8"
+ "worker-loader": "3.0.7"
},
"resolutions": {
"browserslist": "4.16.1",
diff --git a/packages/create-next-app/README.md b/packages/create-next-app/README.md
index deeb80d65567128..8e629058467a3bb 100644
--- a/packages/create-next-app/README.md
+++ b/packages/create-next-app/README.md
@@ -19,7 +19,7 @@ npx create-next-app blog-app
- **--ts, --typescript** - Initialize as a TypeScript project.
- **-e, --example [name]|[github-url]** - An example to bootstrap the app with. You can use an example name from the [Next.js repo](https://github.com/vercel/next.js/tree/master/examples) or a GitHub URL. The URL can use any branch and/or subdirectory.
- **--example-path <path-to-example>** - In a rare case, your GitHub URL might contain a branch name with a slash (e.g. bug/fix-1) and the path to the example (e.g. foo/bar). In this case, you must specify the path to the example separately: `--example-path foo/bar`
-- **--use-npm** - Explicitly tell the CLI to bootstrap the app using npm. Yarn will be used by default if it's installed
+- **--use-npm** - Explicitly tell the CLI to bootstrap the app using npm. To bootstrap using yarn we recommend to run `yarn create next-app`
## Why use Create Next App?
diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json
index 34925c4bb810d66..d8af0393e17bd99 100644
--- a/packages/create-next-app/package.json
+++ b/packages/create-next-app/package.json
@@ -1,6 +1,6 @@
{
"name": "create-next-app",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"keywords": [
"react",
"next",
diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json
index a4791577e5b037d..0244f2361c3f0a6 100644
--- a/packages/eslint-config-next/package.json
+++ b/packages/eslint-config-next/package.json
@@ -1,6 +1,6 @@
{
"name": "eslint-config-next",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"description": "ESLint configuration used by NextJS.",
"main": "index.js",
"license": "MIT",
diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json
index 3020c3171692cdd..0a0597a86b5927d 100644
--- a/packages/eslint-plugin-next/package.json
+++ b/packages/eslint-plugin-next/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/eslint-plugin-next",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"description": "ESLint plugin for NextJS.",
"main": "lib/index.js",
"license": "MIT",
diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json
index 532a95566e26c86..6ee3401c6530ebb 100644
--- a/packages/next-bundle-analyzer/package.json
+++ b/packages/next-bundle-analyzer/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/bundle-analyzer",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"main": "index.js",
"license": "MIT",
"repository": {
diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json
index 40902ae77fdabc3..8329b1b49be7a33 100644
--- a/packages/next-codemod/package.json
+++ b/packages/next-codemod/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/codemod",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"license": "MIT",
"dependencies": {
"chalk": "4.1.0",
diff --git a/packages/next-env/package.json b/packages/next-env/package.json
index 45b077bf8b5eb33..2b2712ce964cc25 100644
--- a/packages/next-env/package.json
+++ b/packages/next-env/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/env",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"keywords": [
"react",
"next",
diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json
index d64a047d925cb54..5b7cbf0571dc163 100644
--- a/packages/next-mdx/package.json
+++ b/packages/next-mdx/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"main": "index.js",
"license": "MIT",
"repository": {
diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json
index e649aac8e562f65..3254f35c4738792 100644
--- a/packages/next-plugin-storybook/package.json
+++ b/packages/next-plugin-storybook/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-storybook",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-storybook"
diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json
index a77c8bfb9fc104b..a648471ea0ff759 100644
--- a/packages/next-polyfill-module/package.json
+++ b/packages/next-polyfill-module/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-module",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)",
"main": "dist/polyfill-module.js",
"license": "MIT",
diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json
index 618df2f0c0be2c6..9b629ebb490806b 100644
--- a/packages/next-polyfill-nomodule/package.json
+++ b/packages/next-polyfill-nomodule/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-nomodule",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"description": "A polyfill for non-dead, nomodule browsers.",
"main": "dist/polyfill-nomodule.js",
"license": "MIT",
diff --git a/packages/next/build/babel/preset.ts b/packages/next/build/babel/preset.ts
index 04a9aee246dd9a9..32657be2e384d50 100644
--- a/packages/next/build/babel/preset.ts
+++ b/packages/next/build/babel/preset.ts
@@ -41,7 +41,6 @@ type NextBabelPresetOptions = {
'preset-react'?: any
'class-properties'?: any
'transform-runtime'?: any
- 'experimental-modern-preset'?: PluginItem
'styled-jsx'?: StyledJsxBabelOptions
'preset-typescript'?: any
}
@@ -89,10 +88,6 @@ export default (
(Boolean(api.caller((caller: any) => !!caller && caller.hasJsxRuntime)) &&
options['preset-react']?.runtime !== 'classic')
- const isLaxModern =
- options['preset-env']?.targets &&
- options['preset-env'].targets.esmodules === true
-
const presetEnvConfig = {
// In the test environment `modules` is often needed to be set to true, babel figures that out by itself using the `'auto'` option
// In production/development this option is set to `false` so that webpack can handle import/export with tree-shaking
@@ -122,17 +117,10 @@ export default (
}
}
- // specify a preset to use instead of @babel/preset-env
- const customModernPreset =
- isLaxModern && options['experimental-modern-preset']
-
return {
sourceType: 'unambiguous',
presets: [
- customModernPreset || [
- require('next/dist/compiled/babel/preset-env'),
- presetEnvConfig,
- ],
+ [require('next/dist/compiled/babel/preset-env'), presetEnvConfig],
[
require('next/dist/compiled/babel/preset-react'),
{
diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts
index 89617e2e609e934..182680febcfc09f 100644
--- a/packages/next/build/index.ts
+++ b/packages/next/build/index.ts
@@ -79,6 +79,7 @@ import { trace, setGlobal } from '../telemetry/trace'
import {
collectPages,
detectConflictingPaths,
+ computeFromManifest,
getJsPageSizeInKb,
getNamedExports,
hasCustomGetInitialProps,
@@ -724,6 +725,11 @@ export default async function build(
)
}
+ const computedManifestData = await computeFromManifest(
+ buildManifest,
+ distDir,
+ config.experimental.gzipSize
+ )
await Promise.all(
pageKeys.map(async (page) => {
const checkPageSpan = staticCheckSpan.traceChild('check-page', {
@@ -734,7 +740,9 @@ export default async function build(
const [selfSize, allSize] = await getJsPageSizeInKb(
actualPage,
distDir,
- buildManifest
+ buildManifest,
+ config.experimental.gzipSize,
+ computedManifestData
)
let isSsg = false
@@ -1525,6 +1533,7 @@ export default async function build(
useStatic404,
pageExtensions: config.pageExtensions,
buildManifest,
+ gzipSize: config.experimental.gzipSize,
})
)
diff --git a/packages/next/build/utils.ts b/packages/next/build/utils.ts
index c29735acdfb0bb2..14a00b71cdaa0b7 100644
--- a/packages/next/build/utils.ts
+++ b/packages/next/build/utils.ts
@@ -1,8 +1,9 @@
import '../next-server/server/node-polyfill-fetch'
import chalk from 'chalk'
-import gzipSize from 'next/dist/compiled/gzip-size'
+import getGzipSize from 'next/dist/compiled/gzip-size'
import textTable from 'next/dist/compiled/text-table'
import path from 'path'
+import { promises as fs } from 'fs'
import { isValidElementType } from 'react-is'
import stripAnsi from 'next/dist/compiled/strip-ansi'
import {
@@ -32,11 +33,20 @@ import * as Log from './output/log'
import { loadComponents } from '../next-server/server/load-components'
import { trace } from '../telemetry/trace'
-const fileGzipStats: { [k: string]: Promise } = {}
+const fileGzipStats: { [k: string]: Promise | undefined } = {}
const fsStatGzip = (file: string) => {
- if (fileGzipStats[file]) return fileGzipStats[file]
- fileGzipStats[file] = gzipSize.file(file)
- return fileGzipStats[file]
+ const cached = fileGzipStats[file]
+ if (cached) return cached
+ return (fileGzipStats[file] = getGzipSize.file(file))
+}
+
+const fileSize = async (file: string) => (await fs.stat(file)).size
+
+const fileStats: { [k: string]: Promise | undefined } = {}
+const fsStat = (file: string) => {
+ const cached = fileStats[file]
+ if (cached) return cached
+ return (fileStats[file] = fileSize(file))
}
export function collectPages(
@@ -70,6 +80,7 @@ export async function printTreeView(
pageExtensions,
buildManifest,
useStatic404,
+ gzipSize = true,
}: {
distPath: string
buildId: string
@@ -77,6 +88,7 @@ export async function printTreeView(
pageExtensions: string[]
buildManifest: BuildManifest
useStatic404: boolean
+ gzipSize?: boolean
}
) {
const getPrettySize = (_size: number): string => {
@@ -96,7 +108,7 @@ export async function printTreeView(
// Re-add `static/` for root files
.replace(/^/, 'static')
// Remove file hash
- .replace(/[.-]([0-9a-z]{6})[0-9a-z]{14}(?=\.)/, '.$1')
+ .replace(/(?:^|[.-])([0-9a-z]{6})[0-9a-z]{14}(?=\.)/, '.$1')
const messages: [string, string, string][] = [
['Page', 'Size', 'First Load JS'].map((entry) =>
@@ -115,7 +127,12 @@ export async function printTreeView(
list = [...list, '/404']
}
- const sizeData = await computeFromManifest(buildManifest, distPath, pageInfos)
+ const sizeData = await computeFromManifest(
+ buildManifest,
+ distPath,
+ gzipSize,
+ pageInfos
+ )
const pageList = list
.slice()
@@ -378,9 +395,10 @@ let cachedBuildManifest: BuildManifest | undefined
let lastCompute: ComputeManifestShape | undefined
let lastComputePageInfo: boolean | undefined
-async function computeFromManifest(
+export async function computeFromManifest(
manifest: BuildManifest,
distPath: string,
+ gzipSize: boolean = true,
pageInfos?: Map
): Promise {
if (
@@ -414,6 +432,8 @@ async function computeFromManifest(
})
})
+ const getSize = gzipSize ? fsStatGzip : fsStat
+
const commonFiles = [...files.entries()]
.filter(([, len]) => len === expected || len === Infinity)
.map(([f]) => f)
@@ -426,7 +446,7 @@ async function computeFromManifest(
stats = await Promise.all(
commonFiles.map(
async (f) =>
- [f, await fsStatGzip(path.join(distPath, f))] as [string, number]
+ [f, await getSize(path.join(distPath, f))] as [string, number]
)
)
} catch (_) {
@@ -438,7 +458,7 @@ async function computeFromManifest(
uniqueStats = await Promise.all(
uniqueFiles.map(
async (f) =>
- [f, await fsStatGzip(path.join(distPath, f))] as [string, number]
+ [f, await getSize(path.join(distPath, f))] as [string, number]
)
)
} catch (_) {
@@ -486,9 +506,13 @@ function sum(a: number[]): number {
export async function getJsPageSizeInKb(
page: string,
distPath: string,
- buildManifest: BuildManifest
+ buildManifest: BuildManifest,
+ gzipSize: boolean = true,
+ computedManifestData?: ComputeManifestShape
): Promise<[number, number]> {
- const data = await computeFromManifest(buildManifest, distPath)
+ const data =
+ computedManifestData ||
+ (await computeFromManifest(buildManifest, distPath, gzipSize))
const fnFilterJs = (entry: string) => entry.endsWith('.js')
@@ -507,11 +531,13 @@ export async function getJsPageSizeInKb(
data.commonFiles
).map(fnMapRealPath)
+ const getSize = gzipSize ? fsStatGzip : fsStat
+
try {
// Doesn't use `Promise.all`, as we'd double compute duplicate files. This
// function is memoized, so the second one will instantly resolve.
- const allFilesSize = sum(await Promise.all(allFilesReal.map(fsStatGzip)))
- const selfFilesSize = sum(await Promise.all(selfFilesReal.map(fsStatGzip)))
+ const allFilesSize = sum(await Promise.all(allFilesReal.map(getSize)))
+ const selfFilesSize = sum(await Promise.all(selfFilesReal.map(getSize)))
return [selfFilesSize, allFilesSize]
} catch (_) {}
diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts
index 9f3c72a177d24fd..4050a470e4b88d5 100644
--- a/packages/next/build/webpack-config.ts
+++ b/packages/next/build/webpack-config.ts
@@ -287,7 +287,6 @@ export default async function getBaseWebpackConfig(
/next[\\/]dist[\\/]next-server[\\/]lib/,
/next[\\/]dist[\\/]client/,
/next[\\/]dist[\\/]pages/,
- /[\\/](strip-ansi|ansi-regex)[\\/]/,
]
// Support for NODE_PATH
@@ -1260,6 +1259,7 @@ export default async function getBaseWebpackConfig(
pageEnv: config.experimental.pageEnv,
excludeDefaultMomentLocales: config.future.excludeDefaultMomentLocales,
assetPrefix: config.assetPrefix,
+ disableOptimizedLoading: config.experimental.disableOptimizedLoading,
target,
reactProductionProfiling,
webpack: !!config.webpack,
diff --git a/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts b/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts
index de8e14e420d84c6..2619b5a4f114254 100644
--- a/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts
+++ b/packages/next/build/webpack/loaders/next-serverless-loader/utils.ts
@@ -289,7 +289,13 @@ export function getUtils({
// on the parsed params, this is used to signal if we need
// to parse x-now-route-matches or not
const isDefaultValue = Array.isArray(value)
- ? value.every((val, idx) => val === defaultRouteMatches![key][idx])
+ ? value.some((val) => {
+ const defaultValue = defaultRouteMatches![key]
+
+ return Array.isArray(defaultValue)
+ ? defaultValue.includes(val)
+ : defaultValue === val
+ })
: value === defaultRouteMatches![key]
if (isDefaultValue || typeof value === 'undefined') {
diff --git a/packages/next/data.sqlite b/packages/next/data.sqlite
new file mode 100644
index 000000000000000..e69de29bb2d1d64
diff --git a/packages/next/export/index.ts b/packages/next/export/index.ts
index 7d8cc3fca103494..54a8bf54b38da3a 100644
--- a/packages/next/export/index.ts
+++ b/packages/next/export/index.ts
@@ -369,6 +369,7 @@ export default async function exportApp(
defaultLocale: i18n?.defaultLocale,
domainLocales: i18n?.domains,
trailingSlash: nextConfig.trailingSlash,
+ disableOptimizedLoading: nextConfig.experimental.disableOptimizedLoading,
}
const { serverRuntimeConfig, publicRuntimeConfig } = nextConfig
@@ -511,7 +512,7 @@ export default async function exportApp(
const worker = new Worker(require.resolve('./worker'), {
maxRetries: 0,
numWorkers: threads,
- enableWorkerThreads: true,
+ enableWorkerThreads: nextConfig.experimental.workerThreads,
exposedMethods: ['default'],
}) as Worker & { default: typeof exportPage }
@@ -541,6 +542,8 @@ export default async function exportApp(
optimizeFonts: nextConfig.optimizeFonts,
optimizeImages: nextConfig.experimental.optimizeImages,
optimizeCss: nextConfig.experimental.optimizeCss,
+ disableOptimizedLoading:
+ nextConfig.experimental.disableOptimizedLoading,
parentSpanId: pageExportSpan.id,
})
diff --git a/packages/next/export/worker.ts b/packages/next/export/worker.ts
index 68f03b80f4ba674..057c4c5f1ebd546 100644
--- a/packages/next/export/worker.ts
+++ b/packages/next/export/worker.ts
@@ -52,6 +52,7 @@ interface ExportPageInput {
optimizeFonts: boolean
optimizeImages?: boolean
optimizeCss: any
+ disableOptimizedLoading: any
parentSpanId: any
}
@@ -70,6 +71,7 @@ interface RenderOpts {
ampSkipValidation?: boolean
optimizeFonts?: boolean
optimizeImages?: boolean
+ disableOptimizedLoading?: boolean
optimizeCss?: any
fontManifest?: FontManifest
locales?: string[]
@@ -98,6 +100,7 @@ export default async function exportPage({
optimizeFonts,
optimizeImages,
optimizeCss,
+ disableOptimizedLoading,
}: ExportPageInput): Promise {
const exportPageSpan = trace('export-page-worker', parentSpanId)
@@ -284,6 +287,7 @@ export default async function exportPage({
optimizeImages,
/// @ts-ignore
optimizeCss,
+ disableOptimizedLoading,
distDir,
fontManifest: optimizeFonts
? requireFontManifest(distDir, serverless)
@@ -357,6 +361,7 @@ export default async function exportPage({
optimizeFonts,
optimizeImages,
optimizeCss,
+ disableOptimizedLoading,
fontManifest: optimizeFonts
? requireFontManifest(distDir, serverless)
: null,
diff --git a/packages/next/lib/typescript/writeConfigurationDefaults.ts b/packages/next/lib/typescript/writeConfigurationDefaults.ts
index 0f8ee3ae4f0495d..04333a8b33eae12 100644
--- a/packages/next/lib/typescript/writeConfigurationDefaults.ts
+++ b/packages/next/lib/typescript/writeConfigurationDefaults.ts
@@ -1,7 +1,6 @@
import { promises as fs } from 'fs'
import chalk from 'chalk'
import * as CommentJson from 'next/dist/compiled/comment-json'
-import semver from 'next/dist/compiled/semver'
import os from 'os'
import { getTypeScriptConfiguration } from './getTypeScriptConfiguration'
@@ -29,9 +28,6 @@ function getDesiredCompilerOptions(
strict: { suggested: false },
forceConsistentCasingInFileNames: { suggested: true },
noEmit: { suggested: true },
- ...(semver.gte(ts.version, '4.3.0-beta')
- ? { incremental: { suggested: true } }
- : undefined),
// These values are required and cannot be changed by the user
// Keep this in sync with the webpack config
diff --git a/packages/next/lib/verifyTypeScriptSetup.ts b/packages/next/lib/verifyTypeScriptSetup.ts
index b37b26e0508809e..c2c36b2d0934e90 100644
--- a/packages/next/lib/verifyTypeScriptSetup.ts
+++ b/packages/next/lib/verifyTypeScriptSetup.ts
@@ -8,7 +8,7 @@ import { CompileError } from './compile-error'
import { FatalError } from './fatal-error'
import { getTypeScriptIntent } from './typescript/getTypeScriptIntent'
-import type { TypeCheckResult } from './typescript/runTypeCheck'
+import { TypeCheckResult } from './typescript/runTypeCheck'
import { writeAppTypeDeclarations } from './typescript/writeAppTypeDeclarations'
import { writeConfigurationDefaults } from './typescript/writeConfigurationDefaults'
diff --git a/packages/next/next-server/lib/post-process.ts b/packages/next/next-server/lib/post-process.ts
index fc446f581189a91..2a448f64bab560a 100644
--- a/packages/next/next-server/lib/post-process.ts
+++ b/packages/next/next-server/lib/post-process.ts
@@ -1,3 +1,4 @@
+import escapeRegexp from 'next/dist/compiled/escape-string-regexp'
import { parse, HTMLElement } from 'node-html-parser'
import { OPTIMIZED_FONT_PROVIDERS } from './constants'
@@ -188,7 +189,8 @@ function isImgEligible(imgElement: HTMLElement): boolean {
}
function preloadTagAlreadyExists(html: string, href: string) {
- const regex = new RegExp(` ]*href[^>]*${href}`)
+ const escapedHref = escapeRegexp(href)
+ const regex = new RegExp(` ]*href[^>]*${escapedHref}`)
return html.match(regex)
}
diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts
index de1a91b942c7211..9e495493ebf8cd2 100644
--- a/packages/next/next-server/lib/router/router.ts
+++ b/packages/next/next-server/lib/router/router.ts
@@ -800,6 +800,7 @@ export default class Router implements BaseRouter {
window.location.href = url
return false
}
+ const shouldResolveHref = url === as || (options as any)._h
// for static pages with query params in the URL we delay
// marking the router ready until after the query is updated
@@ -976,7 +977,7 @@ export default class Router implements BaseRouter {
? removePathTrailingSlash(delBasePath(pathname))
: pathname
- if (pathname !== '/_error') {
+ if (shouldResolveHref && pathname !== '/_error') {
if (process.env.__NEXT_HAS_REWRITES && as.startsWith('/')) {
const rewritesResult = resolveRewrites(
addBasePath(addLocale(cleanedAs, this.locale)),
diff --git a/packages/next/next-server/lib/utils.ts b/packages/next/next-server/lib/utils.ts
index eaaa30b2c806ce3..6af8e33dbdb7f67 100644
--- a/packages/next/next-server/lib/utils.ts
+++ b/packages/next/next-server/lib/utils.ts
@@ -193,6 +193,7 @@ export type DocumentProps = DocumentInitialProps & {
devOnlyCacheBusterQueryString: string
scriptLoader: { afterInteractive?: string[]; beforeInteractive?: any[] }
locale?: string
+ disableOptimizedLoading?: boolean
}
/**
diff --git a/packages/next/next-server/server/config-shared.ts b/packages/next/next-server/server/config-shared.ts
index fb45863f3269e17..42976289ee886c9 100644
--- a/packages/next/next-server/server/config-shared.ts
+++ b/packages/next/next-server/server/config-shared.ts
@@ -61,6 +61,8 @@ export type NextConfig = { [key: string]: any } & {
eslint?: boolean
reactRoot: boolean
enableBlurryPlaceholder: boolean
+ disableOptimizedLoading: boolean
+ gzipSize: boolean
}
}
@@ -118,6 +120,8 @@ export const defaultConfig: NextConfig = {
eslint: false,
reactRoot: Number(process.env.NEXT_PRIVATE_REACT_ROOT) > 0,
enableBlurryPlaceholder: false,
+ disableOptimizedLoading: true,
+ gzipSize: true,
},
future: {
strictPostcssConfiguration: false,
diff --git a/packages/next/next-server/server/config-utils.ts b/packages/next/next-server/server/config-utils.ts
index 742b30bca485f19..77f34ff05fb5751 100644
--- a/packages/next/next-server/server/config-utils.ts
+++ b/packages/next/next-server/server/config-utils.ts
@@ -1,7 +1,7 @@
import path from 'path'
import { Worker } from 'jest-worker'
import * as Log from '../../build/output/log'
-import type { CheckReasons, CheckResult } from './config-utils-worker'
+import { CheckReasons, CheckResult } from './config-utils-worker'
import { install, shouldLoadWithWebpack5 } from './config-utils-worker'
export { install, shouldLoadWithWebpack5 }
diff --git a/packages/next/next-server/server/config.ts b/packages/next/next-server/server/config.ts
index 04b5691d5b0ab6d..beeb39de5a9fc9e 100644
--- a/packages/next/next-server/server/config.ts
+++ b/packages/next/next-server/server/config.ts
@@ -56,7 +56,11 @@ function assignDefaults(userConfig: { [key: string]: any }) {
return currentConfig
}
- if (key === 'experimental' && value && value !== defaultConfig[key]) {
+ if (
+ key === 'experimental' &&
+ value !== undefined &&
+ value !== defaultConfig[key]
+ ) {
experimentalWarning()
}
diff --git a/packages/next/next-server/server/next-server.ts b/packages/next/next-server/server/next-server.ts
index 0b367f43a1a4e18..edb480402608a18 100644
--- a/packages/next/next-server/server/next-server.ts
+++ b/packages/next/next-server/server/next-server.ts
@@ -157,6 +157,7 @@ export default class Server {
images: string
fontManifest: FontManifest
optimizeImages: boolean
+ disableOptimizedLoading: boolean
optimizeCss: any
locale?: string
locales?: string[]
@@ -217,6 +218,8 @@ export default class Server {
: null,
optimizeImages: !!this.nextConfig.experimental.optimizeImages,
optimizeCss: this.nextConfig.experimental.optimizeCss,
+ disableOptimizedLoading: this.nextConfig.experimental
+ .disableOptimizedLoading,
domainLocales: this.nextConfig.i18n?.domains,
distDir: this.distDir,
}
@@ -815,28 +818,30 @@ export default class Server {
}
// Headers come very first
- const headers = this.customRoutes.headers.map((r) => {
- const headerRoute = getCustomRoute(r, 'header')
- return {
- match: headerRoute.match,
- has: headerRoute.has,
- type: headerRoute.type,
- name: `${headerRoute.type} ${headerRoute.source} header route`,
- fn: async (_req, res, params, _parsedUrl) => {
- const hasParams = Object.keys(params).length > 0
-
- for (const header of (headerRoute as Header).headers) {
- let { key, value } = header
- if (hasParams) {
- key = compileNonPath(key, params)
- value = compileNonPath(value, params)
- }
- res.setHeader(key, value)
- }
- return { finished: false }
- },
- } as Route
- })
+ const headers = this.minimalMode
+ ? []
+ : this.customRoutes.headers.map((r) => {
+ const headerRoute = getCustomRoute(r, 'header')
+ return {
+ match: headerRoute.match,
+ has: headerRoute.has,
+ type: headerRoute.type,
+ name: `${headerRoute.type} ${headerRoute.source} header route`,
+ fn: async (_req, res, params, _parsedUrl) => {
+ const hasParams = Object.keys(params).length > 0
+
+ for (const header of (headerRoute as Header).headers) {
+ let { key, value } = header
+ if (hasParams) {
+ key = compileNonPath(key, params)
+ value = compileNonPath(value, params)
+ }
+ res.setHeader(key, value)
+ }
+ return { finished: false }
+ },
+ } as Route
+ })
// since initial query values are decoded by querystring.parse
// we need to re-encode them here but still allow passing through
@@ -968,12 +973,14 @@ export default class Server {
let afterFiles: Route[] = []
let fallback: Route[] = []
- if (Array.isArray(this.customRoutes.rewrites)) {
- afterFiles = this.customRoutes.rewrites.map(buildRewrite)
- } else {
- beforeFiles = this.customRoutes.rewrites.beforeFiles.map(buildRewrite)
- afterFiles = this.customRoutes.rewrites.afterFiles.map(buildRewrite)
- fallback = this.customRoutes.rewrites.fallback.map(buildRewrite)
+ if (!this.minimalMode) {
+ if (Array.isArray(this.customRoutes.rewrites)) {
+ afterFiles = this.customRoutes.rewrites.map(buildRewrite)
+ } else {
+ beforeFiles = this.customRoutes.rewrites.beforeFiles.map(buildRewrite)
+ afterFiles = this.customRoutes.rewrites.afterFiles.map(buildRewrite)
+ fallback = this.customRoutes.rewrites.fallback.map(buildRewrite)
+ }
}
const catchAllRoute: Route = {
diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx
index b00e19fb162d4dd..6508c887415a10a 100644
--- a/packages/next/next-server/server/render.tsx
+++ b/packages/next/next-server/server/render.tsx
@@ -190,6 +190,7 @@ export type RenderOptsPartial = {
locales?: string[]
defaultLocale?: string
domainLocales?: DomainLocales
+ disableOptimizedLoading?: boolean
}
export type RenderOpts = LoadComponentsReturnType & RenderOptsPartial
@@ -234,6 +235,7 @@ function renderDocument(
defaultLocale,
domainLocales,
isPreview,
+ disableOptimizedLoading,
}: RenderOpts & {
props: any
docComponentsRendered: DocumentProps['docComponentsRendered']
@@ -305,6 +307,7 @@ function renderDocument(
devOnlyCacheBusterQueryString,
scriptLoader,
locale,
+ disableOptimizedLoading,
...docProps,
})}
diff --git a/packages/next/package.json b/packages/next/package.json
index 5057f90d64a5d91..37cbeffc3058dfb 100644
--- a/packages/next/package.json
+++ b/packages/next/package.json
@@ -1,6 +1,6 @@
{
"name": "next",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"description": "The React Framework",
"main": "./dist/server/next.js",
"license": "MIT",
@@ -64,10 +64,10 @@
"dependencies": {
"@babel/runtime": "7.12.5",
"@hapi/accept": "5.0.1",
- "@next/env": "10.2.1-canary.5",
- "@next/polyfill-module": "10.2.1-canary.5",
- "@next/react-dev-overlay": "10.2.1-canary.5",
- "@next/react-refresh-utils": "10.2.1-canary.5",
+ "@next/env": "10.2.1-canary.7",
+ "@next/polyfill-module": "10.2.1-canary.7",
+ "@next/react-dev-overlay": "10.2.1-canary.7",
+ "@next/react-refresh-utils": "10.2.1-canary.7",
"@opentelemetry/api": "0.14.0",
"assert": "2.0.0",
"ast-types": "0.13.2",
@@ -151,7 +151,7 @@
"@babel/preset-typescript": "7.12.7",
"@babel/traverse": "^7.12.10",
"@babel/types": "7.12.12",
- "@next/polyfill-nomodule": "10.2.1-canary.5",
+ "@next/polyfill-nomodule": "10.2.1-canary.7",
"@taskr/clear": "1.1.0",
"@taskr/esnext": "1.1.0",
"@taskr/watch": "1.1.0",
diff --git a/packages/next/pages/_document.tsx b/packages/next/pages/_document.tsx
index 98d1d7e1907c06a..d3a486a0e4de99c 100644
--- a/packages/next/pages/_document.tsx
+++ b/packages/next/pages/_document.tsx
@@ -51,6 +51,115 @@ function getDocumentFiles(
}
}
+function getPolyfillScripts(context: DocumentProps, props: OriginProps) {
+ // polyfills.js has to be rendered as nomodule without async
+ // It also has to be the first script to load
+ const {
+ assetPrefix,
+ buildManifest,
+ devOnlyCacheBusterQueryString,
+ disableOptimizedLoading,
+ } = context
+
+ return buildManifest.polyfillFiles
+ .filter(
+ (polyfill) => polyfill.endsWith('.js') && !polyfill.endsWith('.module.js')
+ )
+ .map((polyfill) => (
+
+ ))
+}
+
+function getPreNextScripts(context: DocumentProps, props: OriginProps) {
+ const { scriptLoader, disableOptimizedLoading } = context
+
+ return (scriptLoader.beforeInteractive || []).map(
+ (file: ScriptLoaderProps) => {
+ const { strategy, ...scriptProps } = file
+ return (
+
+ )
+ }
+ )
+}
+
+function getDynamicChunks(
+ context: DocumentProps,
+ props: OriginProps,
+ files: DocumentFiles
+) {
+ const {
+ dynamicImports,
+ assetPrefix,
+ isDevelopment,
+ devOnlyCacheBusterQueryString,
+ disableOptimizedLoading,
+ } = context
+
+ return dynamicImports.map((file) => {
+ if (!file.endsWith('.js') || files.allFiles.includes(file)) return null
+
+ return (
+
+ )
+ })
+}
+
+function getScripts(
+ context: DocumentProps,
+ props: OriginProps,
+ files: DocumentFiles
+) {
+ const {
+ assetPrefix,
+ buildManifest,
+ isDevelopment,
+ devOnlyCacheBusterQueryString,
+ disableOptimizedLoading,
+ } = context
+
+ const normalScripts = files.allFiles.filter((file) => file.endsWith('.js'))
+ const lowPriorityScripts = buildManifest.lowPriorityFiles?.filter((file) =>
+ file.endsWith('.js')
+ )
+
+ return [...normalScripts, ...lowPriorityScripts].map((file) => {
+ return (
+
+ )
+ })
+}
+
/**
* `Document` component handles the initial `document` markup and renders only on the server side.
* Commonly used for implementing server side rendering for `css-in-js` libraries.
@@ -285,6 +394,22 @@ export class Head extends Component<
]
}
+ getDynamicChunks(files: DocumentFiles) {
+ return getDynamicChunks(this.context, this.props, files)
+ }
+
+ getPreNextScripts() {
+ return getPreNextScripts(this.context, this.props)
+ }
+
+ getScripts(files: DocumentFiles) {
+ return getScripts(this.context, this.props, files)
+ }
+
+ getPolyfillScripts() {
+ return getPolyfillScripts(this.context, this.props)
+ }
+
handleDocumentScriptLoaderItems(children: React.ReactNode): ReactNode[] {
const { scriptLoader } = this.context
const scriptLoaderItems: ScriptLoaderProps[] = []
@@ -347,9 +472,12 @@ export class Head extends Component<
headTags,
unstable_runtimeJS,
unstable_JsPreload,
+ disableOptimizedLoading,
} = this.context
+
const disableRuntimeJS = unstable_runtimeJS === false
- const disableJsPreload = unstable_JsPreload === false
+ const disableJsPreload =
+ unstable_JsPreload === false || !disableOptimizedLoading
this.context.docComponentsRendered.Head = true
@@ -582,6 +710,18 @@ export class Head extends Component<
{!disableRuntimeJS &&
!disableJsPreload &&
this.getPreloadMainLinks(files)}
+ {!disableOptimizedLoading &&
+ !disableRuntimeJS &&
+ this.getPolyfillScripts()}
+ {!disableOptimizedLoading &&
+ !disableRuntimeJS &&
+ this.getPreNextScripts()}
+ {!disableOptimizedLoading &&
+ !disableRuntimeJS &&
+ this.getDynamicChunks(files)}
+ {!disableOptimizedLoading &&
+ !disableRuntimeJS &&
+ this.getScripts(files)}
{process.env.__NEXT_OPTIMIZE_CSS && this.getCssLinks(files)}
{process.env.__NEXT_OPTIMIZE_CSS && (
@@ -627,106 +767,19 @@ export class NextScript extends Component {
'!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();'
getDynamicChunks(files: DocumentFiles) {
- const {
- dynamicImports,
- assetPrefix,
- isDevelopment,
- devOnlyCacheBusterQueryString,
- } = this.context
-
- return dynamicImports.map((file) => {
- if (!file.endsWith('.js') || files.allFiles.includes(file)) return null
-
- return (
-
- )
- })
+ return getDynamicChunks(this.context, this.props, files)
}
getPreNextScripts() {
- const { scriptLoader } = this.context
-
- return (scriptLoader.beforeInteractive || []).map(
- (file: ScriptLoaderProps) => {
- const { strategy, ...props } = file
- return (
-
- )
- }
- )
+ return getPreNextScripts(this.context, this.props)
}
getScripts(files: DocumentFiles) {
- const {
- assetPrefix,
- buildManifest,
- isDevelopment,
- devOnlyCacheBusterQueryString,
- } = this.context
-
- const normalScripts = files.allFiles.filter((file) => file.endsWith('.js'))
- const lowPriorityScripts = buildManifest.lowPriorityFiles?.filter((file) =>
- file.endsWith('.js')
- )
-
- return [...normalScripts, ...lowPriorityScripts].map((file) => {
- return (
-
- )
- })
+ return getScripts(this.context, this.props, files)
}
getPolyfillScripts() {
- // polyfills.js has to be rendered as nomodule without async
- // It also has to be the first script to load
- const {
- assetPrefix,
- buildManifest,
- devOnlyCacheBusterQueryString,
- } = this.context
-
- return buildManifest.polyfillFiles
- .filter(
- (polyfill) =>
- polyfill.endsWith('.js') && !polyfill.endsWith('.module.js')
- )
- .map((polyfill) => (
-
- ))
+ return getPolyfillScripts(this.context, this.props)
}
static getInlineScriptSource(documentProps: Readonly): string {
@@ -752,6 +805,7 @@ export class NextScript extends Component {
unstable_runtimeJS,
docComponentsRendered,
devOnlyCacheBusterQueryString,
+ disableOptimizedLoading,
} = this.context
const disableRuntimeJS = unstable_runtimeJS === false
@@ -841,10 +895,16 @@ export class NextScript extends Component {
}}
/>
)}
- {!disableRuntimeJS && this.getPolyfillScripts()}
- {!disableRuntimeJS && this.getPreNextScripts()}
- {disableRuntimeJS ? null : this.getDynamicChunks(files)}
- {disableRuntimeJS ? null : this.getScripts(files)}
+ {disableOptimizedLoading &&
+ !disableRuntimeJS &&
+ this.getPolyfillScripts()}
+ {disableOptimizedLoading &&
+ !disableRuntimeJS &&
+ this.getPreNextScripts()}
+ {disableOptimizedLoading &&
+ !disableRuntimeJS &&
+ this.getDynamicChunks(files)}
+ {disableOptimizedLoading && !disableRuntimeJS && this.getScripts(files)}
>
)
}
diff --git a/packages/next/server/next.ts b/packages/next/server/next.ts
index 6fd8c0e17ca2132..6af1dfe57bcc14e 100644
--- a/packages/next/server/next.ts
+++ b/packages/next/server/next.ts
@@ -1,5 +1,5 @@
import '../next-server/server/node-polyfill-fetch'
-import type {
+import {
default as Server,
ServerConstructor,
} from '../next-server/server/next-server'
diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json
index 08264fa06da1017..cd69f9fa250d168 100644
--- a/packages/react-dev-overlay/package.json
+++ b/packages/react-dev-overlay/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/react-dev-overlay",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"description": "A development-only overlay for developing React applications.",
"repository": {
"url": "vercel/next.js",
diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json
index 8fdf71c759a6858..f93bbcc0dfe5d63 100644
--- a/packages/react-refresh-utils/package.json
+++ b/packages/react-refresh-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/react-refresh-utils",
- "version": "10.2.1-canary.5",
+ "version": "10.2.1-canary.7",
"description": "An experimental package providing utilities for React Refresh.",
"repository": {
"url": "vercel/next.js",
diff --git a/test/integration/build-output/test/index.test.js b/test/integration/build-output/test/index.test.js
index 9e2064a1c708da3..7390a2dc4bcb7e8 100644
--- a/test/integration/build-output/test/index.test.js
+++ b/test/integration/build-output/test/index.test.js
@@ -2,7 +2,7 @@
import 'flat-map-polyfill'
import { remove } from 'fs-extra'
-import { nextBuild } from 'next-test-utils'
+import { nextBuild, File } from 'next-test-utils'
import { join } from 'path'
import { recursiveReadDir } from 'next/dist/lib/recursive-readdir'
@@ -10,133 +10,162 @@ jest.setTimeout(1000 * 60 * 2)
const fixturesDir = join(__dirname, '..', 'fixtures')
-describe('Build Output', () => {
- describe('Basic Application Output', () => {
- let stdout
- const appDir = join(fixturesDir, 'basic-app')
-
- beforeAll(async () => {
- await remove(join(appDir, '.next'))
- })
+const nextConfig = new File(join(fixturesDir, 'basic-app/next.config.js'))
- it('should not include internal pages', async () => {
- ;({ stdout } = await nextBuild(appDir, [], {
- stdout: true,
- }))
-
- expect(stdout).toMatch(/\/ [ ]* \d{1,} B/)
- expect(stdout).toMatch(/\+ First Load JS shared by all [ 0-9.]* kB/)
- expect(stdout).toMatch(/ chunks\/main\.[0-9a-z]{6}\.js [ 0-9.]* kB/)
- expect(stdout).toMatch(/ chunks\/framework\.[0-9a-z]{6}\.js [ 0-9. ]* kB/)
-
- expect(stdout).not.toContain(' /_document')
- expect(stdout).not.toContain(' /_app')
- expect(stdout).not.toContain(' /_error')
- expect(stdout).not.toContain('')
-
- expect(stdout).toContain('○ /')
- })
-
- it('should not deviate from snapshot', async () => {
- console.log(stdout)
-
- if (process.env.NEXT_PRIVATE_SKIP_SIZE_TESTS) {
- return
- }
+describe('Build Output', () => {
+ for (const gzipSize of [true, false, undefined]) {
+ describe(
+ 'Basic Application Output' +
+ (gzipSize !== undefined
+ ? ` (with experimental.gzipSize: ${gzipSize})`
+ : ''),
+ () => {
+ let stdout
+ const appDir = join(fixturesDir, 'basic-app')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ if (gzipSize !== undefined) {
+ nextConfig.write(
+ `module.exports = { experimental: { gzipSize: ${gzipSize} } };`
+ )
+ }
+ })
+
+ if (gzipSize !== undefined) {
+ afterAll(async () => {
+ nextConfig.delete()
+ })
+ }
- const parsePageSize = (page) =>
- stdout.match(
- new RegExp(` ${page} .*?((?:\\d|\\.){1,} (?:\\w{1,})) `)
- )[1]
+ it('should not include internal pages', async () => {
+ ;({ stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
- const parsePageFirstLoad = (page) =>
- stdout.match(
- new RegExp(
- ` ${page} .*?(?:(?:\\d|\\.){1,}) .*? ((?:\\d|\\.){1,} (?:\\w{1,}))`
+ expect(stdout).toMatch(/\/ [ ]* \d{1,} B/)
+ expect(stdout).toMatch(/\+ First Load JS shared by all [ 0-9.]* kB/)
+ expect(stdout).toMatch(/ chunks\/main\.[0-9a-z]{6}\.js [ 0-9.]* kB/)
+ expect(stdout).toMatch(
+ / chunks\/framework\.[0-9a-z]{6}\.js [ 0-9. ]* kB/
)
- )[1]
- const parseSharedSize = (sharedPartName) => {
- const matches = stdout.match(
- new RegExp(`${sharedPartName} .*? ((?:\\d|\\.){1,} (?:\\w{1,}))`)
- )
+ expect(stdout).not.toContain(' /_document')
+ expect(stdout).not.toContain(' /_app')
+ expect(stdout).not.toContain(' /_error')
+ expect(stdout).not.toContain('')
+
+ expect(stdout).toContain('○ /')
+ })
+
+ it('should not deviate from snapshot', async () => {
+ console.log(stdout)
+
+ if (process.env.NEXT_PRIVATE_SKIP_SIZE_TESTS) {
+ return
+ }
+
+ const parsePageSize = (page) =>
+ stdout.match(
+ new RegExp(` ${page} .*?((?:\\d|\\.){1,} (?:\\w{1,})) `)
+ )[1]
+
+ const parsePageFirstLoad = (page) =>
+ stdout.match(
+ new RegExp(
+ ` ${page} .*?(?:(?:\\d|\\.){1,}) .*? ((?:\\d|\\.){1,} (?:\\w{1,}))`
+ )
+ )[1]
+
+ const parseSharedSize = (sharedPartName) => {
+ const matches = stdout.match(
+ new RegExp(`${sharedPartName} .*? ((?:\\d|\\.){1,} (?:\\w{1,}))`)
+ )
+
+ if (!matches) {
+ throw new Error(`Could not match ${sharedPartName}`)
+ }
+
+ return matches[1]
+ }
+
+ const indexSize = parsePageSize('/')
+ const indexFirstLoad = parsePageFirstLoad('/')
+
+ const err404Size = parsePageSize('/404')
+ const err404FirstLoad = parsePageFirstLoad('/404')
+
+ const sharedByAll = parseSharedSize('shared by all')
+ const _appSize = parseSharedSize('_app\\..*?\\.js')
+ const webpackSize = parseSharedSize('webpack\\..*?\\.js')
+ const mainSize = parseSharedSize('main\\..*?\\.js')
+ const frameworkSize = parseSharedSize('framework\\..*?\\.js')
+
+ for (const size of [
+ indexSize,
+ indexFirstLoad,
+ err404Size,
+ err404FirstLoad,
+ sharedByAll,
+ _appSize,
+ webpackSize,
+ mainSize,
+ frameworkSize,
+ ]) {
+ expect(parseFloat(size)).toBeGreaterThan(0)
+ }
+
+ const gz = gzipSize !== false
+
+ expect(parseFloat(indexSize) / 1000).toBeCloseTo(
+ gz ? 0.251 : 0.394,
+ 2
+ )
+ expect(indexSize.endsWith('B')).toBe(true)
- if (!matches) {
- throw new Error(`Could not match ${sharedPartName}`)
- }
+ expect(parseFloat(indexFirstLoad)).toBeCloseTo(gz ? 63.6 : 195, 1)
+ expect(indexFirstLoad.endsWith('kB')).toBe(true)
- return matches[1]
- }
+ expect(parseFloat(err404Size)).toBeCloseTo(gz ? 3.06 : 8.15, 1)
+ expect(err404Size.endsWith('kB')).toBe(true)
- const indexSize = parsePageSize('/')
- const indexFirstLoad = parsePageFirstLoad('/')
-
- const err404Size = parsePageSize('/404')
- const err404FirstLoad = parsePageFirstLoad('/404')
-
- const sharedByAll = parseSharedSize('shared by all')
- const _appSize = parseSharedSize('_app\\..*?\\.js')
- const webpackSize = parseSharedSize('webpack\\..*?\\.js')
- const mainSize = parseSharedSize('main\\..*?\\.js')
- const frameworkSize = parseSharedSize('framework\\..*?\\.js')
-
- for (const size of [
- indexSize,
- indexFirstLoad,
- err404Size,
- err404FirstLoad,
- sharedByAll,
- _appSize,
- webpackSize,
- mainSize,
- frameworkSize,
- ]) {
- expect(parseFloat(size)).toBeGreaterThan(0)
- }
+ expect(parseFloat(err404FirstLoad)).toBeCloseTo(gz ? 66.5 : 203, 1)
+ expect(err404FirstLoad.endsWith('kB')).toBe(true)
- // should be no bigger than 291 bytes
- expect(parseFloat(indexSize) - 291).toBeLessThanOrEqual(0)
- expect(indexSize.endsWith('B')).toBe(true)
+ expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 63.4 : 195, 1)
+ expect(sharedByAll.endsWith('kB')).toBe(true)
- // should be no bigger than 64.8 kb
- expect(parseFloat(indexFirstLoad)).toBeCloseTo(63.6, 1)
- expect(indexFirstLoad.endsWith('kB')).toBe(true)
+ const appSizeValue = _appSize.endsWith('kB')
+ ? parseFloat(_appSize)
+ : parseFloat(_appSize) / 1000
+ expect(appSizeValue).toBeCloseTo(gz ? 1.0 : 2.18, 1)
+ expect(_appSize.endsWith('kB') || _appSize.endsWith(' B')).toBe(true)
- expect(parseFloat(err404Size)).toBeCloseTo(3.04, 1)
- expect(err404Size.endsWith('kB')).toBe(true)
+ const webpackSizeValue = webpackSize.endsWith('kB')
+ ? parseFloat(webpackSize)
+ : parseFloat(webpackSize) / 1000
+ expect(webpackSizeValue).toBeCloseTo(gz ? 0.95 : 1.81, 2)
+ expect(webpackSize.endsWith('kB') || webpackSize.endsWith(' B')).toBe(
+ true
+ )
- expect(parseFloat(err404FirstLoad)).toBeCloseTo(66.3, 0)
- expect(err404FirstLoad.endsWith('kB')).toBe(true)
+ expect(parseFloat(mainSize)).toBeCloseTo(gz ? 19.4 : 60.4, 1)
+ expect(mainSize.endsWith('kB')).toBe(true)
- expect(parseFloat(sharedByAll)).toBeCloseTo(63.4, 1)
- expect(sharedByAll.endsWith('kB')).toBe(true)
+ expect(parseFloat(frameworkSize)).toBeCloseTo(gz ? 42.0 : 130, 1)
+ expect(frameworkSize.endsWith('kB')).toBe(true)
+ })
- if (_appSize.endsWith('kB')) {
- expect(parseFloat(_appSize)).toBeLessThanOrEqual(1.02)
- expect(_appSize.endsWith('kB')).toBe(true)
- } else {
- expect(parseFloat(_appSize) - 1000).toBeLessThanOrEqual(0)
- expect(_appSize.endsWith(' B')).toBe(true)
+ it('should not emit extracted comments', async () => {
+ const files = await recursiveReadDir(
+ join(appDir, '.next'),
+ /\.txt|\.LICENSE\./
+ )
+ expect(files).toEqual([])
+ })
}
-
- expect(parseFloat(webpackSize) - 952).toBeLessThanOrEqual(0)
- expect(webpackSize.endsWith(' B')).toBe(true)
-
- expect(parseFloat(mainSize) - 19.4).toBeLessThanOrEqual(0)
- expect(mainSize.endsWith('kB')).toBe(true)
-
- expect(parseFloat(frameworkSize) - 42.1).toBeLessThanOrEqual(0)
- expect(frameworkSize.endsWith('kB')).toBe(true)
- })
-
- it('should not emit extracted comments', async () => {
- const files = await recursiveReadDir(
- join(appDir, '.next'),
- /\.txt|\.LICENSE\./
- )
- expect(files).toEqual([])
- })
- })
+ )
+ }
describe('Custom App Output', () => {
const appDir = join(fixturesDir, 'with-app')
diff --git a/test/integration/image-optimization/pages/with-querystring.js b/test/integration/image-optimization/pages/with-querystring.js
new file mode 100644
index 000000000000000..397bb1276c2d3a1
--- /dev/null
+++ b/test/integration/image-optimization/pages/with-querystring.js
@@ -0,0 +1,12 @@
+import React from 'react'
+
+const Page = () => {
+ return (
+
+
+
+
+ )
+}
+
+export default Page
diff --git a/test/integration/image-optimization/test/index.test.js b/test/integration/image-optimization/test/index.test.js
index 262a0a7a35edfc6..88745f9c3a9d298 100644
--- a/test/integration/image-optimization/test/index.test.js
+++ b/test/integration/image-optimization/test/index.test.js
@@ -25,6 +25,18 @@ function runTests() {
describe('On an SSR page', () => {
checkImagesOnPage('/stars')
})
+
+ describe('On a static page with querystring ', () => {
+ it('should preload exactly eligible image', async () => {
+ const html = await renderViaHTTP(appPort, '/with-querystring')
+ expect(html).toContain(
+ ' '
+ )
+ expect(html).toContain(
+ ' '
+ )
+ })
+ })
}
function checkImagesOnPage(path) {
diff --git a/test/integration/optimized-loading/next.config.js b/test/integration/optimized-loading/next.config.js
new file mode 100644
index 000000000000000..85ca85bea7b4c0d
--- /dev/null
+++ b/test/integration/optimized-loading/next.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ experimental: { disableOptimizedLoading: false },
+}
diff --git a/test/integration/optimized-loading/pages/index.js b/test/integration/optimized-loading/pages/index.js
new file mode 100644
index 000000000000000..33e1dc15b43c1f2
--- /dev/null
+++ b/test/integration/optimized-loading/pages/index.js
@@ -0,0 +1,10 @@
+import Link from 'next/link'
+
+export default () => (
+
+
Hello World!
+
+
+ Without font
+
+)
diff --git a/test/integration/optimized-loading/pages/page1.js b/test/integration/optimized-loading/pages/page1.js
new file mode 100644
index 000000000000000..5e79c53444ba8c7
--- /dev/null
+++ b/test/integration/optimized-loading/pages/page1.js
@@ -0,0 +1,9 @@
+export default () => Hello World!
+
+export const getServerSideProps = () => {
+ return {
+ props: {
+ hello: 'world',
+ },
+ }
+}
diff --git a/test/integration/optimized-loading/test/index.test.js b/test/integration/optimized-loading/test/index.test.js
new file mode 100644
index 000000000000000..0223128aa65b395
--- /dev/null
+++ b/test/integration/optimized-loading/test/index.test.js
@@ -0,0 +1,75 @@
+/* eslint-env jest */
+
+import { join } from 'path'
+import cheerio from 'cheerio'
+import {
+ nextServer,
+ nextBuild,
+ startApp,
+ stopApp,
+ renderViaHTTP,
+ findPort,
+ launchApp,
+ killApp,
+} from 'next-test-utils'
+
+const appDir = join(__dirname, '../')
+let server
+let app
+jest.setTimeout(1000 * 60 * 5)
+
+const context = {}
+
+function runTests(url) {
+ it('should render the page', async () => {
+ const html = await renderViaHTTP(context.appPort, url)
+ expect(html).toMatch(/Hello World/)
+ })
+
+ it('should not have JS preload links', async () => {
+ const html = await renderViaHTTP(context.appPort, url)
+ const $ = cheerio.load(html)
+ expect($('link[rel=preload]').length).toBe(0)
+ })
+
+ it('should load scripts with defer in head', async () => {
+ const html = await renderViaHTTP(context.appPort, url)
+ const $ = cheerio.load(html)
+ expect($('script[async]').length).toBe(0)
+ expect($('head script[defer]').length).toBeGreaterThan(0)
+ })
+}
+
+describe('Optimized loading', () => {
+ describe('production mode', () => {
+ beforeAll(async () => {
+ await nextBuild(appDir)
+ app = nextServer({
+ dir: join(__dirname, '../'),
+ dev: false,
+ quiet: true,
+ })
+
+ server = await startApp(app)
+ context.appPort = server.address().port
+ })
+ afterAll(() => stopApp(server))
+
+ runTests('/')
+ runTests('/page1')
+ })
+
+ describe('dev mode', () => {
+ let app
+
+ beforeAll(async () => {
+ context.appPort = await findPort()
+ app = await launchApp(join(__dirname, '../'), context.appPort)
+ })
+
+ afterAll(() => killApp(app))
+
+ runTests('/')
+ runTests('/page1')
+ })
+})
diff --git a/test/integration/prerender-native-module/data.sqlite b/test/integration/prerender-native-module/data.sqlite
new file mode 100644
index 000000000000000..658fe04154f7613
Binary files /dev/null and b/test/integration/prerender-native-module/data.sqlite differ
diff --git a/test/integration/prerender-native-module/pages/blog/[slug].js b/test/integration/prerender-native-module/pages/blog/[slug].js
new file mode 100644
index 000000000000000..f181d158ad37029
--- /dev/null
+++ b/test/integration/prerender-native-module/pages/blog/[slug].js
@@ -0,0 +1,46 @@
+import path from 'path'
+import { open } from 'sqlite'
+import sqlite3 from 'sqlite3'
+import { useRouter } from 'next/router'
+
+export const getStaticProps = async ({ params }) => {
+ const dbPath = path.join(process.cwd(), 'data.sqlite')
+ console.log('using db', dbPath)
+
+ const db = await open({
+ filename: dbPath,
+ driver: sqlite3.Database,
+ })
+
+ const users = await db.all(`SELECT * FROM users`)
+
+ return {
+ props: {
+ users,
+ blog: true,
+ params: params || null,
+ },
+ }
+}
+
+export const getStaticPaths = () => {
+ return {
+ paths: ['/blog/first'],
+ fallback: true,
+ }
+}
+
+export default function Page(props) {
+ const router = useRouter()
+
+ if (router.isFallback) {
+ return 'Loading...'
+ }
+
+ return (
+ <>
+ blog page
+ {JSON.stringify(props)}
+ >
+ )
+}
diff --git a/test/integration/prerender-native-module/pages/index.js b/test/integration/prerender-native-module/pages/index.js
new file mode 100644
index 000000000000000..39a9c6502ed04e3
--- /dev/null
+++ b/test/integration/prerender-native-module/pages/index.js
@@ -0,0 +1,16 @@
+export const getStaticProps = () => {
+ return {
+ props: {
+ index: true,
+ },
+ }
+}
+
+export default function Page(props) {
+ return (
+ <>
+ index page
+ {JSON.stringify(props)}
+ >
+ )
+}
diff --git a/test/integration/prerender-native-module/test/index.test.js b/test/integration/prerender-native-module/test/index.test.js
new file mode 100644
index 000000000000000..21198c242a225c3
--- /dev/null
+++ b/test/integration/prerender-native-module/test/index.test.js
@@ -0,0 +1,88 @@
+/* eslint-env jest */
+
+import { join } from 'path'
+import webdriver from 'next-webdriver'
+import {
+ findPort,
+ killApp,
+ launchApp,
+ nextBuild,
+ nextStart,
+} from 'next-test-utils'
+
+jest.setTimeout(1000 * 60 * 2)
+
+let app
+let appPort
+const appDir = join(__dirname, '..')
+
+const runTests = () => {
+ it('should render index correctly', async () => {
+ const browser = await webdriver(appPort, '/')
+ expect(await browser.elementByCss('#index').text()).toBe('index page')
+ expect(JSON.parse(await browser.elementByCss('#props').text())).toEqual({
+ index: true,
+ })
+ })
+
+ it('should render /blog/first correctly', async () => {
+ const browser = await webdriver(appPort, '/blog/first')
+
+ expect(await browser.elementByCss('#blog').text()).toBe('blog page')
+ expect(JSON.parse(await browser.elementByCss('#props').text())).toEqual({
+ params: { slug: 'first' },
+ blog: true,
+ users: [
+ { id: 1, first_name: 'john', last_name: 'deux' },
+ { id: 2, first_name: 'zeit', last_name: 'geist' },
+ ],
+ })
+ })
+
+ it('should render /blog/second correctly', async () => {
+ const browser = await webdriver(appPort, '/blog/second')
+ await browser.waitForElementByCss('#blog')
+
+ expect(await browser.elementByCss('#blog').text()).toBe('blog page')
+ expect(JSON.parse(await browser.elementByCss('#props').text())).toEqual({
+ params: { slug: 'second' },
+ blog: true,
+ users: [
+ { id: 1, first_name: 'john', last_name: 'deux' },
+ { id: 2, first_name: 'zeit', last_name: 'geist' },
+ ],
+ })
+ })
+}
+
+describe('Prerender native module', () => {
+ describe('production', () => {
+ beforeAll(async () => {
+ const result = await nextBuild(appDir, undefined, {
+ cwd: appDir,
+ stderr: true,
+ stdout: true,
+ })
+
+ if (result.code !== 0) {
+ console.error(result)
+ throw new Error(`Failed to build, exited with code ${result.code}`)
+ }
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort, { cwd: appDir })
+ })
+ afterAll(() => killApp(app))
+
+ runTests()
+ })
+
+ describe('dev', () => {
+ beforeAll(async () => {
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort, { cwd: appDir })
+ })
+ afterAll(() => killApp(app))
+
+ runTests()
+ })
+})
diff --git a/test/integration/rewrites-manual-href-as/next.config.js b/test/integration/rewrites-manual-href-as/next.config.js
new file mode 100644
index 000000000000000..0716516e76e651c
--- /dev/null
+++ b/test/integration/rewrites-manual-href-as/next.config.js
@@ -0,0 +1,10 @@
+module.exports = {
+ rewrites() {
+ return [
+ {
+ source: '/rewrite-me',
+ destination: '/another',
+ },
+ ]
+ },
+}
diff --git a/test/integration/rewrites-manual-href-as/pages/another.js b/test/integration/rewrites-manual-href-as/pages/another.js
new file mode 100644
index 000000000000000..daaa9af4d90c255
--- /dev/null
+++ b/test/integration/rewrites-manual-href-as/pages/another.js
@@ -0,0 +1,24 @@
+import { useRouter } from 'next/router'
+import Link from 'next/link'
+
+export default function Page(props) {
+ const router = useRouter()
+
+ return (
+ <>
+ another page
+ {router.pathname}
+ {JSON.stringify(router.query)}
+
+
+ open modal for /preview/123
+
+
+
+
+ go to /preview/123
+
+
+ >
+ )
+}
diff --git a/test/integration/rewrites-manual-href-as/pages/index.js b/test/integration/rewrites-manual-href-as/pages/index.js
new file mode 100644
index 000000000000000..c6f32b544aea810
--- /dev/null
+++ b/test/integration/rewrites-manual-href-as/pages/index.js
@@ -0,0 +1,41 @@
+import { useRouter } from 'next/router'
+import Link from 'next/link'
+
+export default function Page(props) {
+ const router = useRouter()
+
+ return (
+ <>
+ index page
+ {router.pathname}
+ {JSON.stringify(router.query)}
+
+ {router.query.imageId ? show modal
: null}
+
+
+ open modal for /preview/123
+
+
+
+
+ go to /preview/123
+
+
+
+
+ go to /another
+
+
+
+
+ go to /rewrite-me
+
+
+
+
+ go to / as /rewrite-me
+
+
+ >
+ )
+}
diff --git a/test/integration/rewrites-manual-href-as/pages/preview/[slug].js b/test/integration/rewrites-manual-href-as/pages/preview/[slug].js
new file mode 100644
index 000000000000000..babe69b8629a438
--- /dev/null
+++ b/test/integration/rewrites-manual-href-as/pages/preview/[slug].js
@@ -0,0 +1,59 @@
+import { useRouter } from 'next/router'
+import Link from 'next/link'
+
+export const getStaticProps = ({ params }) => {
+ return {
+ props: {
+ params: params || null,
+ preview: true,
+ },
+ }
+}
+
+export const getStaticPaths = () => {
+ return {
+ paths: [],
+ fallback: 'blocking',
+ }
+}
+
+export default function Page(props) {
+ const router = useRouter()
+
+ return (
+ <>
+ preview page
+ {router.pathname}
+ {JSON.stringify(router.query)}
+ {JSON.stringify(props)}
+
+
+ open modal for /preview/123
+
+
+
+
+ go to /preview/321
+
+
+
+
+ go to /another
+
+
+
+
+ go to /rewrite-me
+
+
+
+
+ go to /preview/321 as /rewrite-me
+
+
+ >
+ )
+}
diff --git a/test/integration/rewrites-manual-href-as/test/index.test.js b/test/integration/rewrites-manual-href-as/test/index.test.js
new file mode 100644
index 000000000000000..4da273a03837281
--- /dev/null
+++ b/test/integration/rewrites-manual-href-as/test/index.test.js
@@ -0,0 +1,173 @@
+/* eslint-env jest */
+
+import { join } from 'path'
+import {
+ check,
+ findPort,
+ killApp,
+ launchApp,
+ nextBuild,
+ nextStart,
+} from 'next-test-utils'
+import webdriver from 'next-webdriver'
+
+jest.setTimeout(1000 * 60 * 2)
+
+const appDir = join(__dirname, '../')
+
+let appPort
+let app
+
+const runTests = () => {
+ it('should allow manual href/as on index page', async () => {
+ const browser = await webdriver(appPort, '/')
+
+ expect(await browser.elementByCss('#index').text()).toBe('index page')
+ expect(await browser.hasElementByCssSelector('#modal')).toBeFalsy()
+ await browser.eval('window.beforeNav = 1')
+
+ await browser.elementByCss('#to-modal').click()
+
+ expect(await browser.elementByCss('#index').text()).toBe('index page')
+ expect(await browser.hasElementByCssSelector('#modal')).toBeTruthy()
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({
+ imageId: '123',
+ })
+
+ await browser
+ .elementByCss('#to-preview')
+ .click()
+ .waitForElementByCss('#preview')
+
+ expect(await browser.elementByCss('#preview').text()).toBe('preview page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({
+ slug: '123',
+ })
+
+ await browser.back()
+
+ await browser
+ .elementByCss('#to-another')
+ .click()
+ .waitForElementByCss('#another')
+
+ expect(await browser.elementByCss('#another').text()).toBe('another page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({})
+
+ await browser.back()
+
+ await browser.elementByCss('#to-rewrite-me').click()
+
+ expect(await browser.elementByCss('#another').text()).toBe('another page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({})
+
+ await browser.back()
+
+ await browser
+ .elementByCss('#to-index-as-rewrite')
+ .click()
+ .waitForElementByCss('#index')
+
+ expect(await browser.elementByCss('#index').text()).toBe('index page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({})
+ })
+
+ it('should allow manual href/as on dynamic page', async () => {
+ const browser = await webdriver(appPort, '/preview/123')
+
+ expect(await browser.elementByCss('#preview').text()).toBe('preview page')
+ await browser.eval('window.beforeNav = 1')
+
+ await browser
+ .elementByCss('#to-modal')
+ .click()
+ .waitForElementByCss('#index')
+
+ expect(await browser.elementByCss('#index').text()).toBe('index page')
+ expect(await browser.hasElementByCssSelector('#modal')).toBeTruthy()
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({
+ imageId: '123',
+ })
+
+ await browser
+ .elementByCss('#to-preview')
+ .click()
+ .waitForElementByCss('#preview')
+
+ expect(await browser.elementByCss('#preview').text()).toBe('preview page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({
+ slug: '123',
+ })
+
+ await browser.elementByCss('#to-preview').click()
+
+ expect(await browser.elementByCss('#preview').text()).toBe('preview page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ await check(
+ async () =>
+ JSON.parse(
+ await browser.eval('document.querySelector("#query").innerHTML')
+ ).slug,
+ '321'
+ )
+
+ await browser
+ .elementByCss('#to-another')
+ .click()
+ .waitForElementByCss('#another')
+
+ expect(await browser.elementByCss('#another').text()).toBe('another page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({})
+
+ await browser.back().waitForElementByCss('#preview')
+ await browser.elementByCss('#to-rewrite-me').click()
+
+ expect(await browser.elementByCss('#another').text()).toBe('another page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({})
+
+ await browser.back().waitForElementByCss('#preview')
+
+ await browser
+ .elementByCss('#to-preview-as-rewrite')
+ .click()
+ .waitForElementByCss('#preview')
+
+ expect(await browser.elementByCss('#preview').text()).toBe('preview page')
+ expect(await browser.eval('window.beforeNav')).toBe(1)
+ expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({
+ slug: '321',
+ })
+ })
+}
+
+describe('rewrites manual href/as', () => {
+ describe('dev mode', () => {
+ beforeAll(async () => {
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ })
+ afterAll(() => killApp(app))
+
+ runTests()
+ })
+
+ describe('production mode', () => {
+ beforeAll(async () => {
+ await nextBuild(appDir)
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ })
+ afterAll(() => killApp(app))
+
+ runTests()
+ })
+})
diff --git a/test/integration/tsconfig-verifier/test/index.test.js b/test/integration/tsconfig-verifier/test/index.test.js
index 1011996308a4c32..d5762e6ecaf521b 100644
--- a/test/integration/tsconfig-verifier/test/index.test.js
+++ b/test/integration/tsconfig-verifier/test/index.test.js
@@ -39,7 +39,6 @@ describe('tsconfig.json verifier', () => {
\\"strict\\": false,
\\"forceConsistentCasingInFileNames\\": true,
\\"noEmit\\": true,
- \\"incremental\\": true,
\\"esModuleInterop\\": true,
\\"module\\": \\"esnext\\",
\\"moduleResolution\\": \\"node\\",
@@ -84,7 +83,6 @@ describe('tsconfig.json verifier', () => {
\\"strict\\": false,
\\"forceConsistentCasingInFileNames\\": true,
\\"noEmit\\": true,
- \\"incremental\\": true,
\\"esModuleInterop\\": true,
\\"module\\": \\"esnext\\",
\\"moduleResolution\\": \\"node\\",
@@ -152,7 +150,6 @@ describe('tsconfig.json verifier', () => {
\\"strict\\": false,
\\"forceConsistentCasingInFileNames\\": true,
\\"noEmit\\": true,
- \\"incremental\\": true,
\\"moduleResolution\\": \\"node\\",
\\"resolveJsonModule\\": true,
\\"isolatedModules\\": true,
@@ -201,7 +198,6 @@ describe('tsconfig.json verifier', () => {
\\"strict\\": false,
\\"forceConsistentCasingInFileNames\\": true,
\\"noEmit\\": true,
- \\"incremental\\": true,
\\"moduleResolution\\": \\"node\\",
\\"resolveJsonModule\\": true,
\\"isolatedModules\\": true,
@@ -247,7 +243,6 @@ describe('tsconfig.json verifier', () => {
\\"strict\\": false,
\\"forceConsistentCasingInFileNames\\": true,
\\"noEmit\\": true,
- \\"incremental\\": true,
\\"moduleResolution\\": \\"node\\",
\\"resolveJsonModule\\": true,
\\"isolatedModules\\": true,
@@ -286,7 +281,6 @@ describe('tsconfig.json verifier', () => {
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
- "incremental": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
diff --git a/test/lib/next-test-utils.js b/test/lib/next-test-utils.js
index a64ea6581317dc2..193cc3b176717cd 100644
--- a/test/lib/next-test-utils.js
+++ b/test/lib/next-test-utils.js
@@ -166,7 +166,9 @@ export function runNextCommand(argv, options = {}) {
}
export function runNextCommandDev(argv, stdOut, opts = {}) {
- const cwd = path.dirname(require.resolve('next/package'))
+ const nextDir = path.dirname(require.resolve('next/package'))
+ const nextBin = path.join(nextDir, 'dist/bin/next')
+ const cwd = opts.cwd || nextDir
const env = {
...process.env,
NODE_ENV: undefined,
@@ -175,11 +177,10 @@ export function runNextCommandDev(argv, stdOut, opts = {}) {
}
return new Promise((resolve, reject) => {
- const instance = spawn(
- 'node',
- ['--no-deprecation', 'dist/bin/next', ...argv],
- { cwd, env }
- )
+ const instance = spawn('node', ['--no-deprecation', nextBin, ...argv], {
+ cwd,
+ env,
+ })
let didResolve = false
function handleStdout(data) {
diff --git a/test/unit/next-babel.unit.test.js b/test/unit/next-babel.unit.test.js
index ad6d2d4c5cd7700..672060335045726 100644
--- a/test/unit/next-babel.unit.test.js
+++ b/test/unit/next-babel.unit.test.js
@@ -165,28 +165,6 @@ describe('next/babel', () => {
})
})
- describe('experimental-modern-preset', () => {
- it('should allow passing a custom Babel preset', () => {
- const code = trim`
- const [, b, c] = [...[1,2,3]];
- ({a}) => a;
- `
- const output = babel(code, true, {
- 'preset-env': {
- targets: {
- esmodules: true,
- },
- },
- // our modern preset is no preset at all
- 'experimental-modern-preset': () => ({}),
- })
-
- expect(output).toMatch(trim`
- const[,b,c]=[...[1,2,3]];({a})=>a;
- `)
- })
- })
-
describe('respect preset-react runtime', () => {
it('should allow forcing on automatic mode', () => {
const code = trim`const a = ()=>home `
diff --git a/yarn.lock b/yarn.lock
index 1420e7313f1511f..9fdfd3e8c282774 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4492,6 +4492,13 @@ bl@^4.0.1:
inherits "^2.0.4"
readable-stream "^3.4.0"
+block-stream@*:
+ version "0.0.9"
+ resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+ integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=
+ dependencies:
+ inherits "~2.0.0"
+
bluebird@^3.5.0, bluebird@^3.5.5:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@@ -6236,6 +6243,13 @@ debug@^3.0.0, debug@^3.1.0:
dependencies:
ms "^2.1.1"
+debug@^3.2.6:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+ integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+ dependencies:
+ ms "^2.1.1"
+
debug@~0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-0.8.1.tgz#20ff4d26f5e422cb68a1bacbbb61039ad8c1c130"
@@ -6377,6 +6391,11 @@ detect-indent@^6.0.0:
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd"
integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==
+detect-libc@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+ integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
+
detect-newline@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
@@ -7821,6 +7840,16 @@ fsevents@~2.3.1:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f"
integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
+fstream@^1.0.0, fstream@^1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
+ integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
+ dependencies:
+ graceful-fs "^4.1.2"
+ inherits "~2.0.0"
+ mkdirp ">=0.5 0"
+ rimraf "2"
+
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -8583,7 +8612,7 @@ humanize-ms@^1.2.1:
dependencies:
ms "^2.0.0"
-iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
+iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
dependencies:
@@ -8635,6 +8664,13 @@ ignore-loader@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463"
+ignore-walk@^3.0.1:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335"
+ integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==
+ dependencies:
+ minimatch "^3.0.4"
+
ignore-walk@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
@@ -8743,7 +8779,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
@@ -11209,7 +11245,7 @@ mkdirp-infer-owner@^2.0.0:
infer-owner "^1.0.4"
mkdirp "^1.0.3"
-mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
+"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
dependencies:
@@ -11328,6 +11364,15 @@ natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+needle@^2.2.1:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/needle/-/needle-2.6.0.tgz#24dbb55f2509e2324b4a99d61f413982013ccdbe"
+ integrity sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==
+ dependencies:
+ debug "^3.2.6"
+ iconv-lite "^0.4.4"
+ sax "^1.2.4"
+
negotiator@0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
@@ -11359,6 +11404,11 @@ no-case@^2.2.0, no-case@^2.3.2:
dependencies:
lower-case "^1.1.1"
+node-addon-api@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239"
+ integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==
+
node-dir@^0.1.17:
version "0.1.17"
resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5"
@@ -11388,6 +11438,24 @@ node-fetch@^1.0.1:
encoding "^0.1.11"
is-stream "^1.0.1"
+node-gyp@3.x:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
+ integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==
+ dependencies:
+ fstream "^1.0.0"
+ glob "^7.0.3"
+ graceful-fs "^4.1.2"
+ mkdirp "^0.5.0"
+ nopt "2 || 3"
+ npmlog "0 || 1 || 2 || 3 || 4"
+ osenv "0"
+ request "^2.87.0"
+ rimraf "2"
+ semver "~5.3.0"
+ tar "^2.0.0"
+ which "1"
+
node-gyp@^5.0.2:
version "5.1.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e"
@@ -11475,6 +11543,22 @@ node-notifier@5.4.0:
shellwords "^0.1.1"
which "^1.3.0"
+node-pre-gyp@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054"
+ integrity sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==
+ dependencies:
+ detect-libc "^1.0.2"
+ mkdirp "^0.5.1"
+ needle "^2.2.1"
+ nopt "^4.0.1"
+ npm-packlist "^1.1.6"
+ npmlog "^4.0.2"
+ rc "^1.2.7"
+ rimraf "^2.6.1"
+ semver "^5.3.0"
+ tar "^4"
+
node-releases@^1.1.69:
version "1.1.70"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08"
@@ -11510,6 +11594,13 @@ node-version@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.2.0.tgz#34fde3ffa8e1149bd323983479dda620e1b5060d"
+"nopt@2 || 3":
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+ integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
+ dependencies:
+ abbrev "1"
+
nopt@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
@@ -11574,6 +11665,13 @@ normalize.css@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3"
+npm-bundled@^1.0.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1"
+ integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==
+ dependencies:
+ npm-normalize-package-bin "^1.0.1"
+
npm-bundled@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b"
@@ -11615,6 +11713,15 @@ npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0:
semver "^7.0.0"
validate-npm-package-name "^3.0.0"
+npm-packlist@^1.1.6:
+ version "1.4.8"
+ resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
+ integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==
+ dependencies:
+ ignore-walk "^3.0.1"
+ npm-bundled "^1.0.1"
+ npm-normalize-package-bin "^1.0.1"
+
npm-packlist@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-2.1.4.tgz#40e96b2b43787d0546a574542d01e066640d09da"
@@ -11682,7 +11789,7 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1:
dependencies:
path-key "^3.0.0"
-npmlog@^4.0.0, npmlog@^4.1.2:
+"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
dependencies:
@@ -11961,7 +12068,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
-osenv@^0.1.4:
+osenv@0, osenv@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
@@ -13638,7 +13745,7 @@ raw-body@2.4.1:
iconv-lite "0.4.24"
unpipe "1.0.0"
-rc@^1.0.1, rc@^1.1.6:
+rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
@@ -14118,7 +14225,7 @@ request-promise-native@^1.0.9:
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
-request@2.88.2, request@^2.86.0, request@^2.88.0, request@^2.88.2:
+request@2.88.2, request@^2.86.0, request@^2.87.0, request@^2.88.0, request@^2.88.2:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
@@ -14306,6 +14413,12 @@ rgba-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
+rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@^2.7.1:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ dependencies:
+ glob "^7.1.3"
+
rimraf@2.6.3, rimraf@~2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
@@ -14318,12 +14431,6 @@ rimraf@3.0.0:
dependencies:
glob "^7.1.3"
-rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1:
- version "2.7.1"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
- dependencies:
- glob "^7.1.3"
-
rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -14505,7 +14612,7 @@ sass-loader@6.0.6:
lodash.tail "^4.1.1"
pify "^3.0.0"
-sax@~1.2.4:
+sax@^1.2.4, sax@~1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
@@ -14628,6 +14735,11 @@ semver@^7.2.1:
dependencies:
lru-cache "^6.0.0"
+semver@~5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+ integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
+
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
@@ -15045,6 +15157,21 @@ sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+sqlite3@5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.0.2.tgz#00924adcc001c17686e0a6643b6cbbc2d3965083"
+ integrity sha512-1SdTNo+BVU211Xj1csWa8lV6KM0CtucDwRyA0VHl91wEH1Mgh7RxUpI4rVvG7OhHrzCSGaVyW5g8vKvlrk9DJA==
+ dependencies:
+ node-addon-api "^3.0.0"
+ node-pre-gyp "^0.11.0"
+ optionalDependencies:
+ node-gyp "3.x"
+
+sqlite@4.0.22:
+ version "4.0.22"
+ resolved "https://registry.yarnpkg.com/sqlite/-/sqlite-4.0.22.tgz#4a987dbcf8ccffa9a2ccc80d8a8491c62f5d19e0"
+ integrity sha512-i2qvk6PyZJ35cpdocdO1DF+wMU5a6eRkcn+Dmt+HpGvYJ+pKodK6tZM0DnouCf4tXt1Whs2T2smtrEyFWAauWg==
+
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
@@ -15621,7 +15748,16 @@ tar@4.4.10:
safe-buffer "^5.1.2"
yallist "^3.0.3"
-tar@^4.4.12:
+tar@^2.0.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
+ integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==
+ dependencies:
+ block-stream "*"
+ fstream "^1.0.12"
+ inherits "2"
+
+tar@^4, tar@^4.4.12:
version "4.4.13"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
@@ -16784,15 +16920,15 @@ which-typed-array@^1.1.2:
has-symbols "^1.0.1"
is-typed-array "^1.1.3"
-which@1.2.x:
- version "1.2.14"
- resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
+which@1, which@^1.2.12, which@^1.2.8, which@^1.2.9, which@^1.3.0, which@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
dependencies:
isexe "^2.0.0"
-which@^1.2.12, which@^1.2.8, which@^1.2.9, which@^1.3.0, which@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+which@1.2.x:
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
dependencies:
isexe "^2.0.0"