Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font loader support in app #40898

Merged
merged 11 commits into from
Sep 27, 2022
1 change: 1 addition & 0 deletions packages/font/google/target.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* target file for webpack loader */
1 change: 1 addition & 0 deletions packages/font/local/target.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* target file for webpack loader */
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl<'a> FontImportsGenerator<'a> {
return Some(ImportDecl {
src: Box::new(Str {
value: JsWord::from(format!(
"{}?{}",
"{}/target.css?{}",
font_function.loader,
values.join(";")
)),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import firaCode from "@next/font/google?pages/test.tsx;Abel";
import inter from "@next/font/google?pages/test.tsx;Inter";
import firaCode from "@next/font/google/target.css?pages/test.tsx;Abel";
import inter from "@next/font/google/target.css?pages/test.tsx;Inter";
import React from 'react';
export { firaCode };
export { inter };
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import inter1 from '@next/font/google?pages/test.tsx;Inter;{"variant":"400"}';
import inter2 from '@next/font/google?pages/test.tsx;Inter;{"variant":"400"}';
import inter1 from '@next/font/google/target.css?pages/test.tsx;Inter;{"variant":"400"}';
import inter2 from '@next/font/google/target.css?pages/test.tsx;Inter;{"variant":"400"}';
var i = 10;
var i2 = 20;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import a from "@next/font/google?pages/test.tsx;ABeeZee;{}";
import a from "@next/font/google?pages/test.tsx;ABeeZee;{}";
import a from "@next/font/google?pages/test.tsx;ABeeZee;{}";
import a from "@next/font/google?pages/test.tsx;ABeeZee;{}";
import a from "@next/font/google/target.css?pages/test.tsx;ABeeZee;{}";
import a from "@next/font/google/target.css?pages/test.tsx;ABeeZee;{}";
import a from "@next/font/google/target.css?pages/test.tsx;ABeeZee;{}";
import a from "@next/font/google/target.css?pages/test.tsx;ABeeZee;{}";
const a = fn({
10: 'hello'
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import inter from "@next/font/google?pages/test.tsx;Inter;{};[]";
import inter from "@next/font/google/target.css?pages/test.tsx;Inter;{};[]";
const a = fn(...{}, ...[]);
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import font from 'cool-fonts?pages/test.tsx;;{"prop":true}';
import font from 'cool-fonts/target.css?pages/test.tsx;;{"prop":true}';
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import firaCode from "@next/font/google?pages/test.tsx;Abel";
import inter from "@next/font/google?pages/test.tsx;Inter";
import firaCode from "@next/font/google/target.css?pages/test.tsx;Abel";
import inter from "@next/font/google/target.css?pages/test.tsx;Inter";
import React from 'react';
export { firaCode };
export { inter };
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import firaCode from "@next/font/google?pages/test.tsx;Abel";
import inter from "@next/font/google?pages/test.tsx;Inter";
import firaCode from "@next/font/google/target.css?pages/test.tsx;Abel";
import inter from "@next/font/google/target.css?pages/test.tsx;Inter";
import React from 'react';
export { firaCode };
export default inter;
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import firaCode from '@next/font/google?pages/test.tsx;Fira_Code;{"fallback":["system-ui",{"key":false},[]],"key":{"key2":{}},"preload":true,"variant":"400"}';
import firaCode from '@next/font/google/target.css?pages/test.tsx;Fira_Code;{"fallback":["system-ui",{"key":false},[]],"key":{"key2":{}},"preload":true,"variant":"400"}';
import React from 'react';
console.log(firaCode);
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import acme1 from 'cool-fonts?pages/test.tsx;Acme;{"variant":"400"}';
import acme1 from 'cool-fonts/target.css?pages/test.tsx;Acme;{"variant":"400"}';
import React from 'react';
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import geo from '@next/font/google?pages/test.tsx;Geo;"test";[1.0];{"a":2.0};3.0';
import geo from '@next/font/google/target.css?pages/test.tsx;Geo;"test";[1.0];{"a":2.0};3.0';
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import inter from '@next/font/google?pages/test.tsx;Inter;{"display":"swap","variant":"900"}';
import inter from '@next/font/google?pages/test.tsx;Inter;{"display":"swap","variant":"900"}';
import inter from '@next/font/google/target.css?pages/test.tsx;Inter;{"display":"swap","variant":"900"}';
import inter from '@next/font/google/target.css?pages/test.tsx;Inter;{"display":"swap","variant":"900"}';
import React from 'react';
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import inter from '@next/font/google?pages/test.tsx;Inter;{"variant":"900"}';
import fira from 'cool-fonts?pages/test.tsx;Fira_Code;{"display":"swap","variant":"400"}';
import inter from '@next/font/google/target.css?pages/test.tsx;Inter;{"variant":"900"}';
import fira from 'cool-fonts/target.css?pages/test.tsx;Fira_Code;{"display":"swap","variant":"400"}';
import React from 'react';
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import firaCode from '@next/font/google?pages/test.tsx;Fira_Code;{"fallback":["system-ui"],"variant":"400"}';
import inter from '@next/font/google?pages/test.tsx;Inter;{"display":"swap","variant":"900"}';
import firaCode from '@next/font/google/target.css?pages/test.tsx;Fira_Code;{"fallback":["system-ui"],"variant":"400"}';
import inter from '@next/font/google/target.css?pages/test.tsx;Inter;{"display":"swap","variant":"900"}';
import React from 'react';
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import inter from '@next/font/google?pages/test.tsx;Inter;{"variant":"900"}';
import fira from '@next/font/google?pages/test.tsx;Fira_Code;{"display":"swap","variant":"400"}';
import inter from '@next/font/google/target.css?pages/test.tsx;Inter;{"variant":"900"}';
import fira from '@next/font/google/target.css?pages/test.tsx;Fira_Code;{"display":"swap","variant":"400"}';
import React from 'react';
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import fira from "@next/font/google?pages/test.tsx;Fira_Code";
import fira from "@next/font/google/target.css?pages/test.tsx;Fira_Code";
9 changes: 9 additions & 0 deletions packages/next/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1204,6 +1204,13 @@ export default async function getBaseWebpackConfig(
const rscSharedRegex =
/(node_modules\/react\/|\/shared\/lib\/(head-manager-context|router-context|flush-effects)\.js|node_modules\/styled-jsx\/)/

const fontLoaderTargets =
config.experimental.fontLoaders &&
Object.keys(config.experimental.fontLoaders).map((fontLoader) => {
const resolved = require.resolve(fontLoader)
return path.join(resolved, '../target.css')
})

let webpackConfig: webpack.Configuration = {
parallelism: Number(process.env.NEXT_WEBPACK_PARALLELISM) || undefined,
// @ts-ignore
Expand Down Expand Up @@ -1893,10 +1900,12 @@ export default async function getBaseWebpackConfig(
(isClient
? new FlightManifestPlugin({
dev,
fontLoaderTargets,
})
: new FlightClientEntryPlugin({
dev,
isEdgeServer,
fontLoaderTargets,
})),
!dev &&
isClient &&
Expand Down
45 changes: 23 additions & 22 deletions packages/next/build/webpack/config/blocks/css/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
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'
Expand Down Expand Up @@ -180,32 +181,11 @@ export const css = curry(async function css(

const fns: ConfigurationFn[] = []

// CSS cannot be imported in _document. This comes before everything because
// global CSS nor CSS modules work in said file.
fns.push(
loader({
oneOf: [
markRemovable({
test: regexLikeCss,
// Use a loose regex so we don't have to crawl the file system to
// find the real file name (if present).
issuer: /pages[\\/]_document\./,
use: {
loader: 'error-loader',
options: {
reason: getCustomDocumentError(),
},
},
}),
],
})
)

// 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
? Object.entries(ctx.experimental.fontLoaders).map(
([fontLoader, fontLoaderOptions]: any) => [
require.resolve(fontLoader),
path.join(require.resolve(fontLoader), '../target.css'),
fontLoaderOptions,
]
)
Expand Down Expand Up @@ -254,6 +234,27 @@ export const css = curry(async function css(
)
})

// CSS cannot be imported in _document. This comes before everything because
// global CSS nor CSS modules work in said file.
fns.push(
loader({
oneOf: [
markRemovable({
test: regexLikeCss,
// Use a loose regex so we don't have to crawl the file system to
// find the real file name (if present).
issuer: /pages[\\/]_document\./,
use: {
loader: 'error-loader',
options: {
reason: getCustomDocumentError(),
},
},
}),
],
})
)

// CSS Modules support must be enabled on the server and client so the class
// names are available for SSR or Prerendering.
if (ctx.experimental.appDir && !ctx.isProduction) {
Expand Down
12 changes: 10 additions & 2 deletions packages/next/build/webpack/plugins/flight-client-entry-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { isClientComponentModule } from '../loaders/utils'
interface Options {
dev: boolean
isEdgeServer: boolean
fontLoaderTargets?: string[]
}

const PLUGIN_NAME = 'ClientEntryPlugin'
Expand All @@ -37,10 +38,12 @@ const flightCSSManifest: FlightCSSManifest = {}
export class FlightClientEntryPlugin {
dev: boolean
isEdgeServer: boolean
fontLoaderTargets?: string[]

constructor(options: Options) {
this.dev = options.dev
this.isEdgeServer = options.isEdgeServer
this.fontLoaderTargets = options.fontLoaderTargets
}

apply(compiler: webpack.Compiler) {
Expand Down Expand Up @@ -216,12 +219,17 @@ export class FlightClientEntryPlugin {
// Request could be undefined or ''
if (!rawRequest) return

const isFontLoader = this.fontLoaderTargets?.some((fontLoaderTarget) =>
mod.userRequest.startsWith(`${fontLoaderTarget}?`)
)
const modRequest: string | undefined =
!rawRequest.endsWith('.css') &&
!rawRequest.startsWith('.') &&
!rawRequest.startsWith('/') &&
!rawRequest.startsWith(APP_DIR_ALIAS)
? rawRequest
? isFontLoader
? mod.userRequest
: rawRequest
: mod.resourceResolveData?.path

// Ensure module is not walked again if it's already been visited
Expand All @@ -236,7 +244,7 @@ export class FlightClientEntryPlugin {
}
visitedBySegment[layoutOrPageRequest].add(modRequest)

const isCSS = regexCSS.test(modRequest)
const isCSS = isFontLoader || regexCSS.test(modRequest)
const isClientComponent = isClientComponentModule(mod)

if (isCSS) {
Expand Down
8 changes: 8 additions & 0 deletions packages/next/build/webpack/plugins/flight-manifest-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { isClientComponentModule } from '../loaders/utils'

interface Options {
dev: boolean
fontLoaderTargets?: string[]
}

/**
Expand Down Expand Up @@ -62,9 +63,11 @@ const PLUGIN_NAME = 'FlightManifestPlugin'

export class FlightManifestPlugin {
dev: Options['dev'] = false
fontLoaderTargets?: Options['fontLoaderTargets']

constructor(options: Options) {
this.dev = options.dev
this.fontLoaderTargets = options.fontLoaderTargets
}

apply(compiler: webpack.Compiler) {
Expand Down Expand Up @@ -104,6 +107,7 @@ export class FlightManifestPlugin {
__ssr_module_mapping__: {},
}
const dev = this.dev
const fontLoaderTargets = this.fontLoaderTargets

const clientRequestsSet = new Set()

Expand Down Expand Up @@ -142,7 +146,11 @@ export class FlightManifestPlugin {
id: ModuleId,
mod: webpack.NormalModule
) {
const isFontLoader = fontLoaderTargets?.some((fontLoaderTarget) =>
mod.resource?.startsWith(`${fontLoaderTarget}?`)
)
const isCSSModule =
isFontLoader ||
mod.resource?.endsWith('.css') ||
mod.type === 'css/mini-extract' ||
(!!mod.loaders &&
Expand Down
Loading