diff --git a/errors/babel-font-loader-conflict.md b/errors/babel-font-loader-conflict.md index 00fb535e0b869..3f078db3abc25 100644 --- a/errors/babel-font-loader-conflict.md +++ b/errors/babel-font-loader-conflict.md @@ -1,8 +1,8 @@ -# Babel and `@next/font` conflict +# Babel and `next/font` conflict #### Why This Error Occurred -You have tried to use `@next/font` with a custom babel config. When your application has a custom babel config you opt-out of the Next.js Compiler which is required to use `@next/font`. +You have tried to use `next/font` with a custom babel config. When your application has a custom babel config you opt-out of the Next.js Compiler which is required to use `next/font`. #### Possible Ways to Fix It diff --git a/packages/font/src/google/utils.ts b/packages/font/src/google/utils.ts index 51de0a2c95dc6..07d5484bd6181 100644 --- a/packages/font/src/google/utils.ts +++ b/packages/font/src/google/utils.ts @@ -39,7 +39,7 @@ export function validateData( const subsets = callSubsets ?? config?.subsets ?? [] if (functionName === '') { - nextFontError(`@next/font/google has no default export`) + nextFontError(`next/font/google has no default export`) } const fontFamily = functionName.replace(/_/g, ' ') diff --git a/packages/font/src/local/utils.ts b/packages/font/src/local/utils.ts index 623e875eadbd7..0ffe7ba3ecd8c 100644 --- a/packages/font/src/local/utils.ts +++ b/packages/font/src/local/utils.ts @@ -32,7 +32,7 @@ type FontOptions = { } export function validateData(functionName: string, fontData: any): FontOptions { if (functionName) { - nextFontError(`@next/font/local has no named exports`) + nextFontError(`next/font/local has no named exports`) } let { src, diff --git a/packages/next/font/google/index.d.ts b/packages/next/font/google/index.d.ts new file mode 100644 index 0000000000000..455eb96a8e31b --- /dev/null +++ b/packages/next/font/google/index.d.ts @@ -0,0 +1 @@ +export * from '@next/font/dist/google' diff --git a/packages/next/font/google/index.js b/packages/next/font/google/index.js index dbd5f2de02bb4..e69de29bb2d1d 100644 --- a/packages/next/font/google/index.js +++ b/packages/next/font/google/index.js @@ -1,3 +0,0 @@ -throw new Error( - 'You tried to import `next/font/google`, did you mean `@next/font/google`?\nRead more: https://nextjs.org/docs/basic-features/font-optimization' -) diff --git a/packages/next/font/google/loader.js b/packages/next/font/google/loader.js new file mode 100644 index 0000000000000..ea72adc944a4f --- /dev/null +++ b/packages/next/font/google/loader.js @@ -0,0 +1 @@ +module.exports = require('@next/font/dist/google/loader') diff --git a/packages/next/font/google/target.css b/packages/next/font/google/target.css new file mode 100644 index 0000000000000..e3eb179b3405e --- /dev/null +++ b/packages/next/font/google/target.css @@ -0,0 +1 @@ +/* target file for webpack loader */ diff --git a/packages/next/font/index.js b/packages/next/font/index.js deleted file mode 100644 index 829031b71436c..0000000000000 --- a/packages/next/font/index.js +++ /dev/null @@ -1,3 +0,0 @@ -throw new Error( - 'You tried to import `next/font`, did you mean `@next/font`?\nRead more: https://nextjs.org/docs/basic-features/font-optimization' -) diff --git a/packages/next/font/local/index.d.ts b/packages/next/font/local/index.d.ts new file mode 100644 index 0000000000000..1ee8bfd766390 --- /dev/null +++ b/packages/next/font/local/index.d.ts @@ -0,0 +1 @@ +export { default } from '@next/font/dist/local' diff --git a/packages/next/font/local/index.js b/packages/next/font/local/index.js index 50a6649791c4f..e69de29bb2d1d 100644 --- a/packages/next/font/local/index.js +++ b/packages/next/font/local/index.js @@ -1,3 +0,0 @@ -throw new Error( - 'You tried to import `next/font/local`, did you mean `@next/font/local`?\nRead more: https://nextjs.org/docs/basic-features/font-optimization' -) diff --git a/packages/next/font/local/loader.js b/packages/next/font/local/loader.js new file mode 100644 index 0000000000000..e29e59c52cb13 --- /dev/null +++ b/packages/next/font/local/loader.js @@ -0,0 +1 @@ +module.exports = require('@next/font/dist/local/loader') diff --git a/packages/next/font/local/target.css b/packages/next/font/local/target.css new file mode 100644 index 0000000000000..e3eb179b3405e --- /dev/null +++ b/packages/next/font/local/target.css @@ -0,0 +1 @@ +/* target file for webpack loader */ diff --git a/packages/next/package.json b/packages/next/package.json index 1135337a3b13a..03b54240fd56c 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -78,6 +78,7 @@ }, "dependencies": { "@next/env": "13.1.7-canary.10", + "@next/font": "13.1.7-canary.10", "@swc/helpers": "0.4.14", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", diff --git a/packages/next/src/build/babel/plugins/next-font-unsupported.ts b/packages/next/src/build/babel/plugins/next-font-unsupported.ts index dd17ebf551f1f..49dc853ea3e64 100644 --- a/packages/next/src/build/babel/plugins/next-font-unsupported.ts +++ b/packages/next/src/build/babel/plugins/next-font-unsupported.ts @@ -5,12 +5,15 @@ export default function NextPageDisallowReExportAllExports(): PluginObj { visitor: { ImportDeclaration(path: NodePath) { if ( - ['@next/font/local', '@next/font/google'].includes( - path.node.source.value - ) + [ + '@next/font/local', + '@next/font/google', + 'next/font/local', + 'next/font/google', + ].includes(path.node.source.value) ) { const err = new SyntaxError( - `"@next/font" requires SWC although Babel is being used due to a custom babel config being present.\nRead more: https://nextjs.org/docs/messages/babel-font-loader-conflict` + `"next/font" requires SWC although Babel is being used due to a custom babel config being present.\nRead more: https://nextjs.org/docs/messages/babel-font-loader-conflict` ) ;(err as any).code = 'BABEL_PARSE_ERROR' ;(err as any).loc = diff --git a/packages/next/src/build/entries.ts b/packages/next/src/build/entries.ts index b436ff711e620..7c60d029b0ae5 100644 --- a/packages/next/src/build/entries.ts +++ b/packages/next/src/build/entries.ts @@ -199,7 +199,6 @@ export function getEdgeServerEntry(opts: { pagesType: opts.pagesType, appDirLoader: Buffer.from(opts.appDirLoader || '').toString('base64'), sriEnabled: !opts.isDev && !!opts.config.experimental.sri?.algorithm, - hasFontLoaders: !!opts.config.experimental.fontLoaders, } return { diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index e24fab1063d40..a8667f0ca3669 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -919,12 +919,8 @@ export default async function build( : null, BUILD_ID_FILE, appDir ? path.join(SERVER_DIRECTORY, APP_PATHS_MANIFEST) : null, - ...(config.experimental.fontLoaders - ? [ - path.join(SERVER_DIRECTORY, FONT_LOADER_MANIFEST + '.js'), - path.join(SERVER_DIRECTORY, FONT_LOADER_MANIFEST + '.json'), - ] - : []), + path.join(SERVER_DIRECTORY, FONT_LOADER_MANIFEST + '.js'), + path.join(SERVER_DIRECTORY, FONT_LOADER_MANIFEST + '.json'), ] .filter(nonNullable) .map((file) => path.join(config.distDir, file)), diff --git a/packages/next/src/build/jest/jest.ts b/packages/next/src/build/jest/jest.ts index 9ba1fb0b2a9d5..195fb065dc3c6 100644 --- a/packages/next/src/build/jest/jest.ts +++ b/packages/next/src/build/jest/jest.ts @@ -118,6 +118,8 @@ export default function nextJest(options: { dir?: string } = {}) { // Handle @next/font '@next/font/(.*)': require.resolve('./__mocks__/nextFontMock.js'), + // Handle next/font + 'next/font/(.*)': require.resolve('./__mocks__/nextFontMock.js'), // custom config comes last to ensure the above rules are matched, // fixes the case where @pages/(.*) -> src/pages/$! doesn't break diff --git a/packages/next/src/build/swc/options.ts b/packages/next/src/build/swc/options.ts index 274f5a10939bc..7499ec9c47c7c 100644 --- a/packages/next/src/build/swc/options.ts +++ b/packages/next/src/build/swc/options.ts @@ -250,14 +250,16 @@ any) { hasServerComponents, isServerLayer, }) + baseOptions.fontLoaders = { + fontLoaders: [ + 'next/font/local', + 'next/font/google', - if (nextConfig?.experimental?.fontLoaders && relativeFilePathFromRoot) { - baseOptions.fontLoaders = { - fontLoaders: nextConfig.experimental.fontLoaders.map( - ({ loader }: any) => loader - ), - relativeFilePathFromRoot, - } + // TODO: remove this in the next major version + '@next/font/local', + '@next/font/google', + ], + relativeFilePathFromRoot, } const isNextDist = nextDistPath.test(filename) diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index ec5043a970956..002f92ef6fa31 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -1370,13 +1370,6 @@ export default async function getBaseWebpackConfig( }, } - const fontLoaderTargets = - config.experimental.fontLoaders && - config.experimental.fontLoaders.map(({ loader }) => { - const resolved = require.resolve(loader) - return path.join(resolved, '../target.css') - }) - let webpackConfig: webpack.Configuration = { parallelism: Number(process.env.NEXT_WEBPACK_PARALLELISM) || undefined, ...(isNodeServer ? { externalsPresets: { node: true } } : {}), @@ -2099,7 +2092,6 @@ export default async function getBaseWebpackConfig( new MiddlewarePlugin({ dev, sriEnabled: !dev && !!config.experimental.sri?.algorithm, - hasFontLoaders: !!config.experimental.fontLoaders, }), isClient && new BuildManifestPlugin({ @@ -2164,10 +2156,8 @@ export default async function getBaseWebpackConfig( !!config.experimental.sri?.algorithm && new SubresourceIntegrityPlugin(config.experimental.sri.algorithm), isClient && - fontLoaderTargets && new FontLoaderManifestPlugin({ appDirEnabled: !!config.experimental.appDir, - fontLoaderTargets, }), !dev && isClient && diff --git a/packages/next/src/build/webpack/config/blocks/css/index.ts b/packages/next/src/build/webpack/config/blocks/css/index.ts index 27a85a5a120d2..7de1abd9a9e0a 100644 --- a/packages/next/src/build/webpack/config/blocks/css/index.ts +++ b/packages/next/src/build/webpack/config/blocks/css/index.ts @@ -1,4 +1,3 @@ -import path from 'path' import curry from 'next/dist/compiled/lodash.curry' import { webpack } from 'next/dist/compiled/webpack/webpack' import { loader, plugin } from '../../helpers' @@ -181,32 +180,50 @@ export const css = curry(async function css( const fns: ConfigurationFn[] = [] - // Resolve the configured font loaders, the resolved files are noop files that next-font-loader will match - let fontLoaders: [string, string][] | undefined = ctx.experimental.fontLoaders - ? ctx.experimental.fontLoaders.map(({ loader: fontLoader, options }) => [ - path.join(require.resolve(fontLoader), '../target.css'), - options, - ]) - : undefined + const googleLoaderOptions = + ctx.experimental?.fontLoaders?.find( + (loaderConfig) => + loaderConfig.loader === 'next/font/google' || + loaderConfig.loader === '@next/font/google' + )?.options ?? {} + const fontLoaders: Array<[string | RegExp, string, any?]> = [ + [ + require.resolve('next/font/google/target.css'), + '@next/font/google/loader', + googleLoaderOptions, + ], + [require.resolve('next/font/local/target.css'), '@next/font/local/loader'], + + // TODO: remove this in the next major version + [ + /node_modules\/@next\/font\/google\/target.css/, + '@next/font/google/loader', + googleLoaderOptions, + ], + [/node_modules\/@next\/font\/local\/target.css/, '@next/font/local/loader'], + ] - fontLoaders?.forEach(([fontLoaderPath, fontLoaderOptions]) => { - // Matches the resolved font loaders noop files to run next-font-loader - fns.push( - loader({ - oneOf: [ - markRemovable({ - sideEffects: false, - test: fontLoaderPath, - use: getNextFontLoader( - ctx, - lazyPostCSSInitializer, - fontLoaderOptions - ), - }), - ], - }) - ) - }) + fontLoaders.forEach( + ([fontLoaderTarget, fontLoaderPath, fontLoaderOptions]) => { + // Matches the resolved font loaders noop files to run next-font-loader + fns.push( + loader({ + oneOf: [ + markRemovable({ + sideEffects: false, + test: fontLoaderTarget, + use: getNextFontLoader( + ctx, + lazyPostCSSInitializer, + fontLoaderPath, + fontLoaderOptions + ), + }), + ], + }) + ) + } + ) // CSS cannot be imported in _document. This comes before everything because // global CSS nor CSS modules work in said file. diff --git a/packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts b/packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts index 67440b8c6625f..b3273ba97c650 100644 --- a/packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts +++ b/packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts @@ -6,6 +6,7 @@ import { cssFileResolve } from './file-resolve' export function getNextFontLoader( ctx: ConfigurationContext, postcss: any, + fontLoaderPath: string, fontLoaderOptions: any ): webpack.RuleSetUseItem[] { const loaders: webpack.RuleSetUseItem[] = [] @@ -62,6 +63,7 @@ export function getNextFontLoader( isDev: ctx.isDevelopment, isServer: ctx.isServer, assetPrefix: ctx.assetPrefix, + fontLoaderPath, fontLoaderOptions, postcss, }, diff --git a/packages/next/src/build/webpack/loaders/next-edge-ssr-loader/index.ts b/packages/next/src/build/webpack/loaders/next-edge-ssr-loader/index.ts index 59ebcf17f55d1..1de9b6617a398 100644 --- a/packages/next/src/build/webpack/loaders/next-edge-ssr-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-edge-ssr-loader/index.ts @@ -15,7 +15,6 @@ export type EdgeSSRLoaderQuery = { appDirLoader?: string pagesType: 'app' | 'pages' | 'root' sriEnabled: boolean - hasFontLoaders: boolean } /* @@ -45,7 +44,6 @@ export default async function edgeSSRLoader(this: any) { appDirLoader: appDirLoaderBase64, pagesType, sriEnabled, - hasFontLoaders, } = this.getOptions() const appDirLoader = Buffer.from( @@ -127,9 +125,7 @@ export default async function edgeSSRLoader(this: any) { const subresourceIntegrityManifest = ${ sriEnabled ? 'self.__SUBRESOURCE_INTEGRITY_MANIFEST' : 'undefined' } - const fontLoaderManifest = ${ - hasFontLoaders ? 'self.__FONT_LOADER_MANIFEST' : 'undefined' - } + const fontLoaderManifest = self.__FONT_LOADER_MANIFEST const render = getRender({ pageType, diff --git a/packages/next/src/build/webpack/loaders/next-font-loader/index.ts b/packages/next/src/build/webpack/loaders/next-font-loader/index.ts index be7c30463e04f..d5bf2f4d6024b 100644 --- a/packages/next/src/build/webpack/loaders/next-font-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-font-loader/index.ts @@ -37,6 +37,7 @@ export default async function nextFontLoader(this: any) { isDev, isServer, assetPrefix, + fontLoaderPath, fontLoaderOptions, postcss: getPostcss, } = this.getOptions() @@ -82,10 +83,7 @@ export default async function nextFontLoader(this: any) { } try { - const fontLoader: FontLoader = require(path.join( - this.resourcePath, - '../loader.js' - )).default + const fontLoader: FontLoader = require(fontLoaderPath).default let { css, fallbackFonts, adjustFontFallback, weight, style, variable } = await fontLoader({ functionName, diff --git a/packages/next/src/build/webpack/plugins/font-loader-manifest-plugin.ts b/packages/next/src/build/webpack/plugins/font-loader-manifest-plugin.ts index 898f5140129ee..465ab4c8ff120 100644 --- a/packages/next/src/build/webpack/plugins/font-loader-manifest-plugin.ts +++ b/packages/next/src/build/webpack/plugins/font-loader-manifest-plugin.ts @@ -14,17 +14,20 @@ export type FontLoaderManifest = { } const PLUGIN_NAME = 'FontLoaderManifestPlugin' +const fontLoaderTargets = [ + require.resolve('next/font/google/target.css'), + require.resolve('next/font/local/target.css'), + // TODO: remove this in the next major version + /node_modules\/@next\/font\/google\/target\.css\?{.+}$/, + /node_modules\/@next\/font\/local\/target\.css\?{.+}$/, +] + // Creates a manifest of all fonts that should be preloaded given a route export class FontLoaderManifestPlugin { private appDirEnabled: boolean - private fontLoaderTargets: string[] - constructor(options: { - appDirEnabled: boolean - fontLoaderTargets: string[] - }) { + constructor(options: { appDirEnabled: boolean }) { this.appDirEnabled = options.appDirEnabled - this.fontLoaderTargets = options.fontLoaderTargets } apply(compiler: webpack.Compiler) { @@ -36,8 +39,10 @@ export class FontLoaderManifestPlugin { compilation.hooks.finishModules.tap(PLUGIN_NAME, (modules) => { const modulesArr = Array.from(modules) fontLoaderModules = modulesArr.filter((mod: any) => - this.fontLoaderTargets.some((fontLoaderTarget) => - mod.userRequest?.startsWith(`${fontLoaderTarget}?`) + fontLoaderTargets.some((fontLoaderTarget) => + typeof fontLoaderTarget === 'string' + ? mod.userRequest?.startsWith(`${fontLoaderTarget}?`) + : fontLoaderTarget.test(mod.userRequest) ) ) }) diff --git a/packages/next/src/build/webpack/plugins/middleware-plugin.ts b/packages/next/src/build/webpack/plugins/middleware-plugin.ts index 0b957799c0069..1bf5761db5e85 100644 --- a/packages/next/src/build/webpack/plugins/middleware-plugin.ts +++ b/packages/next/src/build/webpack/plugins/middleware-plugin.ts @@ -90,7 +90,7 @@ function isUsingIndirectEvalAndUsedByExports(args: { function getEntryFiles( entryFiles: string[], meta: EntryMetadata, - opts: { sriEnabled: boolean; hasFontLoaders: boolean } + opts: { sriEnabled: boolean } ) { const files: string[] = [] if (meta.edgeSSR) { @@ -120,9 +120,7 @@ function getEntryFiles( `server/${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js` ) - if (opts.hasFontLoaders) { - files.push(`server/${FONT_LOADER_MANIFEST}.js`) - } + files.push(`server/${FONT_LOADER_MANIFEST}.js`) } files.push( @@ -136,7 +134,7 @@ function getEntryFiles( function getCreateAssets(params: { compilation: webpack.Compilation metadataByEntry: Map - opts: { sriEnabled: boolean; hasFontLoaders: boolean } + opts: { sriEnabled: boolean } }) { const { compilation, metadataByEntry, opts } = params return (assets: any) => { @@ -787,20 +785,10 @@ function getExtractMetadata(params: { export default class MiddlewarePlugin { private readonly dev: boolean private readonly sriEnabled: boolean - private readonly hasFontLoaders: boolean - - constructor({ - dev, - sriEnabled, - hasFontLoaders, - }: { - dev: boolean - sriEnabled: boolean - hasFontLoaders: boolean - }) { + + constructor({ dev, sriEnabled }: { dev: boolean; sriEnabled: boolean }) { this.dev = dev this.sriEnabled = sriEnabled - this.hasFontLoaders = hasFontLoaders } public apply(compiler: webpack.Compiler) { @@ -845,7 +833,6 @@ export default class MiddlewarePlugin { metadataByEntry, opts: { sriEnabled: this.sriEnabled, - hasFontLoaders: this.hasFontLoaders, }, }) ) diff --git a/packages/next/src/build/webpack/plugins/telemetry-plugin.ts b/packages/next/src/build/webpack/plugins/telemetry-plugin.ts index 1f7891192f087..156ef5802d24d 100644 --- a/packages/next/src/build/webpack/plugins/telemetry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/telemetry-plugin.ts @@ -26,6 +26,8 @@ export type Feature = | 'next/dynamic' | '@next/font/google' | '@next/font/local' + | 'next/font/google' + | 'next/font/local' | 'swcLoader' | 'swcMinify' | 'swcRelay' @@ -73,6 +75,8 @@ const FEATURE_MODULE_MAP: ReadonlyMap = new Map([ const FEATURE_MODULE_REGEXP_MAP: ReadonlyMap = new Map([ ['@next/font/google', /\/@next\/font\/google\/target.css?.+$/], ['@next/font/local', /\/@next\/font\/local\/target.css?.+$/], + ['next/font/google', /\/next\/font\/google\/target.css?.+$/], + ['next/font/local', /\/next\/font\/local\/target.css?.+$/], ]) // List of build features used in webpack configuration diff --git a/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts b/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts index 5c433dea1c228..e86ce98bba1ff 100644 --- a/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts +++ b/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts @@ -6,7 +6,11 @@ export function getNextFontError( ): SimpleWebpackError | false { try { const resourceResolveData = module.resourceResolveData - if (resourceResolveData.descriptionFileData.name !== '@next/font') { + if ( + !module.loaders.find((loader: any) => + loader.loader.includes('next-font-loader/index.js') + ) + ) { return false } @@ -18,26 +22,14 @@ export function getNextFontError( // Known error thrown by @next/font, display the error message return new SimpleWebpackError( file, - `\`@next/font\` error:\n${err.message}` + `\`next/font\` error:\n${err.message}` ) } else { // Unknown error thrown by @next/font - // It might be becuase of incompatible versions of @next/font and next are being used, or it might be a bug - - // eslint-disable-next-line import/no-extraneous-dependencies - const nextFontVersion = require('@next/font/package.json').version - const nextVersion = process.env.__NEXT_VERSION - - let message = `An error occured in \`@next/font\`.` - - // Using different versions of @next/font and next, add message that it's possibly fixed by updating both - if (nextFontVersion !== nextVersion) { - message += `\n\nYou might be using incompatible version of \`@next/font\` (${nextFontVersion}) and \`next\` (${nextVersion}). Try updating both \`@next/font\` and \`next\`, if the error still persists it may be a bug.` - } - - message += `\n\n${err.stack}` - - return new SimpleWebpackError(file, message) + return new SimpleWebpackError( + file, + `An error occured in \`next/font\`.\n\n${err.stack}` + ) } } catch { return false diff --git a/packages/next/src/client/dev/error-overlay/format-webpack-messages.ts b/packages/next/src/client/dev/error-overlay/format-webpack-messages.ts index 9b9c0074812a1..ef641e9e39a47 100644 --- a/packages/next/src/client/dev/error-overlay/format-webpack-messages.ts +++ b/packages/next/src/client/dev/error-overlay/format-webpack-messages.ts @@ -184,7 +184,7 @@ function formatMessage( export default function formatWebpackMessages(json: any, verbose?: boolean) { const formattedErrors = json.errors.map((message: any) => { const isUnknownNextFontError = message.message.includes( - 'An error occured in `@next/font`.' + 'An error occured in `next/font`.' ) return formatMessage(message, isUnknownNextFontError || verbose) }) diff --git a/packages/next/src/export/index.ts b/packages/next/src/export/index.ts index 79a92a37dd876..f2e8477b4f006 100644 --- a/packages/next/src/export/index.ts +++ b/packages/next/src/export/index.ts @@ -404,9 +404,11 @@ export default async function exportApp( optimizeFonts: nextConfig.optimizeFonts as FontConfig, largePageDataBytes: nextConfig.experimental.largePageDataBytes, serverComponents: hasAppDir, - fontLoaderManifest: nextConfig.experimental.fontLoaders - ? require(join(distDir, 'server', `${FONT_LOADER_MANIFEST}.json`)) - : undefined, + fontLoaderManifest: require(join( + distDir, + 'server', + `${FONT_LOADER_MANIFEST}.json` + )), } const { serverRuntimeConfig, publicRuntimeConfig } = nextConfig diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 4cf2d193bf15a..24dfbd4e1f60a 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -376,9 +376,7 @@ export default abstract class Server { this.serverCSSManifest = serverComponents ? this.getServerCSSManifest() : undefined - this.fontLoaderManifest = this.nextConfig.experimental.fontLoaders - ? this.getFontLoaderManifest() - : undefined + this.fontLoaderManifest = this.getFontLoaderManifest() this.renderOpts = { poweredByHeader: this.nextConfig.poweredByHeader, diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index 79b47d70cadd0..4ad36f85d35b5 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -667,42 +667,6 @@ export const defaultConfig: NextConfig = { }, } -export function setFontLoaderDefaults(config: NextConfig) { - try { - // eslint-disable-next-line import/no-extraneous-dependencies - require('@next/font/package.json') - - const googleFontLoader = { - loader: '@next/font/google', - } - const localFontLoader = { - loader: '@next/font/local', - } - if (!config.experimental) { - config.experimental = {} - } - if (!config.experimental.fontLoaders) { - config.experimental.fontLoaders = [] - } - if ( - !config.experimental.fontLoaders.find( - ({ loader }: any) => loader === googleFontLoader.loader - ) - ) { - config.experimental.fontLoaders.push(googleFontLoader) - } - if ( - !config.experimental.fontLoaders.find( - ({ loader }: any) => loader === localFontLoader.loader - ) - ) { - config.experimental.fontLoaders.push(localFontLoader) - } - } catch {} -} - -setFontLoaderDefaults(defaultConfig) - export async function normalizeConfig(phase: string, config: any) { if (typeof config === 'function') { config = config(phase, { defaultConfig }) diff --git a/packages/next/src/server/config.ts b/packages/next/src/server/config.ts index 7d152df002e59..631740c0b16c1 100644 --- a/packages/next/src/server/config.ts +++ b/packages/next/src/server/config.ts @@ -95,40 +95,6 @@ export function setHttpClientAndAgentOptions( ) } -function setFontLoaderDefaults(config: NextConfigComplete) { - try { - // eslint-disable-next-line import/no-extraneous-dependencies - require('@next/font/package.json') - - const googleFontLoader = { - loader: '@next/font/google', - } - const localFontLoader = { - loader: '@next/font/local', - } - if (!config.experimental) { - config.experimental = {} - } - if (!config.experimental.fontLoaders) { - config.experimental.fontLoaders = [] - } - if ( - !config.experimental.fontLoaders.find( - ({ loader }: any) => loader === googleFontLoader.loader - ) - ) { - config.experimental.fontLoaders.push(googleFontLoader) - } - if ( - !config.experimental.fontLoaders.find( - ({ loader }: any) => loader === localFontLoader.loader - ) - ) { - config.experimental.fontLoaders.push(localFontLoader) - } - } catch {} -} - export function warnOptionHasBeenMovedOutOfExperimental( config: NextConfig, oldKey: string, @@ -973,7 +939,6 @@ export default async function loadConfig( }, silent ) as NextConfigComplete - setFontLoaderDefaults(completeConfig) return completeConfig } else { const configBaseName = basename(CONFIG_FILES[0], extname(CONFIG_FILES[0])) @@ -1004,6 +969,5 @@ export default async function loadConfig( ) as NextConfigComplete completeConfig.configFileName = configFileName setHttpClientAndAgentOptions(completeConfig, silent) - setFontLoaderDefaults(completeConfig) return completeConfig } diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts index df71efb5662d7..3208154429933 100644 --- a/packages/next/src/server/next-server.ts +++ b/packages/next/src/server/next-server.ts @@ -1017,7 +1017,6 @@ export default class NextNodeServer extends BaseServer { } protected getFontLoaderManifest() { - if (!this.nextConfig.experimental.fontLoaders) return undefined return require(join(this.distDir, 'server', `${FONT_LOADER_MANIFEST}.json`)) } diff --git a/packages/next/src/telemetry/events/build.ts b/packages/next/src/telemetry/events/build.ts index 1e020ef5d2fd2..d5afddbccdd2d 100644 --- a/packages/next/src/telemetry/events/build.ts +++ b/packages/next/src/telemetry/events/build.ts @@ -150,6 +150,8 @@ export type EventBuildFeatureUsage = { | 'next/dynamic' | '@next/font/google' | '@next/font/local' + | 'next/font/google' + | 'next/font/local' | 'experimental/optimizeCss' | 'experimental/nextScriptWorkers' | 'optimizeFonts' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d9c11b658408..b2cfa9434a411 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -511,6 +511,7 @@ importers: '@napi-rs/cli': 2.14.7 '@napi-rs/triples': 1.1.0 '@next/env': 13.1.7-canary.10 + '@next/font': 13.1.7-canary.10 '@next/polyfill-module': 13.1.7-canary.10 '@next/polyfill-nomodule': 13.1.7-canary.10 '@next/react-dev-overlay': 13.1.7-canary.10 @@ -685,6 +686,7 @@ importers: ws: 8.2.3 dependencies: '@next/env': link:../next-env + '@next/font': link:../font '@swc/helpers': 0.4.14 caniuse-lite: 1.0.30001406 fibers: 5.0.3 diff --git a/test/development/next-font/font-loader-in-document-error.test.ts b/test/development/next-font/font-loader-in-document-error.test.ts index fa384b37020b5..b76dcc9d47cc2 100644 --- a/test/development/next-font/font-loader-in-document-error.test.ts +++ b/test/development/next-font/font-loader-in-document-error.test.ts @@ -12,19 +12,16 @@ describe('font-loader-in-document-error', () => { files: { pages: new FileRef(join(__dirname, 'font-loader-in-document/pages')), }, - dependencies: { - '@next/font': 'canary', - }, }) }) afterAll(() => next.destroy()) - test('@next/font inside _document', async () => { + test('next/font inside _document', async () => { const browser = await webdriver(next.url, '/') expect(await hasRedbox(browser, true)).toBeTrue() expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` "pages/_document.js - \`@next/font\` error: + \`next/font\` error: Cannot be used within pages/_document.js." `) }) diff --git a/test/development/next-font/font-loader-in-document/pages/_document.js b/test/development/next-font/font-loader-in-document/pages/_document.js index 309ef3d66ad89..3f4422d3c3b3f 100644 --- a/test/development/next-font/font-loader-in-document/pages/_document.js +++ b/test/development/next-font/font-loader-in-document/pages/_document.js @@ -1,5 +1,5 @@ import { Html, Head, Main, NextScript } from 'next/document' -import { Abel } from '@next/font/google' +import { Abel } from 'next/font/google' // eslint-disable-next-line no-unused-vars const abel = Abel({ weight: '400' }) diff --git a/test/development/next-font/incompatible-versions.test.ts b/test/development/next-font/incompatible-versions.test.ts deleted file mode 100644 index 4f824b49a8479..0000000000000 --- a/test/development/next-font/incompatible-versions.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { createNext, FileRef } from 'e2e-utils' -import { NextInstance } from 'test/lib/next-modes/base' -import { join } from 'path' -import webdriver from 'next-webdriver' -import { getRedboxSource, hasRedbox } from 'next-test-utils' - -describe('incompatible-versions', () => { - let next: NextInstance - - beforeAll(async () => { - next = await createNext({ - files: { - pages: new FileRef(join(__dirname, 'incompatible-versions/pages')), - }, - // Make sure @next/font 13.0.0 is installed from npm - not the version from the monorepo - installCommand: 'pnpm add @next/font@13.0.0', - }) - }) - afterAll(() => next.destroy()) - - it('should warn that you might be using incompatible versions of next and @next/font on unknown error', async () => { - const browser = await webdriver(next.url, '/') - expect(await hasRedbox(browser, true)).toBeTrue() - - const errorMessage = await getRedboxSource(browser) - - // @next/font error info - expect(errorMessage).toInclude('pages/index.js') - expect(errorMessage).toInclude('An error occured in `@next/font`.') - expect(errorMessage).toInclude( - 'You might be using incompatible version of `@next/font` (13.0.0) and `next`' - ) - // Error - expect(errorMessage).toInclude( - 'TypeError: Cannot read properties of undefined' - ) - // Stacktrace - expect(errorMessage).toInclude('at fetchFonts') - }) -}) diff --git a/test/development/next-font/incompatible-versions/pages/fake-font.woff2 b/test/development/next-font/incompatible-versions/pages/fake-font.woff2 deleted file mode 100644 index 114b10d92cf02..0000000000000 --- a/test/development/next-font/incompatible-versions/pages/fake-font.woff2 +++ /dev/null @@ -1 +0,0 @@ -fake-font \ No newline at end of file diff --git a/test/development/next-font/incompatible-versions/pages/index.js b/test/development/next-font/incompatible-versions/pages/index.js deleted file mode 100644 index 1a226165f5ded..0000000000000 --- a/test/development/next-font/incompatible-versions/pages/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import localFont from '@next/font/local' - -const font = localFont({ src: './fake-font.woff2' }) - -export default function Index() { - return

Hello world!

-} diff --git a/test/development/next-font/validation-error.test.ts b/test/development/next-font/validation-error.test.ts index a749a65c72799..35b43189f1e7c 100644 --- a/test/development/next-font/validation-error.test.ts +++ b/test/development/next-font/validation-error.test.ts @@ -12,19 +12,16 @@ describe('validation-error', () => { files: { pages: new FileRef(join(__dirname, 'validation-error/pages')), }, - dependencies: { - '@next/font': 'canary', - }, }) }) afterAll(() => next.destroy()) - it('show a @next/font error when input is wrong', async () => { + it('show a next/font error when input is wrong', async () => { const browser = await webdriver(next.url, '/') expect(await hasRedbox(browser, true)).toBeTrue() expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` "pages/index.js - \`@next/font\` error: + \`next/font\` error: Missing required \`src\` property" `) }) diff --git a/test/development/next-font/validation-error/pages/index.js b/test/development/next-font/validation-error/pages/index.js index 8db5668af599c..18954160b1067 100644 --- a/test/development/next-font/validation-error/pages/index.js +++ b/test/development/next-font/validation-error/pages/index.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const font = localFont() diff --git a/test/e2e/app-dir/app-external/app-external.test.ts b/test/e2e/app-dir/app-external/app-external.test.ts index 748d09721237f..3074f6e0fabe7 100644 --- a/test/e2e/app-dir/app-external/app-external.test.ts +++ b/test/e2e/app-dir/app-external/app-external.test.ts @@ -19,7 +19,6 @@ createNextDescribe( { files: __dirname, dependencies: { - '@next/font': 'canary', react: 'latest', 'react-dom': 'latest', swr: '2.0.0-rc.0', @@ -143,7 +142,7 @@ createNextDescribe( ).toBe('rgb(255, 0, 0)') }) - it('should handle external @next/font', async () => { + it('should handle external next/font', async () => { const browser = await next.browser('/font') expect( diff --git a/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts b/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts index 5a31d967538f1..4833089fa6ed7 100644 --- a/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts +++ b/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts @@ -1,3 +1,3 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' export const myFont = localFont({ src: './my-font.woff2' }) diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/layout.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/layout.js new file mode 100644 index 0000000000000..c84b681925ebc --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/layout.js @@ -0,0 +1,10 @@ +export default function Root({ children }) { + return ( + + + Hello World + + {children} + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/page.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/page.js new file mode 100644 index 0000000000000..d861b42e63d1f --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/page.js @@ -0,0 +1,9 @@ +import styles from './styles.module.css' + +export default function Page() { + return ( + <> +

hello world

+ + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/styles.module.css b/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/styles.module.css new file mode 100644 index 0000000000000..c8cf8ee5c5b2c --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/styles.module.css @@ -0,0 +1,3 @@ +.p { + color: wheat; +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.js new file mode 100644 index 0000000000000..50be0f9f3c7a2 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.js @@ -0,0 +1,9 @@ +import localFont from '@next/font/local' + +const componentFont = localFont({ src: './comp.woff2', preload: false }) + +export default function Component() { + return ( +

{JSON.stringify(componentFont)}

+ ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.woff2 b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.woff2 new file mode 100644 index 0000000000000..c62250d2cbfe7 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.woff2 @@ -0,0 +1 @@ +comp-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/page.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/page.js new file mode 100644 index 0000000000000..2bd70262127ef --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/page.js @@ -0,0 +1,5 @@ +import Comp from './comp' + +export default function Page() { + return +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.js new file mode 100644 index 0000000000000..b4950beabc051 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.js @@ -0,0 +1,12 @@ +import localFont from '@next/font/local' + +const layoutFont = localFont({ src: './layout.woff2', preload: false }) + +export default function Layout({ children }) { + return ( + <> +

{JSON.stringify(layoutFont)}

+ {children} + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.woff2 b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.woff2 new file mode 100644 index 0000000000000..ac7fe0c6b67c0 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.woff2 @@ -0,0 +1 @@ +layout-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/page.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/page.js new file mode 100644 index 0000000000000..c17431379f962 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/page.js @@ -0,0 +1,3 @@ +export default function Page() { + return null +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.js new file mode 100644 index 0000000000000..d84badf1eec69 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.js @@ -0,0 +1,12 @@ +'use client' +import localFont from '@next/font/local' + +const pageFont = localFont({ src: './page.woff2', preload: false }) + +export default function Page() { + return ( + <> +

{JSON.stringify(pageFont)}

+ + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.woff2 b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.woff2 new file mode 100644 index 0000000000000..cb4ed2b24f421 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.woff2 @@ -0,0 +1 @@ +page-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/Comp.js b/test/e2e/app-dir/next-font/app-old/(preload)/Comp.js new file mode 100644 index 0000000000000..07a0875d88947 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/Comp.js @@ -0,0 +1,9 @@ +import { font3 } from '../../fonts' + +export default function Component() { + return ( +

+ {JSON.stringify(font3)} +

+ ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/client/Comp.js b/test/e2e/app-dir/next-font/app-old/(preload)/client/Comp.js new file mode 100644 index 0000000000000..2679352a57119 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/client/Comp.js @@ -0,0 +1,10 @@ +'use client' +import { font6 } from '../../../fonts' + +export default function Component() { + return ( +

+ {JSON.stringify(font6)} +

+ ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/client/layout.js b/test/e2e/app-dir/next-font/app-old/(preload)/client/layout.js new file mode 100644 index 0000000000000..83816c21a59b9 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/client/layout.js @@ -0,0 +1,13 @@ +'use client' +import { font4 } from '../../../fonts' + +export default function Root({ children }) { + return ( + <> +

+ {JSON.stringify(font4)} +

+ {children} + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/client/page.js b/test/e2e/app-dir/next-font/app-old/(preload)/client/page.js new file mode 100644 index 0000000000000..9606c96a020d9 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/client/page.js @@ -0,0 +1,14 @@ +'use client' +import Comp from './Comp' +import { font5 } from '../../../fonts' + +export default function HomePage() { + return ( + <> +

+ {JSON.stringify(font5)} +

+ + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout-font.woff2 b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout-font.woff2 new file mode 100644 index 0000000000000..ac7fe0c6b67c0 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout-font.woff2 @@ -0,0 +1 @@ +layout-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout.js b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout.js new file mode 100644 index 0000000000000..f7dbe5f5ea43a --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout.js @@ -0,0 +1,14 @@ +import localFont from '@next/font/local' + +const layoutFont = localFont({ src: './layout-font.woff2' }) + +export default function Layout({ children }) { + return ( + <> +

+ {JSON.stringify(layoutFont)} +

+ {children} + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/page.js b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/page.js new file mode 100644 index 0000000000000..338cd4773f66c --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/page.js @@ -0,0 +1,3 @@ +export default function HomePage() { + return

Only layout

+} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/layout.js b/test/e2e/app-dir/next-font/app-old/(preload)/layout.js new file mode 100644 index 0000000000000..82758ca4f485d --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/layout.js @@ -0,0 +1,17 @@ +import { font1 } from '../../fonts' + +export default function Root({ children }) { + return ( + + + Hello World + + +

+ {JSON.stringify(font1)} +

+ {children} + + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/layout.js b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/layout.js new file mode 100644 index 0000000000000..f927b11a8caad --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/layout.js @@ -0,0 +1,4 @@ +'use client' +export default function Layout({ children }) { + return children +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page-font.woff2 b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page-font.woff2 new file mode 100644 index 0000000000000..cb4ed2b24f421 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page-font.woff2 @@ -0,0 +1 @@ +page-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page.js b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page.js new file mode 100644 index 0000000000000..31df82aa277bb --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page.js @@ -0,0 +1,11 @@ +import localFont from '@next/font/local' + +const pageFont = localFont({ src: './page-font.woff2' }) + +export default function HomePage() { + return ( +

+ {JSON.stringify(pageFont)} +

+ ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/page.js b/test/e2e/app-dir/next-font/app-old/(preload)/page.js new file mode 100644 index 0000000000000..64e1768d9e36c --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/page.js @@ -0,0 +1,16 @@ +import Comp from './Comp' +import { font1, font2 } from '../../fonts' + +export default function HomePage() { + return ( + <> +

Hello world

+

+ {JSON.stringify(font2)} +

+ + + ) +} + +export const runtime = 'experimental-edge' diff --git a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-component/comp.js b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-component/comp.js index 50be0f9f3c7a2..b76c81ef9ba78 100644 --- a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-component/comp.js +++ b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-component/comp.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const componentFont = localFont({ src: './comp.woff2', preload: false }) diff --git a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-layout/layout.js b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-layout/layout.js index b4950beabc051..be8c9716e6c4f 100644 --- a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-layout/layout.js +++ b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-layout/layout.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const layoutFont = localFont({ src: './layout.woff2', preload: false }) diff --git a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-page/page.js b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-page/page.js index d84badf1eec69..cbd3d397105ac 100644 --- a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-page/page.js +++ b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-page/page.js @@ -1,5 +1,5 @@ 'use client' -import localFont from '@next/font/local' +import localFont from 'next/font/local' const pageFont = localFont({ src: './page.woff2', preload: false }) diff --git a/test/e2e/app-dir/next-font/app/(preload)/layout-with-fonts/layout.js b/test/e2e/app-dir/next-font/app/(preload)/layout-with-fonts/layout.js index f7dbe5f5ea43a..3ed0c60361884 100644 --- a/test/e2e/app-dir/next-font/app/(preload)/layout-with-fonts/layout.js +++ b/test/e2e/app-dir/next-font/app/(preload)/layout-with-fonts/layout.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const layoutFont = localFont({ src: './layout-font.woff2' }) diff --git a/test/e2e/app-dir/next-font/app/(preload)/page-with-fonts/page.js b/test/e2e/app-dir/next-font/app/(preload)/page-with-fonts/page.js index 31df82aa277bb..9a32b3881a07f 100644 --- a/test/e2e/app-dir/next-font/app/(preload)/page-with-fonts/page.js +++ b/test/e2e/app-dir/next-font/app/(preload)/page-with-fonts/page.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const pageFont = localFont({ src: './page-font.woff2' }) diff --git a/test/e2e/app-dir/next-font/fonts/index.js b/test/e2e/app-dir/next-font/fonts/index.js index d9d8746396cef..4bf7fbadcd96f 100644 --- a/test/e2e/app-dir/next-font/fonts/index.js +++ b/test/e2e/app-dir/next-font/fonts/index.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' export const font1 = localFont({ src: './font1.woff2', variable: '--font-1' }) export const font2 = localFont({ src: 'font2.woff2', variable: '--font-2' }) diff --git a/test/e2e/app-dir/next-font/next-font.test.ts b/test/e2e/app-dir/next-font/next-font.test.ts index 534a27077d69a..c1e6818ffc58a 100644 --- a/test/e2e/app-dir/next-font/next-font.test.ts +++ b/test/e2e/app-dir/next-font/next-font.test.ts @@ -1,5 +1,6 @@ -import { createNextDescribe } from 'e2e-utils' +import { createNextDescribe, FileRef } from 'e2e-utils' import { getRedboxSource, hasRedbox } from 'next-test-utils' +import { join } from 'path' const getAttrs = (elems: Cheerio) => Array.from(elems) @@ -8,394 +9,398 @@ const getAttrs = (elems: Cheerio) => // My machine behaves differently to CI .sort((a, b) => (a.href < b.href ? -1 : 1)) -createNextDescribe( - 'app dir next-font', - { - files: __dirname, - dependencies: { - '@next/font': 'canary', - react: 'latest', - 'react-dom': 'latest', +describe.each([['app'], ['app-old']])('%s', (fixture: string) => { + createNextDescribe( + 'app dir next-font', + { + files: { + app: new FileRef(join(__dirname, fixture)), + fonts: new FileRef(join(__dirname, 'fonts')), + 'next.config.js': new FileRef(join(__dirname, 'next.config.js')), + }, + dependencies: { + '@next/font': 'canary', + }, + skipDeployment: true, }, - skipDeployment: true, - }, - ({ next, isNextDev: isDev }) => { - describe('import values', () => { - it('should have correct values at /', async () => { - const $ = await next.render$('/') - - // layout - expect(JSON.parse($('#root-layout').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font1_.{6}'$/), - }, - }) - // page - expect(JSON.parse($('#root-page').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font2_.{6}'$/), - }, - }) - // Comp - expect(JSON.parse($('#root-comp').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font3_.{6}'$/), - fontStyle: 'italic', - fontWeight: 900, - }, - }) - }) - - it('should have correct values at /client', async () => { - const $ = await next.render$('/client') - - // root layout - expect(JSON.parse($('#root-layout').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font1_.{6}'$/), - }, - }) - - // layout - expect(JSON.parse($('#client-layout').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font4_.{6}'$/), - fontWeight: 100, - }, - }) - // page - expect(JSON.parse($('#client-page').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font5_.{6}'$/), - fontStyle: 'italic', - }, - }) - // Comp - expect(JSON.parse($('#client-comp').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font6_.{6}'$/), - }, - }) - }) - }) - - describe('computed styles', () => { - it('should have correct styles at /', async () => { - const browser = await next.browser('/') - - // layout - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontFamily' - ) - ).toMatch(/^__font1_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontStyle' - ) - ).toBe('normal') - - // page - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-page")).fontFamily' - ) - ).toMatch(/^__font2_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-page")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-page")).fontStyle' - ) - ).toBe('normal') - - // Comp - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-comp")).fontFamily' - ) - ).toMatch(/^__font3_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-comp")).fontWeight' - ) - ).toBe('900') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-comp")).fontStyle' - ) - ).toBe('italic') - }) - - it('should have correct styles at /client', async () => { - const browser = await next.browser('/client') - - // root layout - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontFamily' - ) - ).toMatch(/^__font1_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontStyle' - ) - ).toBe('normal') - - // layout - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-layout")).fontFamily' - ) - ).toMatch(/^__font4_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-layout")).fontWeight' - ) - ).toBe('100') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-layout")).fontStyle' - ) - ).toBe('normal') - - // page - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-page")).fontFamily' - ) - ).toMatch(/^__font5_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-page")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-page")).fontStyle' - ) - ).toBe('italic') - - // Comp - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-comp")).fontFamily' - ) - ).toMatch(/^__font6_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-comp")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-comp")).fontStyle' - ) - ).toBe('normal') - }) - }) - - if (!isDev) { - describe('preload', () => { - it('should preload correctly with server components', async () => { + ({ next, isNextDev: isDev }) => { + describe('import values', () => { + it('should have correct values at /', async () => { const $ = await next.render$('/') - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From root layout - expect(getAttrs($('link[as="font"]'))).toEqual([ - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/b2104791981359ae-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + // layout + expect(JSON.parse($('#root-layout').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font1_.{6}'$/), }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/b61859a50be14c53-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + }) + // page + expect(JSON.parse($('#root-page').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font2_.{6}'$/), }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + }) + // Comp + expect(JSON.parse($('#root-comp').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font3_.{6}'$/), + fontStyle: 'italic', + fontWeight: 900, }, - ]) + }) }) - it('should preload correctly with client components', async () => { + it('should have correct values at /client', async () => { const $ = await next.render$('/client') - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From root layout - expect(getAttrs($('link[as="font"]'))).toEqual([ - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e1053f04babc7571-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + // root layout + expect(JSON.parse($('#root-layout').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font1_.{6}'$/), }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + }) + + // layout + expect(JSON.parse($('#client-layout').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font4_.{6}'$/), + fontWeight: 100, }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/feab2c68f2a8e9a4-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + }) + // page + expect(JSON.parse($('#client-page').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font5_.{6}'$/), + fontStyle: 'italic', }, - ]) + }) + // Comp + expect(JSON.parse($('#client-comp').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font6_.{6}'$/), + }, + }) }) + }) - it('should preload correctly with layout using fonts', async () => { - const $ = await next.render$('/layout-with-fonts') - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From root layout - expect(getAttrs($('link[as="font"]'))).toEqual([ - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/75c5faeeb9c86969-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }, - ]) + describe('computed styles', () => { + it('should have correct styles at /', async () => { + const browser = await next.browser('/') + + // layout + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontFamily' + ) + ).toMatch(/^__font1_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontStyle' + ) + ).toBe('normal') + + // page + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-page")).fontFamily' + ) + ).toMatch(/^__font2_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-page")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-page")).fontStyle' + ) + ).toBe('normal') + + // Comp + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-comp")).fontFamily' + ) + ).toMatch(/^__font3_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-comp")).fontWeight' + ) + ).toBe('900') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-comp")).fontStyle' + ) + ).toBe('italic') }) - it('should preload correctly with page using fonts', async () => { - const $ = await next.render$('/page-with-fonts') - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From root layout - expect(getAttrs($('link[as="font"]'))).toEqual([ - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/568e4c6d8123c4d6-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }, - ]) + it('should have correct styles at /client', async () => { + const browser = await next.browser('/client') + + // root layout + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontFamily' + ) + ).toMatch(/^__font1_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontStyle' + ) + ).toBe('normal') + + // layout + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-layout")).fontFamily' + ) + ).toMatch(/^__font4_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-layout")).fontWeight' + ) + ).toBe('100') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-layout")).fontStyle' + ) + ).toBe('normal') + + // page + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-page")).fontFamily' + ) + ).toMatch(/^__font5_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-page")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-page")).fontStyle' + ) + ).toBe('italic') + + // Comp + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-comp")).fontFamily' + ) + ).toMatch(/^__font6_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-comp")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-comp")).fontStyle' + ) + ).toBe('normal') }) }) - describe('preconnect', () => { - it.each([['page'], ['layout'], ['component']])( - 'should add preconnect when preloading is disabled in %s', - async (type: string) => { - const $ = await next.render$(`/preconnect-${type}`) + if (!isDev) { + describe('preload', () => { + it('should preload correctly with server components', async () => { + const $ = await next.render$('/') // Preconnect - expect($('link[rel="preconnect"]').length).toBe(1) - expect($('link[rel="preconnect"]').get(0).attribs).toEqual({ - crossorigin: 'anonymous', - href: '/', - rel: 'preconnect', - 'data-next-font': 'size-adjust', - }) - // Preload - expect($('link[as="font"]').length).toBe(0) - } - ) + expect($('link[rel="preconnect"]').length).toBe(0) + + // From root layout + expect(getAttrs($('link[as="font"]'))).toEqual([ + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/b2104791981359ae-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/b61859a50be14c53-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + ]) + }) + + it('should preload correctly with client components', async () => { + const $ = await next.render$('/client') - it('should not preconnect when css is used but no fonts', async () => { - const $ = await next.render$('/no-preconnect') + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From root layout + expect(getAttrs($('link[as="font"]'))).toEqual([ + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e1053f04babc7571-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/feab2c68f2a8e9a4-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + ]) + }) + + it('should preload correctly with layout using fonts', async () => { + const $ = await next.render$('/layout-with-fonts') - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - // Preload - expect(getAttrs($('link[as="font"]'))).toEqual([]) - }) - }) - } + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From root layout + expect(getAttrs($('link[as="font"]'))).toEqual([ + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/75c5faeeb9c86969-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + ]) + }) + + it('should preload correctly with page using fonts', async () => { + const $ = await next.render$('/page-with-fonts') - if (isDev) { - describe('Dev errors', () => { - it('should recover on font loader error', async () => { - const browser = await next.browser('/') - const font1Content = await next.readFile('fonts/index.js') + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From root layout + expect(getAttrs($('link[as="font"]'))).toEqual([ + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/568e4c6d8123c4d6-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + ]) + }) + }) - // Break file - await next.patchFile( - 'fonts/index.js', - font1Content.replace('./font1.woff2', './does-not-exist.woff2') - ) - expect(await hasRedbox(browser, true)).toBeTrue() - expect(await getRedboxSource(browser)).toInclude( - "Can't resolve './does-not-exist.woff2'" + describe('preconnect', () => { + it.each([['page'], ['layout'], ['component']])( + 'should add preconnect when preloading is disabled in %s', + async (type: string) => { + const $ = await next.render$(`/preconnect-${type}`) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(1) + expect($('link[rel="preconnect"]').get(0).attribs).toEqual({ + crossorigin: 'anonymous', + href: '/', + rel: 'preconnect', + 'data-next-font': 'size-adjust', + }) + // Preload + expect($('link[as="font"]').length).toBe(0) + } ) - // Fix file - await next.patchFile('fonts/index.js', font1Content) - await browser.waitForElementByCss('#root-page') + it('should not preconnect when css is used but no fonts', async () => { + const $ = await next.render$('/no-preconnect') + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + // Preload + expect(getAttrs($('link[as="font"]'))).toEqual([]) + }) }) - }) + } + + if (isDev) { + describe('Dev errors', () => { + it('should recover on font loader error', async () => { + const browser = await next.browser('/') + const font1Content = await next.readFile('fonts/index.js') + + // Break file + await next.patchFile( + 'fonts/index.js', + font1Content.replace('./font1.woff2', './does-not-exist.woff2') + ) + expect(await hasRedbox(browser, true)).toBeTrue() + expect(await getRedboxSource(browser)).toInclude( + "Can't resolve './does-not-exist.woff2'" + ) + + // Fix file + await next.patchFile('fonts/index.js', font1Content) + await browser.waitForElementByCss('#root-page') + }) + }) + } } - } -) + ) +}) diff --git a/test/e2e/next-font/app-old/components/CompWithFonts.js b/test/e2e/next-font/app-old/components/CompWithFonts.js new file mode 100644 index 0000000000000..104526effb17d --- /dev/null +++ b/test/e2e/next-font/app-old/components/CompWithFonts.js @@ -0,0 +1,22 @@ +import { Inter, Roboto } from '@next/font/google' +const inter = Inter({ weight: '900', display: 'swap', preload: false }) +const roboto = Roboto({ + weight: '100', + style: 'italic', + display: 'swap', + preload: true, + subsets: ['vietnamese'], +}) + +export default function Component() { + return ( + <> +
+ {JSON.stringify(inter)} +
+
+ {JSON.stringify(roboto)} +
+ + ) +} diff --git a/test/e2e/next-font/app-old/fonts/my-font.woff2 b/test/e2e/next-font/app-old/fonts/my-font.woff2 new file mode 100644 index 0000000000000..a6b3c3a9d69fa Binary files /dev/null and b/test/e2e/next-font/app-old/fonts/my-font.woff2 differ diff --git a/test/e2e/next-font/app-old/fonts/my-other-font.woff2 b/test/e2e/next-font/app-old/fonts/my-other-font.woff2 new file mode 100644 index 0000000000000..ac8adf10ed942 Binary files /dev/null and b/test/e2e/next-font/app-old/fonts/my-other-font.woff2 differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 new file mode 100644 index 0000000000000..1f22fa96cdfe5 Binary files /dev/null and b/test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-100.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-100.woff2 new file mode 100644 index 0000000000000..921b2bb6a9de1 Binary files /dev/null and b/test/e2e/next-font/app-old/fonts/roboto/roboto-100.woff2 differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-400-italic.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-400-italic.woff2 new file mode 100644 index 0000000000000..fbe1a26c9c4c2 Binary files /dev/null and b/test/e2e/next-font/app-old/fonts/roboto/roboto-400-italic.woff2 differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 new file mode 100644 index 0000000000000..b65a361a2e44d Binary files /dev/null and b/test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 new file mode 100644 index 0000000000000..741d0638b1db4 Binary files /dev/null and b/test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-900.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-900.woff2 new file mode 100644 index 0000000000000..4b7cb645bb87f Binary files /dev/null and b/test/e2e/next-font/app-old/fonts/roboto/roboto-900.woff2 differ diff --git a/test/production/next-font/telemetry/next.config.js b/test/e2e/next-font/app-old/next.config.js similarity index 75% rename from test/production/next-font/telemetry/next.config.js rename to test/e2e/next-font/app-old/next.config.js index 6a94ea94ad864..3f4a776b7f409 100644 --- a/test/production/next-font/telemetry/next.config.js +++ b/test/e2e/next-font/app-old/next.config.js @@ -5,9 +5,6 @@ module.exports = { loader: '@next/font/google', options: { subsets: ['latin'] }, }, - { - loader: '@next/font/local', - }, ], }, } diff --git a/test/e2e/next-font/app-old/pages/_app.js b/test/e2e/next-font/app-old/pages/_app.js new file mode 100644 index 0000000000000..87fd0d1ed9b67 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/_app.js @@ -0,0 +1,16 @@ +import { Open_Sans } from '@next/font/google' +const openSans = Open_Sans({ variable: '--open-sans' }) + +function MyApp({ Component, pageProps }) { + return ( + <> +
+ {JSON.stringify(openSans)} +
+ + + ) +} + +export { openSans } +export default MyApp diff --git a/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js b/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js new file mode 100644 index 0000000000000..62ac7af99f5c1 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js @@ -0,0 +1,7 @@ +import { Single_Day } from '@next/font/google' + +const singleDay = Single_Day({ weight: '400' }) + +export default function FontWithoutPreloadableSubsets() { + return

{JSON.stringify(singleDay)}

+} diff --git a/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js b/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js new file mode 100644 index 0000000000000..bb78339d8d405 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js @@ -0,0 +1,11 @@ +import { Nabla } from '@next/font/google' + +const nabla = Nabla() + +export default function VariableFontWithoutWeightRange() { + return ( +

+ {JSON.stringify(nabla)} +

+ ) +} diff --git a/test/e2e/next-font/app-old/pages/variables.js b/test/e2e/next-font/app-old/pages/variables.js new file mode 100644 index 0000000000000..e4b19c560a37a --- /dev/null +++ b/test/e2e/next-font/app-old/pages/variables.js @@ -0,0 +1,67 @@ +import { Fira_Code, Roboto } from '@next/font/google' +import localFont from '@next/font/local' + +const firaCode = Fira_Code({ variable: '--fira-code' }) +const roboto = Roboto({ + weight: '100', + style: 'italic', + display: 'swap', + preload: true, + variable: '--roboto-100-italic', +}) +const myFont = localFont({ + src: '../fonts/my-font.woff2', + preload: false, + variable: '--my-font', +}) + +export default function WithFonts() { + return ( + <> + {/* Fira Code Variable */} +
+ With variables +
+
+ Without variables +
+ + {/* Roboto 100 Italic */} +
+ With variables +
+
+ Without variables +
+ + {/* Local font */} +
+ With variables +
+
+ Without variables +
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/with-fallback.js b/test/e2e/next-font/app-old/pages/with-fallback.js new file mode 100644 index 0000000000000..eeebf33ccecd6 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/with-fallback.js @@ -0,0 +1,36 @@ +import localFont from '@next/font/local' +import { Open_Sans } from '@next/font/google' +const openSans = Open_Sans({ + fallback: ['system-ui', 'Arial'], + variable: '--open-sans', + adjustFontFallback: false, +}) + +const myFont = localFont({ + fallback: ['system-ui', 'Arial'], + src: '../fonts/my-font.woff2', + adjustFontFallback: false, +}) + +export default function WithFonts() { + return ( + <> +
+ {JSON.stringify(openSans)} +
+
+ {JSON.stringify(openSans)} +
+
+ {JSON.stringify(openSans)} +
+
+ {JSON.stringify(myFont)} +
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/with-fonts.js b/test/e2e/next-font/app-old/pages/with-fonts.js new file mode 100644 index 0000000000000..13dbe3e46bf9f --- /dev/null +++ b/test/e2e/next-font/app-old/pages/with-fonts.js @@ -0,0 +1,14 @@ +import CompWithFonts from '../components/CompWithFonts' +import { openSans } from './_app' + +export default function WithFonts() { + return ( + <> + +
+ {JSON.stringify(openSans)} +
+
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/with-google-fonts.js b/test/e2e/next-font/app-old/pages/with-google-fonts.js new file mode 100644 index 0000000000000..acf3309a9ebfb --- /dev/null +++ b/test/e2e/next-font/app-old/pages/with-google-fonts.js @@ -0,0 +1,40 @@ +import { Fraunces, Indie_Flower, Roboto } from '@next/font/google' + +const indieFlower = Indie_Flower({ weight: '400', preload: false }) +const fraunces = Fraunces({ weight: '400', preload: false }) + +const robotoMultiple = Roboto({ + weight: ['900', '100'], + style: ['normal', 'italic'], +}) +const frauncesMultiple = Fraunces({ + style: ['italic', 'normal'], + axes: ['SOFT', 'WONK', 'opsz'], +}) + +const frauncesMultipleWeights = Fraunces({ weight: ['100', '400', '900'] }) + +export default function WithFonts() { + return ( + <> +
+ {JSON.stringify(indieFlower)} +
+
+ {JSON.stringify(fraunces)} +
+
+ {JSON.stringify(robotoMultiple)} +
+
+ {JSON.stringify(frauncesMultiple)} +
+
+ {JSON.stringify(frauncesMultipleWeights)} +
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/with-local-fonts.js b/test/e2e/next-font/app-old/pages/with-local-fonts.js new file mode 100644 index 0000000000000..37f218859d243 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/with-local-fonts.js @@ -0,0 +1,153 @@ +import localFont from '@next/font/local' + +const myFont1 = localFont({ + src: '../fonts/my-font.woff2', + style: 'italic', + weight: '100', + fallback: ['system-ui'], + adjustFontFallback: 'Times New Roman', +}) +const myFont2 = localFont({ + src: '../fonts/my-other-font.woff2', + preload: false, + variable: '--my-font', +}) + +const roboto = localFont({ + preload: false, + src: [ + { + path: '../fonts/roboto/roboto-100-italic.woff2', + weight: '100', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '100', + style: 'normal', + }, + { + path: '../fonts/my-font.woff2', + weight: '400', + style: 'italic', + }, + { + path: '../fonts/roboto/roboto-400.woff2', + weight: '400', + }, + { + path: '../fonts/my-font.woff2', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '900', + style: 'normal', + }, + ], +}) + +const robotoVar1 = localFont({ + preload: false, + src: [ + { + path: '../fonts/roboto/roboto-400.woff2', + weight: '100 300', + style: 'normal', + }, + { + path: '../fonts/my-font.woff2', + weight: '100 300', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '500 900', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '500 900', + style: 'normal', + }, + ], +}) + +const robotoVar2 = localFont({ + preload: false, + src: [ + { + path: '../fonts/roboto/roboto-900.woff2', + weight: '100 900', + style: 'italic', + }, + { + path: '../fonts/roboto/roboto-400.woff2', + weight: '100 900', + style: 'normal', + }, + { + path: '../fonts/my-font.woff2', + weight: '300 399', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '401 500', + style: 'normal', + }, + ], +}) + +const robotoWithPreload = localFont({ + src: [ + { + path: '../fonts/roboto/roboto-100.woff2', + weight: '100', + style: 'normal', + }, + { + path: '../fonts/roboto/roboto-900-italic.woff2', + weight: '900', + style: 'italic', + }, + { + path: '../fonts/roboto/roboto-100.woff2', + weight: '100', + style: 'normal', + }, + { + path: '../fonts/roboto/roboto-100-italic.woff2', + weight: '900', + style: 'italic', + }, + ], +}) + +export default function WithFonts() { + return ( + <> +
+ {JSON.stringify(myFont1)} +
+
+ {JSON.stringify(myFont2)} +
+
+ {JSON.stringify(roboto)} +
+
+ {JSON.stringify(robotoVar1)} +
+
+ {JSON.stringify(robotoVar2)} +
+
+ {JSON.stringify(robotoWithPreload)} +
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/without-fonts.js b/test/e2e/next-font/app-old/pages/without-fonts.js new file mode 100644 index 0000000000000..0f649722e671d --- /dev/null +++ b/test/e2e/next-font/app-old/pages/without-fonts.js @@ -0,0 +1,3 @@ +export default function WithoutFonts() { + return

Hello world

+} diff --git a/test/e2e/next-font/app/components/CompWithFonts.js b/test/e2e/next-font/app/components/CompWithFonts.js index 104526effb17d..50a98f1cff35a 100644 --- a/test/e2e/next-font/app/components/CompWithFonts.js +++ b/test/e2e/next-font/app/components/CompWithFonts.js @@ -1,4 +1,4 @@ -import { Inter, Roboto } from '@next/font/google' +import { Inter, Roboto } from 'next/font/google' const inter = Inter({ weight: '900', display: 'swap', preload: false }) const roboto = Roboto({ weight: '100', diff --git a/test/e2e/next-font/app/next.config.js b/test/e2e/next-font/app/next.config.js index 6a94ea94ad864..51b19fbc18002 100644 --- a/test/e2e/next-font/app/next.config.js +++ b/test/e2e/next-font/app/next.config.js @@ -2,12 +2,9 @@ module.exports = { experimental: { fontLoaders: [ { - loader: '@next/font/google', + loader: 'next/font/google', options: { subsets: ['latin'] }, }, - { - loader: '@next/font/local', - }, ], }, } diff --git a/test/e2e/next-font/app/pages/_app.js b/test/e2e/next-font/app/pages/_app.js index 87fd0d1ed9b67..5d957229dc906 100644 --- a/test/e2e/next-font/app/pages/_app.js +++ b/test/e2e/next-font/app/pages/_app.js @@ -1,4 +1,4 @@ -import { Open_Sans } from '@next/font/google' +import { Open_Sans } from 'next/font/google' const openSans = Open_Sans({ variable: '--open-sans' }) function MyApp({ Component, pageProps }) { diff --git a/test/e2e/next-font/app/pages/font-without-preloadable-subsets.js b/test/e2e/next-font/app/pages/font-without-preloadable-subsets.js index 62ac7af99f5c1..b79674311253d 100644 --- a/test/e2e/next-font/app/pages/font-without-preloadable-subsets.js +++ b/test/e2e/next-font/app/pages/font-without-preloadable-subsets.js @@ -1,4 +1,4 @@ -import { Single_Day } from '@next/font/google' +import { Single_Day } from 'next/font/google' const singleDay = Single_Day({ weight: '400' }) diff --git a/test/e2e/next-font/app/pages/variable-font-without-weight-range.js b/test/e2e/next-font/app/pages/variable-font-without-weight-range.js index bb78339d8d405..64ee22e9b955f 100644 --- a/test/e2e/next-font/app/pages/variable-font-without-weight-range.js +++ b/test/e2e/next-font/app/pages/variable-font-without-weight-range.js @@ -1,4 +1,4 @@ -import { Nabla } from '@next/font/google' +import { Nabla } from 'next/font/google' const nabla = Nabla() diff --git a/test/e2e/next-font/app/pages/variables.js b/test/e2e/next-font/app/pages/variables.js index e4b19c560a37a..e03b2be3856db 100644 --- a/test/e2e/next-font/app/pages/variables.js +++ b/test/e2e/next-font/app/pages/variables.js @@ -1,5 +1,5 @@ -import { Fira_Code, Roboto } from '@next/font/google' -import localFont from '@next/font/local' +import { Fira_Code, Roboto } from 'next/font/google' +import localFont from 'next/font/local' const firaCode = Fira_Code({ variable: '--fira-code' }) const roboto = Roboto({ diff --git a/test/e2e/next-font/app/pages/with-fallback.js b/test/e2e/next-font/app/pages/with-fallback.js index eeebf33ccecd6..9338f23d27278 100644 --- a/test/e2e/next-font/app/pages/with-fallback.js +++ b/test/e2e/next-font/app/pages/with-fallback.js @@ -1,5 +1,5 @@ -import localFont from '@next/font/local' -import { Open_Sans } from '@next/font/google' +import localFont from 'next/font/local' +import { Open_Sans } from 'next/font/google' const openSans = Open_Sans({ fallback: ['system-ui', 'Arial'], variable: '--open-sans', diff --git a/test/e2e/next-font/app/pages/with-google-fonts.js b/test/e2e/next-font/app/pages/with-google-fonts.js index acf3309a9ebfb..1332c4a761a65 100644 --- a/test/e2e/next-font/app/pages/with-google-fonts.js +++ b/test/e2e/next-font/app/pages/with-google-fonts.js @@ -1,4 +1,4 @@ -import { Fraunces, Indie_Flower, Roboto } from '@next/font/google' +import { Fraunces, Indie_Flower, Roboto } from 'next/font/google' const indieFlower = Indie_Flower({ weight: '400', preload: false }) const fraunces = Fraunces({ weight: '400', preload: false }) diff --git a/test/e2e/next-font/app/pages/with-local-fonts.js b/test/e2e/next-font/app/pages/with-local-fonts.js index 37f218859d243..645253ea14a8d 100644 --- a/test/e2e/next-font/app/pages/with-local-fonts.js +++ b/test/e2e/next-font/app/pages/with-local-fonts.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const myFont1 = localFont({ src: '../fonts/my-font.woff2', diff --git a/test/e2e/next-font/basepath.test.ts b/test/e2e/next-font/basepath.test.ts index 5573ba99ba9fd..47964a90ab167 100644 --- a/test/e2e/next-font/basepath.test.ts +++ b/test/e2e/next-font/basepath.test.ts @@ -8,7 +8,7 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font/google basepath', () => { +describe('next/font/google basepath', () => { let next: NextInstance if ((global as any).isNextDeploy) { @@ -24,9 +24,6 @@ describe('@next/font/google basepath', () => { join(__dirname, 'basepath/next.config.js') ), }, - dependencies: { - '@next/font': 'canary', - }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, diff --git a/test/e2e/next-font/basepath/next.config.js b/test/e2e/next-font/basepath/next.config.js index 1be9432475a2c..4f15a0286194e 100644 --- a/test/e2e/next-font/basepath/next.config.js +++ b/test/e2e/next-font/basepath/next.config.js @@ -1,10 +1,3 @@ module.exports = { basePath: '/dashboard', - experimental: { - fontLoaders: [ - { - loader: '@next/font/local', - }, - ], - }, } diff --git a/test/e2e/next-font/basepath/pages/index.js b/test/e2e/next-font/basepath/pages/index.js index 3d0967e56b323..78c7d10857616 100644 --- a/test/e2e/next-font/basepath/pages/index.js +++ b/test/e2e/next-font/basepath/pages/index.js @@ -1,4 +1,4 @@ -import { Open_Sans } from '@next/font/google' +import { Open_Sans } from 'next/font/google' const openSans = Open_Sans({ subsets: ['latin'] }) export default function Inter() { diff --git a/test/e2e/next-font/google-fetch-error.test.ts b/test/e2e/next-font/google-fetch-error.test.ts index 582b4bf87a790..435da8570a572 100644 --- a/test/e2e/next-font/google-fetch-error.test.ts +++ b/test/e2e/next-font/google-fetch-error.test.ts @@ -7,7 +7,7 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font/google fetch error', () => { +describe('next/font/google fetch error', () => { const isDev = (global as any).isNextDev let next: NextInstance @@ -20,12 +20,6 @@ describe('@next/font/google fetch error', () => { next = await createNext({ files: { pages: new FileRef(join(__dirname, 'google-fetch-error/pages')), - 'next.config.js': new FileRef( - join(__dirname, 'google-fetch-error/next.config.js') - ), - }, - dependencies: { - '@next/font': 'canary', }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, diff --git a/test/e2e/next-font/google-fetch-error/next.config.js b/test/e2e/next-font/google-fetch-error/next.config.js deleted file mode 100644 index 16e3ab6f546a2..0000000000000 --- a/test/e2e/next-font/google-fetch-error/next.config.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - experimental: { - fontLoaders: [ - { - loader: '@next/font/google', - }, - ], - }, -} diff --git a/test/e2e/next-font/google-fetch-error/pages/index.js b/test/e2e/next-font/google-fetch-error/pages/index.js index 229c3d6631c43..2653808616d3e 100644 --- a/test/e2e/next-font/google-fetch-error/pages/index.js +++ b/test/e2e/next-font/google-fetch-error/pages/index.js @@ -1,4 +1,4 @@ -import { Inter } from '@next/font/google' +import { Inter } from 'next/font/google' const inter = Inter({ weight: '400', subsets: ['latin'] }) export default function Page() { diff --git a/test/e2e/next-font/index.test.ts b/test/e2e/next-font/index.test.ts index 986a9ba443f10..e78db2e229a38 100644 --- a/test/e2e/next-font/index.test.ts +++ b/test/e2e/next-font/index.test.ts @@ -9,601 +9,605 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font/google', () => { - let next: NextInstance - - if ((global as any).isNextDeploy) { - it('should skip next deploy for now', () => {}) - return - } - - beforeAll(async () => { - next = await createNext({ - files: { - pages: new FileRef(join(__dirname, 'app/pages')), - components: new FileRef(join(__dirname, 'app/components')), - fonts: new FileRef(join(__dirname, 'app/fonts')), - 'next.config.js': new FileRef(join(__dirname, 'app/next.config.js')), - }, - dependencies: { - '@next/font': 'canary', - }, - env: { - NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, - }, - }) - }) - afterAll(() => next.destroy()) - - describe('import values', () => { - test('page with font', async () => { - const html = await renderViaHTTP(next.url, '/with-fonts') - const $ = cheerio.load(html) - - // _app.js - expect(JSON.parse($('#app-open-sans').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ +describe('next/font', () => { + describe.each([['app'], ['app-old']])('%s', (fixture: string) => { + let next: NextInstance + + if ((global as any).isNextDeploy) { + it('should skip next deploy for now', () => {}) + return + } + + beforeAll(async () => { + next = await createNext({ + files: { + pages: new FileRef(join(__dirname, `${fixture}/pages`)), + components: new FileRef(join(__dirname, `${fixture}/components`)), + fonts: new FileRef(join(__dirname, `${fixture}/fonts`)), + 'next.config.js': new FileRef( + join(__dirname, `${fixture}/next.config.js`) ), - fontStyle: 'normal', }, - }) - - // with-fonts.js - expect(JSON.parse($('#with-fonts-open-sans').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ - ), - fontStyle: 'normal', + dependencies: { + '@next/font': 'canary', }, - }) - - // CompWithFonts.js - expect(JSON.parse($('#comp-with-fonts-inter').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__Inter_.{6}', '__Inter_Fallback_.{6}'$/ - ), - fontWeight: 900, - fontStyle: 'normal', - }, - }) - expect(JSON.parse($('#comp-with-fonts-roboto').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__Roboto_.{6}', '__Roboto_Fallback_.{6}'$/ - ), - fontStyle: 'italic', - fontWeight: 100, + env: { + NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, }) }) - - test('page with local fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-local-fonts') - const $ = cheerio.load(html) - - // _app.js - expect(JSON.parse($('#app-open-sans').text())).toEqual({ - className: expect.stringMatching(/__className_.{6}/), - variable: expect.stringMatching(/__variable_.{6}/), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ - ), - fontStyle: 'normal', - }, + afterAll(() => next.destroy()) + + describe('import values', () => { + test('page with font', async () => { + const html = await renderViaHTTP(next.url, '/with-fonts') + const $ = cheerio.load(html) + + // _app.js + expect(JSON.parse($('#app-open-sans').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + + // with-fonts.js + expect(JSON.parse($('#with-fonts-open-sans').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + + // CompWithFonts.js + expect(JSON.parse($('#comp-with-fonts-inter').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__Inter_.{6}', '__Inter_Fallback_.{6}'$/ + ), + fontWeight: 900, + fontStyle: 'normal', + }, + }) + expect(JSON.parse($('#comp-with-fonts-roboto').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__Roboto_.{6}', '__Roboto_Fallback_.{6}'$/ + ), + fontStyle: 'italic', + fontWeight: 100, + }, + }) }) - // with-local-fonts.js - expect(JSON.parse($('#first-local-font').text())).toEqual({ - className: expect.stringMatching(/__className_.{6}/), - style: { - fontFamily: expect.stringMatching( - /^'__myFont1_.{6}', '__myFont1_Fallback_.{6}', system-ui$/ - ), - fontStyle: 'italic', - fontWeight: 100, - }, + test('page with local fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-local-fonts') + const $ = cheerio.load(html) + + // _app.js + expect(JSON.parse($('#app-open-sans').text())).toEqual({ + className: expect.stringMatching(/__className_.{6}/), + variable: expect.stringMatching(/__variable_.{6}/), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + + // with-local-fonts.js + expect(JSON.parse($('#first-local-font').text())).toEqual({ + className: expect.stringMatching(/__className_.{6}/), + style: { + fontFamily: expect.stringMatching( + /^'__myFont1_.{6}', '__myFont1_Fallback_.{6}', system-ui$/ + ), + fontStyle: 'italic', + fontWeight: 100, + }, + }) + expect(JSON.parse($('#second-local-font').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__myFont2_.{6}', '__myFont2_Fallback_.{6}'$/ + ), + }, + }) }) - expect(JSON.parse($('#second-local-font').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__myFont2_.{6}', '__myFont2_Fallback_.{6}'$/ - ), - }, - }) - }) - - test('Variable font without weight range', async () => { - const html = await renderViaHTTP( - next.url, - '/variable-font-without-weight-range' - ) - const $ = cheerio.load(html) - - expect(JSON.parse($('#nabla').text())).toEqual({ - className: expect.stringMatching(/__className_.{6}/), - style: { - fontFamily: expect.stringMatching(/^'__Nabla_.{6}'$/), - fontStyle: 'normal', - }, - }) - }) - }) - describe('computed styles', () => { - test('page with fonts', async () => { - const browser = await webdriver(next.url, '/with-fonts') - - // _app.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontWeight' + test('Variable font without weight range', async () => { + const html = await renderViaHTTP( + next.url, + '/variable-font-without-weight-range' ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontStyle' - ) - ).toBe('normal') + const $ = cheerio.load(html) - // with-fonts.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontStyle' - ) - ).toBe('normal') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontStyle' - ) - ).toBe('normal') - - // CompWithFonts.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontFamily' - ) - ).toMatch(/^__Inter_.{6}, __Inter_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontWeight' - ) - ).toBe('900') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontStyle' - ) - ).toBe('normal') - - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontFamily' - ) - ).toMatch(/^__Roboto_.{6}, __Roboto_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontWeight' - ) - ).toBe('100') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontStyle' - ) - ).toBe('italic') - }) - - test('page using variables', async () => { - const browser = await webdriver(next.url, '/variables') - - // Fira Code Variable - const firaCodeRegex = /^__Fira_Code_.{6}, __Fira_Code_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-fira-code")).fontFamily' - ) - ).toMatch(firaCodeRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-fira-code")).fontFamily' - ) - ).not.toMatch(firaCodeRegex) - - // Roboto 100 Italic - const roboto100ItalicRegex = /^__Roboto_.{6}, __Roboto_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-roboto-100-italic")).fontFamily' - ) - ).toMatch(roboto100ItalicRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-roboto-100-italic")).fontFamily' - ) - ).not.toMatch(roboto100ItalicRegex) - - // Local font - const localFontRegex = /^__myFont_.{6}, __myFont_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-local-font")).fontFamily' - ) - ).toMatch(localFontRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-local-font")).fontFamily' - ) - ).not.toMatch(localFontRegex) - }) - - test('page using fallback fonts', async () => { - const browser = await webdriver(next.url, '/with-fallback') - - // .className - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-classname")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - - // .style - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-style")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - - // .variable - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-variable")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - }) - }) - - describe('preload', () => { - test('page with fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - expect($('link[as="font"]').length).toBe(2) - // From /_app - expect($('link[as="font"]').get(0).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }) - expect($('link[as="font"]').get(1).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/675c25f648fd6a30-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + expect(JSON.parse($('#nabla').text())).toEqual({ + className: expect.stringMatching(/__className_.{6}/), + style: { + fontFamily: expect.stringMatching(/^'__Nabla_.{6}'$/), + fontStyle: 'normal', + }, + }) }) }) - test('page without fonts', async () => { - const html = await renderViaHTTP(next.url, '/without-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From _app - expect($('link[as="font"]').length).toBe(1) - expect($('link[as="font"]').get(0).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + describe('computed styles', () => { + test('page with fonts', async () => { + const browser = await webdriver(next.url, '/with-fonts') + + // _app.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontStyle' + ) + ).toBe('normal') + + // with-fonts.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontStyle' + ) + ).toBe('normal') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontStyle' + ) + ).toBe('normal') + + // CompWithFonts.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontFamily' + ) + ).toMatch(/^__Inter_.{6}, __Inter_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontWeight' + ) + ).toBe('900') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontStyle' + ) + ).toBe('normal') + + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontFamily' + ) + ).toMatch(/^__Roboto_.{6}, __Roboto_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontWeight' + ) + ).toBe('100') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontStyle' + ) + ).toBe('italic') }) - }) - test('page with local fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-local-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // Preload - expect($('link[as="font"]').length).toBe(5) - expect( - Array.from($('link[as="font"]')) - .map((el) => el.attribs.href) - .sort() - ).toEqual([ - '/_next/static/media/02205c9944024f15-s.p.woff2', - '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - '/_next/static/media/1deec1af325840fd-s.p.woff2', - '/_next/static/media/ab6fdae82d1a8d92-s.p.woff2', - '/_next/static/media/d55edb6f37902ebf-s.p.woff2', - ]) - }) - - test('google fonts with multiple weights/styles', async () => { - const html = await renderViaHTTP(next.url, '/with-google-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // Preload - expect($('link[as="font"]').length).toBe(8) - - expect( - Array.from($('link[as="font"]')) - .map((el) => el.attribs.href) - .sort() - ).toEqual([ - '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - '/_next/static/media/4f3dcdf40b3ca86d-s.p.woff2', - '/_next/static/media/560a6db6ac485cb1-s.p.woff2', - '/_next/static/media/686d1702f12625fe-s.p.woff2', - '/_next/static/media/86d92167ff02c708-s.p.woff2', - '/_next/static/media/9ac01b894b856187-s.p.woff2', - '/_next/static/media/c9baea324111137d-s.p.woff2', - '/_next/static/media/fb68b4558e2a718e-s.p.woff2', - ]) - }) - - test('font without preloadable subsets', async () => { - const html = await renderViaHTTP( - next.url, - '/font-without-preloadable-subsets' - ) - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From _app - expect($('link[as="font"]').length).toBe(1) - expect($('link[as="font"]').get(0).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }) - }) - - test('font without size adjust', async () => { - const html = await renderViaHTTP(next.url, '/with-fallback') - const $ = cheerio.load(html) - - expect($('link[as="font"]').get(1).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/0812efcfaefec5ea.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': '', + test('page using variables', async () => { + const browser = await webdriver(next.url, '/variables') + + // Fira Code Variable + const firaCodeRegex = /^__Fira_Code_.{6}, __Fira_Code_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-fira-code")).fontFamily' + ) + ).toMatch(firaCodeRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-fira-code")).fontFamily' + ) + ).not.toMatch(firaCodeRegex) + + // Roboto 100 Italic + const roboto100ItalicRegex = /^__Roboto_.{6}, __Roboto_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-roboto-100-italic")).fontFamily' + ) + ).toMatch(roboto100ItalicRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-roboto-100-italic")).fontFamily' + ) + ).not.toMatch(roboto100ItalicRegex) + + // Local font + const localFontRegex = /^__myFont_.{6}, __myFont_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-local-font")).fontFamily' + ) + ).toMatch(localFontRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-local-font")).fontFamily' + ) + ).not.toMatch(localFontRegex) }) - expect($('link[as="font"]').get(2).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/ab6fdae82d1a8d92.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': '', + test('page using fallback fonts', async () => { + const browser = await webdriver(next.url, '/with-fallback') + + // .className + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-classname")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) + + // .style + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-style")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) + + // .variable + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-variable")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) }) }) - }) - describe('Fallback fontfaces', () => { - describe('local', () => { - test('Indie flower', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('103.26%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('51.94%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('94%') + describe('preload', () => { + test('page with fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + expect($('link[as="font"]').length).toBe(2) + // From /_app + expect($('link[as="font"]').get(0).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }) + expect($('link[as="font"]').get(1).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/675c25f648fd6a30-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }) }) - test('Fraunces', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('84.71%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('22.09%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('115.45%') + test('page without fonts', async () => { + const html = await renderViaHTTP(next.url, '/without-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From _app + expect($('link[as="font"]').length).toBe(1) + expect($('link[as="font"]').get(0).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }) }) - test('Roboto multiple weights and styles', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') + test('page with local fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-local-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // Preload + expect($('link[as="font"]').length).toBe(5) + expect( + Array.from($('link[as="font"]')) + .map((el) => el.attribs.href) + .sort() + ).toEqual([ + '/_next/static/media/02205c9944024f15-s.p.woff2', + '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + '/_next/static/media/1deec1af325840fd-s.p.woff2', + '/_next/static/media/ab6fdae82d1a8d92-s.p.woff2', + '/_next/static/media/d55edb6f37902ebf-s.p.woff2', + ]) }) - test('Roboto multiple weights and styles - variable 1', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') + test('google fonts with multiple weights/styles', async () => { + const html = await renderViaHTTP(next.url, '/with-google-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // Preload + expect($('link[as="font"]').length).toBe(8) + + expect( + Array.from($('link[as="font"]')) + .map((el) => el.attribs.href) + .sort() + ).toEqual([ + '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + '/_next/static/media/4f3dcdf40b3ca86d-s.p.woff2', + '/_next/static/media/560a6db6ac485cb1-s.p.woff2', + '/_next/static/media/686d1702f12625fe-s.p.woff2', + '/_next/static/media/86d92167ff02c708-s.p.woff2', + '/_next/static/media/9ac01b894b856187-s.p.woff2', + '/_next/static/media/c9baea324111137d-s.p.woff2', + '/_next/static/media/fb68b4558e2a718e-s.p.woff2', + ]) }) - test('Roboto multiple weights and styles - variable 2', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') + test('font without preloadable subsets', async () => { + const html = await renderViaHTTP( + next.url, + '/font-without-preloadable-subsets' + ) + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From _app + expect($('link[as="font"]').length).toBe(1) + expect($('link[as="font"]').get(0).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }) + }) - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') + test('font without size adjust', async () => { + const html = await renderViaHTTP(next.url, '/with-fallback') + const $ = cheerio.load(html) + + expect($('link[as="font"]').get(1).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/0812efcfaefec5ea.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': '', + }) + + expect($('link[as="font"]').get(2).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/ab6fdae82d1a8d92.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': '', + }) }) }) - describe('google', () => { - test('Indie flower', async () => { - const browser = await webdriver(next.url, '/with-google-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('103.26%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('51.94%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('94%') + describe('Fallback fontfaces', () => { + describe('local', () => { + test('Indie flower', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('103.26%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('51.94%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('94%') + }) + + test('Fraunces', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('84.71%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('22.09%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('115.45%') + }) + + test('Roboto multiple weights and styles', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') + }) + + test('Roboto multiple weights and styles - variable 1', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') + }) + + test('Roboto multiple weights and styles - variable 2', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') + }) }) - test('Fraunces', async () => { - const browser = await webdriver(next.url, '/with-google-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('84.71%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('22.09%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('115.45%') + describe('google', () => { + test('Indie flower', async () => { + const browser = await webdriver(next.url, '/with-google-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('103.26%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('51.94%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('94%') + }) + + test('Fraunces', async () => { + const browser = await webdriver(next.url, '/with-google-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('84.71%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('22.09%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('115.45%') + }) }) }) }) diff --git a/test/e2e/next-font/with-font-declarations-file.test.ts b/test/e2e/next-font/with-font-declarations-file.test.ts index fcfb44beb75b1..383f69d433b14 100644 --- a/test/e2e/next-font/with-font-declarations-file.test.ts +++ b/test/e2e/next-font/with-font-declarations-file.test.ts @@ -10,7 +10,7 @@ const mockedGoogleFontResponses = require.resolve( const isDev = (global as any).isNextDev -describe('@next/font/google with-font-declarations-file', () => { +describe('next/font/google with-font-declarations-file', () => { let next: NextInstance if ((global as any).isNextDeploy) { @@ -37,9 +37,6 @@ describe('@next/font/google with-font-declarations-file', () => { join(__dirname, 'with-font-declarations-file/next.config.js') ), }, - dependencies: { - '@next/font': 'canary', - }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, diff --git a/test/e2e/next-font/with-font-declarations-file/fonts.js b/test/e2e/next-font/with-font-declarations-file/fonts.js index f6c1c4071f5a6..8fb3a2914330f 100644 --- a/test/e2e/next-font/with-font-declarations-file/fonts.js +++ b/test/e2e/next-font/with-font-declarations-file/fonts.js @@ -1,11 +1,11 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' import { Open_Sans, Source_Code_Pro, Abel, Inter, Roboto, -} from '@next/font/google' +} from 'next/font/google' const openSans = Open_Sans() const sourceCodePro = Source_Code_Pro({ display: 'swap', preload: false }) diff --git a/test/e2e/next-font/with-font-declarations-file/next.config.js b/test/e2e/next-font/with-font-declarations-file/next.config.js index 3f4a776b7f409..51b19fbc18002 100644 --- a/test/e2e/next-font/with-font-declarations-file/next.config.js +++ b/test/e2e/next-font/with-font-declarations-file/next.config.js @@ -2,7 +2,7 @@ module.exports = { experimental: { fontLoaders: [ { - loader: '@next/font/google', + loader: 'next/font/google', options: { subsets: ['latin'] }, }, ], diff --git a/test/e2e/next-font/without-preloaded-fonts.test.ts b/test/e2e/next-font/without-preloaded-fonts.test.ts index a2d71bf730807..b71000c7d645c 100644 --- a/test/e2e/next-font/without-preloaded-fonts.test.ts +++ b/test/e2e/next-font/without-preloaded-fonts.test.ts @@ -8,7 +8,7 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font/google without-preloaded-fonts without _app', () => { +describe('next/font/google without-preloaded-fonts without _app', () => { let next: NextInstance if ((global as any).isNextDeploy) { @@ -29,9 +29,6 @@ describe('@next/font/google without-preloaded-fonts without _app', () => { join(__dirname, 'without-preloaded-fonts/next.config.js') ), }, - dependencies: { - '@next/font': 'canary', - }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, @@ -65,7 +62,7 @@ describe('@next/font/google without-preloaded-fonts without _app', () => { }) }) -describe('@next/font/google no preloads with _app', () => { +describe('next/font/google no preloads with _app', () => { let next: NextInstance if ((global as any).isNextDeploy) { @@ -89,9 +86,6 @@ describe('@next/font/google no preloads with _app', () => { join(__dirname, 'without-preloaded-fonts/next.config.js') ), }, - dependencies: { - '@next/font': 'canary', - }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, diff --git a/test/e2e/next-font/without-preloaded-fonts/next.config.js b/test/e2e/next-font/without-preloaded-fonts/next.config.js index 3f4a776b7f409..51b19fbc18002 100644 --- a/test/e2e/next-font/without-preloaded-fonts/next.config.js +++ b/test/e2e/next-font/without-preloaded-fonts/next.config.js @@ -2,7 +2,7 @@ module.exports = { experimental: { fontLoaders: [ { - loader: '@next/font/google', + loader: 'next/font/google', options: { subsets: ['latin'] }, }, ], diff --git a/test/e2e/next-font/without-preloaded-fonts/pages/_app.js b/test/e2e/next-font/without-preloaded-fonts/pages/_app.js index a19d81c7a1c8a..723151757dd3a 100644 --- a/test/e2e/next-font/without-preloaded-fonts/pages/_app.js +++ b/test/e2e/next-font/without-preloaded-fonts/pages/_app.js @@ -1,4 +1,4 @@ -import { Abel } from '@next/font/google' +import { Abel } from 'next/font/google' const abel = Abel({ weight: '400', display: 'optional', preload: false }) function MyApp({ Component, pageProps }) { diff --git a/test/e2e/next-font/without-preloaded-fonts/pages/no-preload.js b/test/e2e/next-font/without-preloaded-fonts/pages/no-preload.js index 4ebfef35a2ed8..9213aafe9f842 100644 --- a/test/e2e/next-font/without-preloaded-fonts/pages/no-preload.js +++ b/test/e2e/next-font/without-preloaded-fonts/pages/no-preload.js @@ -1,4 +1,4 @@ -import { Abel } from '@next/font/google' +import { Abel } from 'next/font/google' const abel = Abel({ weight: '400', display: 'optional', preload: false }) export default function NoPreload() { diff --git a/test/production/jest/index.test.ts b/test/production/jest/index.test.ts index 998619bc15892..d17bd3f33db17 100644 --- a/test/production/jest/index.test.ts +++ b/test/production/jest/index.test.ts @@ -21,8 +21,8 @@ describe('next/jest', () => { import Image from "next/image"; import img from "../public/vercel.svg"; import styles from "../styles/index.module.css"; - import localFont from "@next/font/local"; - import { Inter } from "@next/font/google"; + import localFont from "next/font/local"; + import { Inter } from "next/font/google"; const inter = Inter({ subsets: ["latin"] }); const myFont = localFont({ src: "./my-font.woff2" }); diff --git a/test/production/next-font/babel-unsupported.test.ts b/test/production/next-font/babel-unsupported.test.ts index 1214ef377b578..ae2fe4868385b 100644 --- a/test/production/next-font/babel-unsupported.test.ts +++ b/test/production/next-font/babel-unsupported.test.ts @@ -9,9 +9,6 @@ describe('@next/fon babel unsupported', () => { next = await createNext({ skipStart: true, files: new FileRef(join(__dirname, 'babel-unsupported')), - dependencies: { - '@next/font': 'canary', - }, }) }) afterAll(() => next.destroy()) @@ -21,7 +18,7 @@ describe('@next/fon babel unsupported', () => { 'next build failed with code/signal 1' ) expect(next.cliOutput).toMatch( - /"@next\/font" requires SWC although Babel is being used due to a custom babel config being present./ + /"next\/font" requires SWC although Babel is being used due to a custom babel config being present./ ) }) }) diff --git a/test/production/next-font/babel-unsupported/pages/index.js b/test/production/next-font/babel-unsupported/pages/index.js index a5942d198ea38..cd0c6a8237d0e 100644 --- a/test/production/next-font/babel-unsupported/pages/index.js +++ b/test/production/next-font/babel-unsupported/pages/index.js @@ -1,4 +1,4 @@ -import { Inter } from '@next/font/google' +import { Inter } from 'next/font/google' console.log(Inter) diff --git a/test/production/next-font/telemetry-old.test.ts b/test/production/next-font/telemetry-old.test.ts new file mode 100644 index 0000000000000..c27ec16e94795 --- /dev/null +++ b/test/production/next-font/telemetry-old.test.ts @@ -0,0 +1,78 @@ +import { createNext, FileRef } from 'e2e-utils' +import { NextInstance } from 'test/lib/next-modes/base' +import { findAllTelemetryEvents } from 'next-test-utils' +import { join } from 'path' + +const mockedGoogleFontResponses = require.resolve( + './google-font-mocked-responses.js' +) + +describe('@next/font used telemetry', () => { + let next: NextInstance + + beforeAll(async () => { + next = await createNext({ + files: { + pages: new FileRef(join(__dirname, 'telemetry-old/pages')), + }, + dependencies: { + '@next/font': 'canary', + }, + env: { + NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, + NEXT_TELEMETRY_DEBUG: '1', + }, + }) + }) + afterAll(() => next.destroy()) + + it('should send @next/font/google and @next/font/local usage event', async () => { + const events = findAllTelemetryEvents( + next.cliOutput, + 'NEXT_BUILD_FEATURE_USAGE' + ) + expect(events).toContainEqual({ + featureName: '@next/font/google', + invocationCount: 1, + }) + expect(events).toContainEqual({ + featureName: '@next/font/local', + invocationCount: 1, + }) + }) +}) + +describe('@next/font unused telemetry', () => { + let next: NextInstance + + beforeAll(async () => { + next = await createNext({ + files: { + pages: new FileRef(join(__dirname, 'telemetry/pages-unused')), + }, + dependencies: { + '@next/font': 'canary', + }, + env: { + NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, + NEXT_TELEMETRY_DEBUG: '1', + }, + }) + }) + afterAll(() => next.destroy()) + + it('should not send @next/font/google and @next/font/local usage event', async () => { + const events = findAllTelemetryEvents( + next.cliOutput, + 'NEXT_BUILD_FEATURE_USAGE' + ) + expect(events).toContainEqual({ + featureName: '@next/font/google', + invocationCount: 0, + }) + expect(events).toContainEqual({ + featureName: '@next/font/local', + invocationCount: 0, + }) + }) +}) diff --git a/test/production/next-font/telemetry-old/pages-unused/index.js b/test/production/next-font/telemetry-old/pages-unused/index.js new file mode 100644 index 0000000000000..a681aa7ce257c --- /dev/null +++ b/test/production/next-font/telemetry-old/pages-unused/index.js @@ -0,0 +1,3 @@ +export default function Page() { + return

Hello world

+} diff --git a/test/production/next-font/telemetry-old/pages/_app.js b/test/production/next-font/telemetry-old/pages/_app.js new file mode 100644 index 0000000000000..05702a3dc4834 --- /dev/null +++ b/test/production/next-font/telemetry-old/pages/_app.js @@ -0,0 +1,13 @@ +import localFont from '@next/font/local' + +const myFont = localFont({ src: './my-font.woff2' }) + +function MyApp({ Component, pageProps }) { + return ( +
+ +
+ ) +} + +export default MyApp diff --git a/test/production/next-font/telemetry-old/pages/index.js b/test/production/next-font/telemetry-old/pages/index.js new file mode 100644 index 0000000000000..26400dc9cebe7 --- /dev/null +++ b/test/production/next-font/telemetry-old/pages/index.js @@ -0,0 +1,11 @@ +import { Open_Sans } from '@next/font/google' +const openSans = Open_Sans({ subsets: ['latin'] }) + +export default function Page() { + return ( + <> +

Hello world 1

+

Hello world 2

+ + ) +} diff --git a/test/production/next-font/telemetry-old/pages/my-font.woff2 b/test/production/next-font/telemetry-old/pages/my-font.woff2 new file mode 100644 index 0000000000000..a6b3c3a9d69fa Binary files /dev/null and b/test/production/next-font/telemetry-old/pages/my-font.woff2 differ diff --git a/test/production/next-font/telemetry.test.ts b/test/production/next-font/telemetry.test.ts index 8867c1ec780f8..00f1d4ebd3be8 100644 --- a/test/production/next-font/telemetry.test.ts +++ b/test/production/next-font/telemetry.test.ts @@ -7,19 +7,13 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font used telemetry', () => { +describe('next/font used telemetry', () => { let next: NextInstance beforeAll(async () => { next = await createNext({ files: { pages: new FileRef(join(__dirname, 'telemetry/pages')), - 'next.config.js': new FileRef( - join(__dirname, 'telemetry/next.config.js') - ), - }, - dependencies: { - '@next/font': 'canary', }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, @@ -29,35 +23,29 @@ describe('@next/font used telemetry', () => { }) afterAll(() => next.destroy()) - it('should send @next/font/google and @next/font/local usage event', async () => { + it('should send next/font/google and next/font/local usage event', async () => { const events = findAllTelemetryEvents( next.cliOutput, 'NEXT_BUILD_FEATURE_USAGE' ) expect(events).toContainEqual({ - featureName: '@next/font/google', + featureName: 'next/font/google', invocationCount: 1, }) expect(events).toContainEqual({ - featureName: '@next/font/local', + featureName: 'next/font/local', invocationCount: 1, }) }) }) -describe('@next/font unused telemetry', () => { +describe('next/font unused telemetry', () => { let next: NextInstance beforeAll(async () => { next = await createNext({ files: { pages: new FileRef(join(__dirname, 'telemetry/pages-unused')), - 'next.config.js': new FileRef( - join(__dirname, 'telemetry/next.config.js') - ), - }, - dependencies: { - '@next/font': 'canary', }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, @@ -67,17 +55,17 @@ describe('@next/font unused telemetry', () => { }) afterAll(() => next.destroy()) - it('should not send @next/font/google and @next/font/local usage event', async () => { + it('should not send next/font/google and next/font/local usage event', async () => { const events = findAllTelemetryEvents( next.cliOutput, 'NEXT_BUILD_FEATURE_USAGE' ) expect(events).toContainEqual({ - featureName: '@next/font/google', + featureName: 'next/font/google', invocationCount: 0, }) expect(events).toContainEqual({ - featureName: '@next/font/local', + featureName: 'next/font/local', invocationCount: 0, }) }) diff --git a/test/production/next-font/telemetry/pages/_app.js b/test/production/next-font/telemetry/pages/_app.js index 05702a3dc4834..5475f7ef54428 100644 --- a/test/production/next-font/telemetry/pages/_app.js +++ b/test/production/next-font/telemetry/pages/_app.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const myFont = localFont({ src: './my-font.woff2' }) diff --git a/test/production/next-font/telemetry/pages/index.js b/test/production/next-font/telemetry/pages/index.js index 26400dc9cebe7..b99c8aacbbeae 100644 --- a/test/production/next-font/telemetry/pages/index.js +++ b/test/production/next-font/telemetry/pages/index.js @@ -1,4 +1,4 @@ -import { Open_Sans } from '@next/font/google' +import { Open_Sans } from 'next/font/google' const openSans = Open_Sans({ subsets: ['latin'] }) export default function Page() { diff --git a/test/unit/google-font-loader.test.ts b/test/unit/google-font-loader.test.ts index 25dca9d3201ee..14890a96d9e96 100644 --- a/test/unit/google-font-loader.test.ts +++ b/test/unit/google-font-loader.test.ts @@ -3,7 +3,7 @@ import fetch from 'next/dist/compiled/node-fetch' jest.mock('next/dist/compiled/node-fetch') -describe('@next/font/google loader', () => { +describe('next/font/google loader', () => { afterEach(() => { jest.resetAllMocks() }) @@ -148,7 +148,7 @@ describe('@next/font/google loader', () => { variableName: 'myFont', }) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"@next/font/google has no default export"` + `"next/font/google has no default export"` ) }) diff --git a/test/unit/local-font-loader.test.ts b/test/unit/local-font-loader.test.ts index 86acc47d0dd6b..8ab46a58b930d 100644 --- a/test/unit/local-font-loader.test.ts +++ b/test/unit/local-font-loader.test.ts @@ -1,6 +1,6 @@ import loader from '@next/font/local/loader' -describe('@next/font/local', () => { +describe('next/font/local', () => { describe('generated CSS', () => { test('Default CSS', async () => { const { css } = await loader({ @@ -251,7 +251,7 @@ describe('@next/font/local', () => { loaderContext: {} as any, }) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"@next/font/local has no named exports"` + `"next/font/local has no named exports"` ) })