diff --git a/docs/upgrading.md b/docs/upgrading.md index cc13023fc81c2..47757325c1564 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -4,6 +4,38 @@ description: Learn how to upgrade Next.js. # Upgrade Guide +## Upgrading from version 10 to 11 + +### Remove `super.componentDidCatch()` from `pages/_app.js` + +The `next/app` component's `componentDidCatch` has been deprecated since Next.js 9 as it's no longer needed and has since been a no-op, in Next.js 11 it has been removed. + +If your `pages/_app.js` has a custom `componentDidCatch` method you can remove `super.componentDidCatch` as it is no longer needed. + +### Remove `Container` from `pages/_app.js` + +This export has been deprecated since Next.js 9 as it's no longer needed and has since been a no-op with a warning during development. In Next.js 11 it has been removed. + +If your `pages/_app.js` imports `Container` from `next/app` you can remove `Container` as it has been removed. Learn more in [the documentation](https://nextjs.org/docs/messages/app-container-deprecated). + +### Remove `props.url` usage from page components + +This property has been deprecated since Next.js 4 and has since shown a warning during development. With the introduction of `getStaticProps` / `getServerSideProps` these methods already disallowed usage of `props.url`. In Next.js 11 it has been removed completely. + +You can learn more in [the documentation](https://nextjs.org/docs/messages/url-deprecated). + +### Remove `unsized` property on `next/image` + +The `unsized` property on `next/image` was deprecated in Next.js 10.0.1. You can use `layout="fill"` instead. In Next.js 11 `unsized` was removed. + +### Remove `modules` property on `next/dynamic` + +The `modules` and `render` option for `next/dynamic` have been deprecated since Next.js 9.5 showing a warning that it has been deprecated. This was done in order to make `next/dynamic` close to `React.lazy` in API surface. In Next.js 11 the `modules` and `render` options have been removed. + +This option hasn't been mentioned in the documentation since Next.js 8 so it's less likely that your application is using it. + +If you application does use `modules` and `render` you can refer to [the documentation](https://nextjs.org/docs/messages/next-dynamic-modules). + ## React 16 to 17 React 17 introduced a new [JSX Transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) that brings a long-time Next.js feature to the wider React ecosystem: Not having to `import React from 'react'` when using JSX. When using React 17 Next.js will automatically use the new transform. This transform does not make the `React` variable global, which was an unintended side-effect of the previous Next.js implementation. A [codemod is available](/docs/advanced-features/codemods.md#add-missing-react-import) to automatically fix cases where you accidentally used `React` without importing it. diff --git a/examples/with-mdx-remote/README.md b/examples/with-mdx-remote/README.md index 45d57da1ea461..8c08583dfb38e 100644 --- a/examples/with-mdx-remote/README.md +++ b/examples/with-mdx-remote/README.md @@ -34,10 +34,12 @@ For example, here's how you can change `getStaticProps` to pass a list of compon ```js import dynamic from 'next/dynamic' +import Test from '../components/test' const SomeHeavyComponent = dynamic(() => import('SomeHeavyComponent')) -// ... +const defaultComponents = { Test } + export function SomePage({ mdxSource, componentNames }) { const components = { ...defaultComponents, @@ -46,10 +48,17 @@ export function SomePage({ mdxSource, componentNames }) { : null, } - return + return } export async function getStaticProps() { + const source = `--- + title: Conditional custom components + --- + + Some **mdx** text, with a default component and a Heavy component + ` + const { content, data } = matter(source) const componentNames = [ diff --git a/lerna.json b/lerna.json index 2b9cd8b70f1f3..5c2bd8726c546 100644 --- a/lerna.json +++ b/lerna.json @@ -17,5 +17,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "10.2.4-canary.0" + "version": "10.2.4-canary.2" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 7566b0570cde9..797d9906447a8 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.4-canary.0", + "version": "10.2.4-canary.2", "keywords": [ "react", "next", diff --git a/packages/create-next-app/templates/default/next.config.js b/packages/create-next-app/templates/default/next.config.js new file mode 100644 index 0000000000000..0d6071006ab35 --- /dev/null +++ b/packages/create-next-app/templates/default/next.config.js @@ -0,0 +1,3 @@ +module.exports = { + reactStrictMode: true, +} diff --git a/packages/create-next-app/templates/typescript/next.config.js b/packages/create-next-app/templates/typescript/next.config.js index 651299536b7a2..0d6071006ab35 100644 --- a/packages/create-next-app/templates/typescript/next.config.js +++ b/packages/create-next-app/templates/typescript/next.config.js @@ -1,3 +1,3 @@ module.exports = { - eslint: true, + reactStrictMode: true, } diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index a3bd1e790f3b1..d9bf430076f8d 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.4-canary.0", + "version": "10.2.4-canary.2", "description": "ESLint configuration used by NextJS.", "main": "index.js", "license": "MIT", @@ -9,7 +9,7 @@ "directory": "packages/eslint-config-next" }, "dependencies": { - "@next/eslint-plugin-next": "10.2.4-canary.0", + "@next/eslint-plugin-next": "10.2.4-canary.2", "@rushstack/eslint-patch": "^1.0.6", "@typescript-eslint/parser": "^4.20.0", "eslint-import-resolver-node": "^0.3.4", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 13be56e9199a1..261ec7dc4be47 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.4-canary.0", + "version": "10.2.4-canary.2", "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 4090a281b7aa6..5e5eac5a6f243 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.4-canary.0", + "version": "10.2.4-canary.2", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index df7a591542a83..98e27d804486b 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "10.2.4-canary.0", + "version": "10.2.4-canary.2", "license": "MIT", "dependencies": { "chalk": "4.1.0", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 708f85bb523f2..1581967682d22 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "10.2.4-canary.0", + "version": "10.2.4-canary.2", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index e22b029e53b68..8d0bde78c76b7 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "10.2.4-canary.0", + "version": "10.2.4-canary.2", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index a41c2ac4deb8b..82d74e394c203 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.4-canary.0", + "version": "10.2.4-canary.2", "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 389511147dad9..21703440d9031 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.4-canary.0", + "version": "10.2.4-canary.2", "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 a4641cfd09080..8cca9dc16f1c6 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.4-canary.0", + "version": "10.2.4-canary.2", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index 554cdf5fed900..e5c44640df2e9 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -543,33 +543,25 @@ export default async function build( const webpackBuildStart = process.hrtime() let result: CompilerResult = { warnings: [], errors: [] } - // We run client and server compilation separately when configured for - // memory constraint and for serverless to be able to load manifests - // produced in the client build - if (isLikeServerless || config.experimental.serialWebpackBuild) { - await nextBuildSpan - .traceChild('run-webpack-compiler') - .traceAsyncFn(async () => { - const clientResult = await runCompiler(clientConfig) - // Fail build if clientResult contains errors - if (clientResult.errors.length > 0) { - result = { - warnings: [...clientResult.warnings], - errors: [...clientResult.errors], - } - } else { - const serverResult = await runCompiler(configs[1]) - result = { - warnings: [...clientResult.warnings, ...serverResult.warnings], - errors: [...clientResult.errors, ...serverResult.errors], - } + // We run client and server compilation separately to optimize for memory usage + await nextBuildSpan + .traceChild('run-webpack-compiler') + .traceAsyncFn(async () => { + const clientResult = await runCompiler(clientConfig) + // Fail build if clientResult contains errors + if (clientResult.errors.length > 0) { + result = { + warnings: [...clientResult.warnings], + errors: [...clientResult.errors], } - }) - } else { - result = await nextBuildSpan - .traceChild('run-webpack-compiler') - .traceAsyncFn(() => runCompiler(configs)) - } + } else { + const serverResult = await runCompiler(configs[1]) + result = { + warnings: [...clientResult.warnings, ...serverResult.warnings], + errors: [...clientResult.errors, ...serverResult.errors], + } + } + }) const webpackBuildEnd = process.hrtime(webpackBuildStart) if (buildSpinner) { diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 139a06abf8687..6263f321793c3 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -260,7 +260,9 @@ export default async function getBaseWebpackConfig( const distDir = path.join(dir, config.distDir) - const babelLoader = config.experimental.turboMode + // Webpack 5 can use the faster babel loader, webpack 5 has built-in caching for loaders + // For webpack 4 the old loader is used as it has external caching + const babelLoader = isWebpack5 ? require.resolve('./babel/loader/index') : 'next-babel-loader' const defaultLoaders = { diff --git a/packages/next/build/webpack/plugins/font-stylesheet-gathering-plugin.ts b/packages/next/build/webpack/plugins/font-stylesheet-gathering-plugin.ts index 043c09ca91b29..a3fff7d54fa99 100644 --- a/packages/next/build/webpack/plugins/font-stylesheet-gathering-plugin.ts +++ b/packages/next/build/webpack/plugins/font-stylesheet-gathering-plugin.ts @@ -106,7 +106,7 @@ export class FontStylesheetGatheringPlugin { !props.rel || props.rel !== 'stylesheet' || !props.href || - !OPTIMIZED_FONT_PROVIDERS.some((url) => + !OPTIMIZED_FONT_PROVIDERS.some(({ url }) => props.href.startsWith(url) ) ) { diff --git a/packages/next/client/image.tsx b/packages/next/client/image.tsx index eea353be48980..e41f5c4b94475 100644 --- a/packages/next/client/image.tsx +++ b/packages/next/client/image.tsx @@ -62,12 +62,6 @@ export type ImageProps = Omit< objectFit?: ImgElementStyle['objectFit'] objectPosition?: ImgElementStyle['objectPosition'] } & ( - | { - width?: never - height?: never - /** @deprecated Use `layout="fill"` instead */ - unsized: true - } | { width?: never; height?: never; layout: 'fill' } | { width: number | string @@ -260,12 +254,7 @@ export default function Image({ }: ImageProps) { let rest: Partial = all let layout: NonNullable = sizes ? 'responsive' : 'intrinsic' - let unsized = false - if ('unsized' in rest) { - unsized = Boolean(rest.unsized) - // Remove property so it's not spread into image: - delete rest['unsized'] - } else if ('layout' in rest) { + if ('layout' in rest) { // Override default layout if the user specified one: if (rest.layout) layout = rest.layout @@ -304,11 +293,6 @@ export default function Image({ `Image with src "${src}" has both "priority" and "loading='lazy'" properties. Only one should be used.` ) } - if (unsized) { - throw new Error( - `Image with src "${src}" has deprecated "unsized" property, which was removed in favor of the "layout='fill'" property` - ) - } } let isLazy = @@ -461,11 +445,6 @@ export default function Image({ }) } - if (unsized) { - wrapperStyle = undefined - sizerStyle = undefined - imgStyle = undefined - } return (
{sizerStyle ? ( diff --git a/packages/next/next-server/lib/constants.ts b/packages/next/next-server/lib/constants.ts index eed0b3877ba92..8d2dc6ba86db4 100644 --- a/packages/next/next-server/lib/constants.ts +++ b/packages/next/next-server/lib/constants.ts @@ -37,8 +37,9 @@ export const TEMPORARY_REDIRECT_STATUS = 307 export const PERMANENT_REDIRECT_STATUS = 308 export const STATIC_PROPS_ID = '__N_SSG' export const SERVER_PROPS_ID = '__N_SSP' +export const GOOGLE_FONT_PROVIDER = 'https://fonts.googleapis.com/css' export const OPTIMIZED_FONT_PROVIDERS = [ - 'https://fonts.googleapis.com/css', - 'https://use.typekit.net/', + { url: GOOGLE_FONT_PROVIDER, preconnect: 'https://fonts.gstatic.com' }, + { url: 'https://use.typekit.net', preconnect: 'https://use.typekit.net' }, ] export const STATIC_STATUS_PAGES = ['/500'] diff --git a/packages/next/next-server/lib/dynamic.tsx b/packages/next/next-server/lib/dynamic.tsx index 53931abde0782..0b260d19e9641 100644 --- a/packages/next/next-server/lib/dynamic.tsx +++ b/packages/next/next-server/lib/dynamic.tsx @@ -33,16 +33,9 @@ export type LoadableBaseOptions

= LoadableGeneratedOptions & { ssr?: boolean } -export type LoadableOptions

= LoadableBaseOptions

& { - render?(loader: any, props: any): JSX.Element -} +export type LoadableOptions

= LoadableBaseOptions

-export type DynamicOptions

= LoadableBaseOptions

& { - /** - * @deprecated the modules option has been planned for removal - */ - render?(props: P, loaded: any): JSX.Element -} +export type DynamicOptions

= LoadableBaseOptions

export type LoadableFn

= ( opts: LoadableOptions

@@ -117,40 +110,6 @@ export default function dynamic

( // Support for passing options, eg: dynamic(import('../hello-world'), {loading: () =>

Loading something

}) loadableOptions = { ...loadableOptions, ...options } - if ( - typeof dynamicOptions === 'object' && - !(dynamicOptions instanceof Promise) - ) { - // show deprecation warning for `modules` key in development - if (process.env.NODE_ENV !== 'production') { - if (dynamicOptions.modules) { - console.warn( - 'The modules option for next/dynamic has been deprecated. See here for more info https://nextjs.org/docs/messages/next-dynamic-modules' - ) - } - } - // Support for `render` when using a mapping, eg: `dynamic({ modules: () => {return {HelloWorld: import('../hello-world')}, render(props, loaded) {} } }) - if (dynamicOptions.render) { - loadableOptions.render = (loaded, props) => - dynamicOptions.render!(props, loaded) - } - // Support for `modules` when using a mapping, eg: `dynamic({ modules: () => {return {HelloWorld: import('../hello-world')}, render(props, loaded) {} } }) - if (dynamicOptions.modules) { - loadableFn = Loadable.Map - const loadModules: LoaderMap = {} - const modules = dynamicOptions.modules() - Object.keys(modules).forEach((key) => { - const value: any = modules[key] - if (typeof value.then === 'function') { - loadModules[key] = () => value.then((mod: any) => mod.default || mod) - return - } - loadModules[key] = value - }) - loadableOptions.loader = loadModules - } - } - // coming from build/babel/plugins/react-loadable-plugin.js if (loadableOptions.loadableGenerated) { loadableOptions = { diff --git a/packages/next/next-server/lib/loadable.js b/packages/next/next-server/lib/loadable.js index a81d792610ed3..3b2381b319dfb 100644 --- a/packages/next/next-server/lib/loadable.js +++ b/packages/next/next-server/lib/loadable.js @@ -53,61 +53,10 @@ function load(loader) { return state } -function loadMap(obj) { - let state = { - loading: false, - loaded: {}, - error: null, - } - - let promises = [] - - try { - Object.keys(obj).forEach((key) => { - let result = load(obj[key]) - - if (!result.loading) { - state.loaded[key] = result.loaded - state.error = result.error - } else { - state.loading = true - } - - promises.push(result.promise) - - result.promise - .then((res) => { - state.loaded[key] = res - }) - .catch((err) => { - state.error = err - }) - }) - } catch (err) { - state.error = err - } - - state.promise = Promise.all(promises) - .then((res) => { - state.loading = false - return res - }) - .catch((err) => { - state.loading = false - throw err - }) - - return state -} - function resolve(obj) { return obj && obj.__esModule ? obj.default : obj } -function render(loaded, props) { - return React.createElement(resolve(loaded), props) -} - function createLoadableComponent(loadFn, options) { let opts = Object.assign( { @@ -115,7 +64,6 @@ function createLoadableComponent(loadFn, options) { loading: null, delay: 200, timeout: null, - render: render, webpack: null, modules: null, }, @@ -188,7 +136,7 @@ function createLoadableComponent(loadFn, options) { retry: subscription.retry, }) } else if (state.loaded) { - return opts.render(state.loaded, props) + return React.createElement(resolve(state.loaded), props) } else { return null } @@ -291,16 +239,6 @@ function Loadable(opts) { return createLoadableComponent(load, opts) } -function LoadableMap(opts) { - if (typeof opts.render !== 'function') { - throw new Error('LoadableMap requires a `render(loaded, props)` function') - } - - return createLoadableComponent(loadMap, opts) -} - -Loadable.Map = LoadableMap - function flushInitializers(initializers, ids) { let promises = [] diff --git a/packages/next/next-server/lib/post-process.ts b/packages/next/next-server/lib/post-process.ts index 2a448f64bab56..04c9ad8225720 100644 --- a/packages/next/next-server/lib/post-process.ts +++ b/packages/next/next-server/lib/post-process.ts @@ -82,7 +82,7 @@ class FontOptimizerMiddleware implements PostProcessMiddleware { (tag: HTMLElement) => tag.getAttribute('rel') === 'stylesheet' && tag.hasAttribute('data-href') && - OPTIMIZED_FONT_PROVIDERS.some((url) => { + OPTIMIZED_FONT_PROVIDERS.some(({ url }) => { const dataHref = tag.getAttribute('data-href') return dataHref ? dataHref.startsWith(url) : false }) @@ -104,6 +104,8 @@ class FontOptimizerMiddleware implements PostProcessMiddleware { options: renderOptions ) => { let result = markup + let preconnectUrls = new Set() + if (!options.getFontDefinition) { return markup } @@ -132,9 +134,27 @@ class FontOptimizerMiddleware implements PostProcessMiddleware { '', `` ) + + const provider = OPTIMIZED_FONT_PROVIDERS.find((p) => + url.startsWith(p.url) + ) + + if (provider) { + preconnectUrls.add(provider.preconnect) + } } }) + let preconnectTag = '' + preconnectUrls.forEach((url) => { + preconnectTag += `` + }) + + result = result.replace( + '', + preconnectTag + ) + return result } } diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index 739d06597b945..54397b7475b81 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -650,11 +650,14 @@ export default class Router implements BaseRouter { if (as.substr(0, 2) !== '//') { // in order for `e.state` to work on the `onpopstate` event // we have to register the initial route upon initialization + const options: TransitionOptions = { locale } + ;(options as any)._shouldResolveHref = as !== pathname + this.changeState( 'replaceState', formatWithValidation({ pathname: addBasePath(pathname), query }), getURL(), - { locale } + options ) } @@ -804,7 +807,8 @@ export default class Router implements BaseRouter { window.location.href = url return false } - const shouldResolveHref = url === as || (options as any)._h + const shouldResolveHref = + url === as || (options as any)._h || (options as any)._shouldResolveHref // for static pages with query params in the URL we delay // marking the router ready until after the query is updated @@ -982,6 +986,8 @@ export default class Router implements BaseRouter { : pathname if (shouldResolveHref && pathname !== '/_error') { + ;(options as any)._shouldResolveHref = true + if (process.env.__NEXT_HAS_REWRITES && as.startsWith('/')) { const rewritesResult = resolveRewrites( addBasePath(addLocale(cleanedAs, this.locale)), diff --git a/packages/next/next-server/server/config-shared.ts b/packages/next/next-server/server/config-shared.ts index 5f2b3ca00ed69..c0d3e3d40b15c 100644 --- a/packages/next/next-server/server/config-shared.ts +++ b/packages/next/next-server/server/config-shared.ts @@ -49,14 +49,12 @@ export type NextConfig = { [key: string]: any } & { scriptLoader?: boolean stats?: boolean externalDir?: boolean - serialWebpackBuild?: boolean conformance?: boolean amp?: { optimizer?: any validator?: string skipValidation?: boolean } - turboMode?: boolean reactRoot?: boolean enableBlurryPlaceholder?: boolean disableOptimizedLoading?: boolean @@ -113,8 +111,6 @@ export const defaultConfig: NextConfig = { scriptLoader: false, stats: false, externalDir: false, - serialWebpackBuild: false, - turboMode: false, reactRoot: Number(process.env.NEXT_PRIVATE_REACT_ROOT) > 0, enableBlurryPlaceholder: false, disableOptimizedLoading: true, diff --git a/packages/next/next-server/server/config-utils.ts b/packages/next/next-server/server/config-utils.ts index 77f34ff05fb57..96a2040326fc3 100644 --- a/packages/next/next-server/server/config-utils.ts +++ b/packages/next/next-server/server/config-utils.ts @@ -3,6 +3,7 @@ import { Worker } from 'jest-worker' import * as Log from '../../build/output/log' import { CheckReasons, CheckResult } from './config-utils-worker' import { install, shouldLoadWithWebpack5 } from './config-utils-worker' +import { PHASE_PRODUCTION_SERVER } from '../lib/constants' export { install, shouldLoadWithWebpack5 } @@ -36,11 +37,15 @@ export async function loadWebpackHook(phase: string, dir: string) { ) try { const result: CheckResult = await worker.shouldLoadWithWebpack5(phase, dir) - Log.info( - `Using webpack ${result.enabled ? '5' : '4'}. Reason: ${reasonMessage( - result.reason - )} https://nextjs.org/docs/messages/webpack5` - ) + // Don't log which webpack version is being used when booting production server as it's not used after build + if (phase !== PHASE_PRODUCTION_SERVER) { + Log.info( + `Using webpack ${result.enabled ? '5' : '4'}. Reason: ${reasonMessage( + result.reason + )} https://nextjs.org/docs/messages/webpack5` + ) + } + useWebpack5 = Boolean(result.enabled) } catch { // If this errors, it likely will do so again upon boot, so we just swallow diff --git a/packages/next/next-server/server/font-utils.ts b/packages/next/next-server/server/font-utils.ts index 4d4b25dbe9425..6e2b9cfee6a3a 100644 --- a/packages/next/next-server/server/font-utils.ts +++ b/packages/next/next-server/server/font-utils.ts @@ -1,4 +1,5 @@ import * as Log from '../../build/output/log' +import { GOOGLE_FONT_PROVIDER } from '../lib/constants' const https = require('https') const CHROME_UA = @@ -10,6 +11,10 @@ export type FontManifest = Array<{ content: string }> +function isGoogleFont(url: string): boolean { + return url.startsWith(GOOGLE_FONT_PROVIDER) +} + function getFontForUA(url: string, UA: string): Promise { return new Promise((resolve, reject) => { let rawData: any = '' @@ -45,7 +50,9 @@ export async function getFontDefinitionFromNetwork( * CSS cascading 🤷‍♂️. */ try { - result += await getFontForUA(url, IE_UA) + if (isGoogleFont(url)) { + result += await getFontForUA(url, IE_UA) + } result += await getFontForUA(url, CHROME_UA) } catch (e) { Log.warn( diff --git a/packages/next/package.json b/packages/next/package.json index 9d56f79c409a1..cc702f5482ced 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "10.2.4-canary.0", + "version": "10.2.4-canary.2", "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.2", - "@next/env": "10.2.4-canary.0", - "@next/polyfill-module": "10.2.4-canary.0", - "@next/react-dev-overlay": "10.2.4-canary.0", - "@next/react-refresh-utils": "10.2.4-canary.0", + "@next/env": "10.2.4-canary.2", + "@next/polyfill-module": "10.2.4-canary.2", + "@next/react-dev-overlay": "10.2.4-canary.2", + "@next/react-refresh-utils": "10.2.4-canary.2", "@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.4-canary.0", + "@next/polyfill-nomodule": "10.2.4-canary.2", "@taskr/clear": "1.1.0", "@taskr/esnext": "1.1.0", "@taskr/watch": "1.1.0", diff --git a/packages/next/pages/_app.tsx b/packages/next/pages/_app.tsx index 0a2e8e80d8ab4..4036cfd89674e 100644 --- a/packages/next/pages/_app.tsx +++ b/packages/next/pages/_app.tsx @@ -1,6 +1,5 @@ -import React, { ErrorInfo } from 'react' +import React from 'react' import { - execOnce, loadGetInitialProps, AppContextType, AppInitialProps, @@ -36,94 +35,9 @@ export default class App

extends React.Component< static origGetInitialProps = appGetInitialProps static getInitialProps = appGetInitialProps - // Kept here for backwards compatibility. - // When someone ended App they could call `super.componentDidCatch`. - // @deprecated This method is no longer needed. Errors are caught at the top level - componentDidCatch(error: Error, _errorInfo: ErrorInfo): void { - throw error - } - render() { - const { router, Component, pageProps, __N_SSG, __N_SSP } = this - .props as AppProps - - return ( - - ) - } -} - -let warnContainer: () => void -let warnUrl: () => void - -if (process.env.NODE_ENV !== 'production') { - warnContainer = execOnce(() => { - console.warn( - `Warning: the \`Container\` in \`_app\` has been deprecated and should be removed. https://nextjs.org/docs/messages/app-container-deprecated` - ) - }) - - warnUrl = execOnce(() => { - console.error( - `Warning: the 'url' property is deprecated. https://nextjs.org/docs/messages/url-deprecated` - ) - }) -} - -// @deprecated noop for now until removal -export function Container(p: any) { - if (process.env.NODE_ENV !== 'production') warnContainer() - return p.children -} - -export function createUrl(router: Router) { - // This is to make sure we don't references the router object at call time - const { pathname, asPath, query } = router - return { - get query() { - if (process.env.NODE_ENV !== 'production') warnUrl() - return query - }, - get pathname() { - if (process.env.NODE_ENV !== 'production') warnUrl() - return pathname - }, - get asPath() { - if (process.env.NODE_ENV !== 'production') warnUrl() - return asPath - }, - back: () => { - if (process.env.NODE_ENV !== 'production') warnUrl() - router.back() - }, - push: (url: string, as?: string) => { - if (process.env.NODE_ENV !== 'production') warnUrl() - return router.push(url, as) - }, - pushTo: (href: string, as?: string) => { - if (process.env.NODE_ENV !== 'production') warnUrl() - const pushRoute = as ? href : '' - const pushUrl = as || href - - return router.push(pushRoute, pushUrl) - }, - replace: (url: string, as?: string) => { - if (process.env.NODE_ENV !== 'production') warnUrl() - return router.replace(url, as) - }, - replaceTo: (href: string, as?: string) => { - if (process.env.NODE_ENV !== 'production') warnUrl() - const replaceRoute = as ? href : '' - const replaceUrl = as || href + const { Component, pageProps } = this.props as AppProps - return router.replace(replaceRoute, replaceUrl) - }, + return } } diff --git a/packages/next/pages/_document.tsx b/packages/next/pages/_document.tsx index d3a486a0e4de9..9faa6ebfd7414 100644 --- a/packages/next/pages/_document.tsx +++ b/packages/next/pages/_document.tsx @@ -447,7 +447,9 @@ export class Head extends Component< if ( c.type === 'link' && c.props['href'] && - OPTIMIZED_FONT_PROVIDERS.some((url) => c.props['href'].startsWith(url)) + OPTIMIZED_FONT_PROVIDERS.some(({ url }) => + c.props['href'].startsWith(url) + ) ) { const newProps = { ...(c.props || {}) } newProps['data-href'] = newProps['href'] @@ -639,6 +641,9 @@ export class Head extends Component< )} {children} + {process.env.__NEXT_OPTIMIZE_FONTS && ( + + )} {head} { - const components = { - HelloContext: import('../../components/hello-context'), - Hello1: import('../../components/hello1'), - Hello2: import('../../components/hello2'), - } - - return components - }, - render: (props, { HelloContext, Hello1, Hello2 }) => ( -

-

{props.title}

- - - {props.showMore ? : null} -
- ), -}) - -export default class Bundle extends React.Component { - static childContextTypes = { - data: PropTypes.object, - } - - static getInitialProps({ query }) { - return { showMore: Boolean(query.showMore) } - } - - getChildContext() { - return { - data: { title: 'Vercel Rocks' }, - } - } - - toggleShowMore() { - if (this.props.showMore) { - Router.push('/dynamic/bundle') - return - } - - Router.push('/dynamic/bundle?showMore=1') - } - - render() { - const { showMore } = this.props - - return ( -
- - -
- ) - } -} diff --git a/test/integration/basic/test/dynamic.js b/test/integration/basic/test/dynamic.js index fcce8c706dfcc..c7600d7ea1505 100644 --- a/test/integration/basic/test/dynamic.js +++ b/test/integration/basic/test/dynamic.js @@ -1,7 +1,7 @@ /* eslint-env jest */ import webdriver from 'next-webdriver' import cheerio from 'cheerio' -import { waitFor, check } from 'next-test-utils' +import { check } from 'next-test-utils' export default (context, render) => { async function get$(path, query) { @@ -227,76 +227,5 @@ export default (context, render) => { } }) }) - - describe('Import mapping', () => { - it('should render dynamic imports bundle', async () => { - const $ = await get$('/dynamic/bundle') - const bodyText = $('body').text() - expect(/Dynamic Bundle/.test(bodyText)).toBe(true) - expect(/Hello World 1/.test(bodyText)).toBe(true) - expect(/Hello World 2/.test(bodyText)).toBe(false) - }) - - it('should render dynamic imports bundle with additional components', async () => { - const $ = await get$('/dynamic/bundle?showMore=1') - const bodyText = $('body').text() - expect(/Dynamic Bundle/.test(bodyText)).toBe(true) - expect(/Hello World 1/.test(bodyText)).toBe(true) - expect(/Hello World 2/.test(bodyText)).toBe(true) - }) - - it('should render components', async () => { - const browser = await webdriver(context.appPort, '/dynamic/bundle') - - while (true) { - const bodyText = await browser.elementByCss('body').text() - if ( - /Dynamic Bundle/.test(bodyText) && - /Hello World 1/.test(bodyText) && - !/Hello World 2/.test(bodyText) - ) { - break - } - await waitFor(1000) - } - - await browser.close() - }) - - it('should render support React context', async () => { - const browser = await webdriver(context.appPort, '/dynamic/bundle') - - while (true) { - const bodyText = await browser.elementByCss('body').text() - if (/Vercel Rocks/.test(bodyText)) break - await waitFor(1000) - } - - await browser.close() - }) - - it('should load new components and render for prop changes', async () => { - const browser = await webdriver(context.appPort, '/dynamic/bundle') - - await browser - .waitForElementByCss('#toggle-show-more') - .elementByCss('#toggle-show-more') - .click() - - while (true) { - const bodyText = await browser.elementByCss('body').text() - if ( - /Dynamic Bundle/.test(bodyText) && - /Hello World 1/.test(bodyText) && - /Hello World 2/.test(bodyText) - ) { - break - } - await waitFor(1000) - } - - await browser.close() - }) - }) }) } diff --git a/test/integration/build-output/test/index.test.js b/test/integration/build-output/test/index.test.js index 41f800ec9af6f..8a2571989cb64 100644 --- a/test/integration/build-output/test/index.test.js +++ b/test/integration/build-output/test/index.test.js @@ -123,22 +123,22 @@ describe('Build Output', () => { ) expect(indexSize.endsWith('B')).toBe(true) - expect(parseFloat(indexFirstLoad)).toBeCloseTo(gz ? 63.5 : 195, 1) + expect(parseFloat(indexFirstLoad)).toBeCloseTo(gz ? 63.3 : 194, 1) expect(indexFirstLoad.endsWith('kB')).toBe(true) expect(parseFloat(err404Size)).toBeCloseTo(gz ? 3.06 : 8.15, 1) expect(err404Size.endsWith('kB')).toBe(true) - expect(parseFloat(err404FirstLoad)).toBeCloseTo(gz ? 66.3 : 202, 1) + expect(parseFloat(err404FirstLoad)).toBeCloseTo(gz ? 66.1 : 202, 1) expect(err404FirstLoad.endsWith('kB')).toBe(true) - expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 63.2 : 194, 1) + expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 63 : 194, 1) expect(sharedByAll.endsWith('kB')).toBe(true) const appSizeValue = _appSize.endsWith('kB') ? parseFloat(_appSize) : parseFloat(_appSize) / 1000 - expect(appSizeValue).toBeCloseTo(gz ? 1.0 : 2.18, 1) + expect(appSizeValue).toBeCloseTo(gz ? 0.799 : 1.63, 1) expect(_appSize.endsWith('kB') || _appSize.endsWith(' B')).toBe(true) const webpackSizeValue = webpackSize.endsWith('kB') @@ -149,7 +149,7 @@ describe('Build Output', () => { true ) - expect(parseFloat(mainSize)).toBeCloseTo(gz ? 19.4 : 60.5, 1) + expect(parseFloat(mainSize)).toBeCloseTo(gz ? 19.4 : 60.6, 1) expect(mainSize.endsWith('kB')).toBe(true) expect(parseFloat(frameworkSize)).toBeCloseTo(gz ? 42.0 : 130, 1) diff --git a/test/integration/client-navigation/pages/nav/shallow-routing.js b/test/integration/client-navigation/pages/nav/shallow-routing.js index 728467f9afde4..5703ae7f0c76a 100644 --- a/test/integration/client-navigation/pages/nav/shallow-routing.js +++ b/test/integration/client-navigation/pages/nav/shallow-routing.js @@ -1,6 +1,6 @@ import { Component } from 'react' import Link from 'next/link' -import Router from 'next/router' +import Router, { withRouter } from 'next/router' let getInitialPropsRunCount = 1 @@ -8,60 +8,62 @@ const linkStyle = { marginRight: 10, } -export default class extends Component { - static getInitialProps({ res }) { - if (res) return { getInitialPropsRunCount: 1 } - getInitialPropsRunCount++ +export default withRouter( + class extends Component { + static getInitialProps({ res }) { + if (res) return { getInitialPropsRunCount: 1 } + getInitialPropsRunCount++ - return { getInitialPropsRunCount } - } + return { getInitialPropsRunCount } + } - getCurrentCounter() { - const { url } = this.props - return url.query.counter ? parseInt(url.query.counter) : 0 - } + getCurrentCounter() { + const { router } = this.props + return router.query.counter ? parseInt(router.query.counter) : 0 + } - increase() { - const counter = this.getCurrentCounter() - const href = `/nav/shallow-routing?counter=${counter + 1}` - Router.push(href, href, { shallow: true }) - } + increase() { + const counter = this.getCurrentCounter() + const href = `/nav/shallow-routing?counter=${counter + 1}` + Router.push(href, href, { shallow: true }) + } - increaseNonShallow() { - const counter = this.getCurrentCounter() - const href = `/nav/shallow-routing?counter=${counter + 1}` - Router.push(href, href, {}) - } + increaseNonShallow() { + const counter = this.getCurrentCounter() + const href = `/nav/shallow-routing?counter=${counter + 1}` + Router.push(href, href, {}) + } - gotoNavShallow() { - const href = `/nav` - Router.push(href, href, { shallow: true }) - } + gotoNavShallow() { + const href = `/nav` + Router.push(href, href, { shallow: true }) + } - render() { - return ( -
- - - Home - - -
- Counter: {this.getCurrentCounter()} -
-
- getInitialProps run count: {this.props.getInitialPropsRunCount} + render() { + return ( +
+ + + Home + + +
+ Counter: {this.getCurrentCounter()} +
+
+ getInitialProps run count: {this.props.getInitialPropsRunCount} +
+ + +
- - - -
- ) + ) + } } -} +) diff --git a/test/integration/client-navigation/pages/nav/url-prop-change.js b/test/integration/client-navigation/pages/nav/url-prop-change.js deleted file mode 100644 index 0b2a1095f70cc..0000000000000 --- a/test/integration/client-navigation/pages/nav/url-prop-change.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react' -import Link from 'next/link' - -export default class UrlPropChange extends React.Component { - constructor(props) { - super(props) - this.state = { - previousUrl: {}, - url: props.url, - } - } - - componentDidUpdate(prevProps) { - if (prevProps.url !== this.props.url) { - this.setState(() => { - return { - previousUrl: prevProps.url, - url: this.props.url, - } - }) - } - } - - render() { - const { previousUrl, url } = this.state - return ( -
- Current: -
{JSON.stringify(url)}
-
-
- Previous: -
{JSON.stringify(previousUrl)}
- - Add querystring - -
- ) - } -} diff --git a/test/integration/client-navigation/pages/url-prop-override.js b/test/integration/client-navigation/pages/url-prop-override.js deleted file mode 100644 index 68d5067c8943c..0000000000000 --- a/test/integration/client-navigation/pages/url-prop-override.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' -export default class extends React.Component { - static getInitialProps() { - return { - url: 'test', // This gets overridden by Next in lib/_app.js - } - } - render() { - const { url } = this.props - return ( -
-

{url.pathname}

-

{Object.keys(url.query).length}

-

{url.asPath}

-
- ) - } -} diff --git a/test/integration/client-navigation/pages/url-prop.js b/test/integration/client-navigation/pages/url-prop.js deleted file mode 100644 index 465d963d26722..0000000000000 --- a/test/integration/client-navigation/pages/url-prop.js +++ /dev/null @@ -1,13 +0,0 @@ -const Page = ({ url }) => { - return ( -
-

{url.pathname}

-

{Object.keys(url.query).length}

-

{url.asPath}

-
- ) -} - -Page.getInitialProps = () => ({}) - -export default Page diff --git a/test/integration/client-navigation/test/index.test.js b/test/integration/client-navigation/test/index.test.js index 3e73719dd690d..5f666b5a00648 100644 --- a/test/integration/client-navigation/test/index.test.js +++ b/test/integration/client-navigation/test/index.test.js @@ -42,7 +42,6 @@ describe('Client Navigation', () => { '/styled-jsx-external', '/with-cdm', '/url-prop', - '/url-prop-override', '/dynamic/ssr', '/dynamic/[slug]/route', @@ -57,7 +56,6 @@ describe('Client Navigation', () => { '/nav/redirect', '/nav/as-path', '/nav/as-path-using-router', - '/nav/url-prop-change', '/nested-cdm', ] @@ -169,30 +167,6 @@ describe('Client Navigation', () => { }) }) - describe('With url property', () => { - it('Should keep immutable pathname, asPath and query', async () => { - const browser = await webdriver(context.appPort, '/nav/url-prop-change') - await browser.elementByCss('#add-query').click() - const urlResult = await browser.elementByCss('#url-result').text() - const previousUrlResult = await browser - .elementByCss('#previous-url-result') - .text() - - expect(JSON.parse(urlResult)).toMatchObject({ - query: { added: 'yes' }, - pathname: '/nav/url-prop-change', - asPath: '/nav/url-prop-change?added=yes', - }) - expect(JSON.parse(previousUrlResult)).toMatchObject({ - query: {}, - pathname: '/nav/url-prop-change', - asPath: '/nav/url-prop-change', - }) - - await browser.close() - }) - }) - describe('with tag inside the ', () => { it('should navigate the page', async () => { const browser = await webdriver(context.appPort, '/nav/about') diff --git a/test/integration/client-navigation/test/rendering.js b/test/integration/client-navigation/test/rendering.js index a8eb14a3893e9..b991454c2fa09 100644 --- a/test/integration/client-navigation/test/rendering.js +++ b/test/integration/client-navigation/test/rendering.js @@ -209,7 +209,7 @@ export default function (render, fetch, ctx) { }) it('should render the page without `nextExport` property', async () => { - const html = await render('/url-prop') + const html = await render('/async-props') expect(html).not.toContain('"nextExport"') }) @@ -376,22 +376,6 @@ export default function (render, fetch, ctx) { expect($('.as-path-content').text()).toBe('/nav/as-path?aa=10') }) - describe('Url prop', () => { - it('should provide pathname, query and asPath', async () => { - const $ = await get$('/url-prop') - expect($('#pathname').text()).toBe('/url-prop') - expect($('#query').text()).toBe('0') - expect($('#aspath').text()).toBe('/url-prop') - }) - - it('should override props.url, even when getInitialProps returns url as property', async () => { - const $ = await get$('/url-prop-override') - expect($('#pathname').text()).toBe('/url-prop-override') - expect($('#query').text()).toBe('0') - expect($('#aspath').text()).toBe('/url-prop-override') - }) - }) - describe('404', () => { it('should 404 on not existent page', async () => { const $ = await get$('/non-existent') diff --git a/test/integration/custom-routes/pages/multi-rewrites.js b/test/integration/custom-routes/pages/multi-rewrites.js index 516c8ad7c29ac..aff869dcc74d8 100644 --- a/test/integration/custom-routes/pages/multi-rewrites.js +++ b/test/integration/custom-routes/pages/multi-rewrites.js @@ -1 +1,3 @@ -export default () => 'multi-rewrites' +const Page = () => 'multi-rewrites' + +export default Page diff --git a/test/integration/custom-routes/pages/nav.js b/test/integration/custom-routes/pages/nav.js index 88ca61b02404c..2be4ac0870eac 100644 --- a/test/integration/custom-routes/pages/nav.js +++ b/test/integration/custom-routes/pages/nav.js @@ -1,6 +1,6 @@ import Link from 'next/link' -export default () => ( +const Page = () => ( <> @@ -42,3 +42,4 @@ export default () => (
) +export default Page diff --git a/test/integration/custom-routes/test/index.test.js b/test/integration/custom-routes/test/index.test.js index 461774b7a799a..9453a19eb5fd5 100644 --- a/test/integration/custom-routes/test/index.test.js +++ b/test/integration/custom-routes/test/index.test.js @@ -20,6 +20,7 @@ import { normalizeRegEx, initNextServerScript, nextExport, + hasRedbox, } from 'next-test-utils' jest.setTimeout(1000 * 60 * 2) @@ -38,6 +39,42 @@ let appPort let app const runTests = (isDev = false) => { + it('should resolveHref correctly navigating through history', async () => { + const browser = await webdriver(appPort, '/') + await browser.eval('window.beforeNav = 1') + + expect(await browser.eval('document.documentElement.innerHTML')).toContain( + 'multi-rewrites' + ) + + await browser.eval('next.router.push("/rewriting-to-auto-export")') + await browser.waitForElementByCss('#auto-export') + + expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({ + slug: 'hello', + rewrite: '1', + }) + expect(await browser.eval('window.beforeNav')).toBe(1) + + await browser.eval('next.router.push("/nav")') + await browser.waitForElementByCss('#nav') + + expect(await browser.elementByCss('#nav').text()).toBe('Nav') + + await browser.back() + await browser.waitForElementByCss('#auto-export') + + expect(JSON.parse(await browser.elementByCss('#query').text())).toEqual({ + slug: 'hello', + rewrite: '1', + }) + expect(await browser.eval('window.beforeNav')).toBe(1) + + if (isDev) { + expect(await hasRedbox(browser, false)).toBe(false) + } + }) + it('should continue in beforeFiles rewrites', async () => { const res = await fetchViaHTTP(appPort, '/old-blog/about') expect(res.status).toBe(200) diff --git a/test/integration/font-optimization/fixtures/with-google/pages/_document.js b/test/integration/font-optimization/fixtures/with-google/pages/_document.js index f3f300181f324..6b1db914b491f 100644 --- a/test/integration/font-optimization/fixtures/with-google/pages/_document.js +++ b/test/integration/font-optimization/fixtures/with-google/pages/_document.js @@ -1,7 +1,6 @@ import * as React from 'react' /// @ts-ignore import Document, { Main, NextScript, Head } from 'next/document' - export default class MyDocument extends Document { constructor(props) { super(props) diff --git a/test/integration/font-optimization/fixtures/with-typekit/manifest-snapshot.json b/test/integration/font-optimization/fixtures/with-typekit/manifest-snapshot.json index 42681af1533b5..cb517f819778c 100644 --- a/test/integration/font-optimization/fixtures/with-typekit/manifest-snapshot.json +++ b/test/integration/font-optimization/fixtures/with-typekit/manifest-snapshot.json @@ -1,14 +1,14 @@ [ { "url": "https://use.typekit.net/plm1izr.css", - "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=plm1izr&ht=tk&f=32266&a=23152309&app=typekit&e=css\");@font-face{font-family:\"birra-2\";src:url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:700}.tk-birra-2{font-family:\"birra-2\",serif}@import url(\"https://p.typekit.net/p.css?s=1&k=plm1izr&ht=tk&f=32266&a=23152309&app=typekit&e=css\");@font-face{font-family:\"birra-2\";src:url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:700}.tk-birra-2{font-family:\"birra-2\",serif}" + "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=plm1izr&ht=tk&f=32266&a=23152309&app=typekit&e=css\");@font-face{font-family:\"birra-2\";src:url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:700}.tk-birra-2{font-family:\"birra-2\",serif}" }, { "url": "https://use.typekit.net/ucs7mcf.css", - "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=ucs7mcf&ht=tk&f=43886&a=23152309&app=typekit&e=css\");@font-face{font-family:\"flegrei\";src:url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-flegrei{font-family:\"flegrei\",sans-serif}@import url(\"https://p.typekit.net/p.css?s=1&k=ucs7mcf&ht=tk&f=43886&a=23152309&app=typekit&e=css\");@font-face{font-family:\"flegrei\";src:url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-flegrei{font-family:\"flegrei\",sans-serif}" + "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=ucs7mcf&ht=tk&f=43886&a=23152309&app=typekit&e=css\");@font-face{font-family:\"flegrei\";src:url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-flegrei{font-family:\"flegrei\",sans-serif}" }, { "url": "https://use.typekit.net/erd0sed.css", - "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=erd0sed&ht=tk&f=43885&a=23152309&app=typekit&e=css\");@font-face{font-family:\"pantelleria\";src:url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-pantelleria{font-family:\"pantelleria\",sans-serif}@import url(\"https://p.typekit.net/p.css?s=1&k=erd0sed&ht=tk&f=43885&a=23152309&app=typekit&e=css\");@font-face{font-family:\"pantelleria\";src:url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-pantelleria{font-family:\"pantelleria\",sans-serif}" + "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=erd0sed&ht=tk&f=43885&a=23152309&app=typekit&e=css\");@font-face{font-family:\"pantelleria\";src:url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-pantelleria{font-family:\"pantelleria\",sans-serif}" } ] diff --git a/test/integration/font-optimization/test/index.test.js b/test/integration/font-optimization/test/index.test.js index da01c47350f83..6ac704e066be8 100644 --- a/test/integration/font-optimization/test/index.test.js +++ b/test/integration/font-optimization/test/index.test.js @@ -54,6 +54,7 @@ describe('Font Optimization', () => { /