From a8938c9edf6a38415c131ad09bb2ed683e8d4f49 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 11 May 2022 17:41:05 +0200 Subject: [PATCH] Enable font optimization for react 18 --- packages/next/server/render.tsx | 93 +++++++++---------- .../amphtml-custom-optimizer/next.config.js | 5 +- .../test/index.test.js | 13 +-- test/integration/amphtml/next.config.js | 5 +- test/integration/amphtml/test/index.test.js | 9 +- test/integration/app-document/next.config.js | 5 +- .../app-document/pages/_document.js | 2 +- .../app-document/test/index.test.js | 4 - .../fixtures/with-google/next.config.js | 8 +- .../fixtures/with-typekit/next.config.js | 8 +- .../font-optimization/test/index.test.js | 50 +++------- .../react-18-invalid-config/index.test.js | 6 +- 12 files changed, 71 insertions(+), 137 deletions(-) diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index fb2e9f9e3639f..ddf0f7de00513 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -1751,56 +1751,51 @@ export async function renderToHTML( return RenderResult.fromStatic((renderOpts as any).pageData) } - const postProcessors: Array<((html: string) => Promise) | null> = ( - generateStaticHTML - ? [ - inAmpMode - ? async (html: string) => { - html = await optimizeAmp(html, renderOpts.ampOptimizerConfig) - if (!renderOpts.ampSkipValidation && renderOpts.ampValidator) { - await renderOpts.ampValidator(html, pathname) - } - return html - } - : null, - process.env.NEXT_RUNTIME !== 'edge' && - process.env.__NEXT_OPTIMIZE_FONTS - ? async (html: string) => { - return await postProcess( - html, - { getFontDefinition }, - { - optimizeFonts: renderOpts.optimizeFonts, - } - ) - } - : null, - process.env.NEXT_RUNTIME !== 'edge' && renderOpts.optimizeCss - ? async (html: string) => { - // eslint-disable-next-line import/no-extraneous-dependencies - const Critters = require('critters') - const cssOptimizer = new Critters({ - ssrMode: true, - reduceInlineStyles: false, - path: renderOpts.distDir, - publicPath: `${renderOpts.assetPrefix}/_next/`, - preload: 'media', - fonts: false, - ...renderOpts.optimizeCss, - }) - return await cssOptimizer.process(html) - } - : null, - inAmpMode || hybridAmp - ? async (html: string) => { - return html.replace(/&amp=1/g, '&=1') - } - : null, - ] - : [] - ).filter(Boolean) + const postProcessors: Array<((html: string) => Promise) | null> = [ + inAmpMode + ? async (html: string) => { + html = await optimizeAmp(html, renderOpts.ampOptimizerConfig) + if (!renderOpts.ampSkipValidation && renderOpts.ampValidator) { + await renderOpts.ampValidator(html, pathname) + } + return html + } + : null, + process.env.NEXT_RUNTIME !== 'edge' && process.env.__NEXT_OPTIMIZE_FONTS + ? async (html: string) => { + return await postProcess( + html, + { getFontDefinition }, + { + optimizeFonts: renderOpts.optimizeFonts, + } + ) + } + : null, + process.env.NEXT_RUNTIME !== 'edge' && renderOpts.optimizeCss + ? async (html: string) => { + // eslint-disable-next-line import/no-extraneous-dependencies + const Critters = require('critters') + const cssOptimizer = new Critters({ + ssrMode: true, + reduceInlineStyles: false, + path: renderOpts.distDir, + publicPath: `${renderOpts.assetPrefix}/_next/`, + preload: 'media', + fonts: false, + ...renderOpts.optimizeCss, + }) + return await cssOptimizer.process(html) + } + : null, + inAmpMode || hybridAmp + ? async (html: string) => { + return html.replace(/&amp=1/g, '&=1') + } + : null, + ].filter(Boolean) - if (generateStaticHTML || postProcessors.length > 0) { + if (postProcessors.length > 0) { let html = await streamToString(chainStreams(streams)) for (const postProcessor of postProcessors) { if (postProcessor) { diff --git a/test/integration/amphtml-custom-optimizer/next.config.js b/test/integration/amphtml-custom-optimizer/next.config.js index 32d983dc28dfa..072c5b3965f97 100644 --- a/test/integration/amphtml-custom-optimizer/next.config.js +++ b/test/integration/amphtml-custom-optimizer/next.config.js @@ -1,5 +1,4 @@ -const path = require('path') -module.exports = require(path.join(__dirname, '../../lib/with-react-17.js'))({ +module.exports = { experimental: { amp: { optimizer: { @@ -10,4 +9,4 @@ module.exports = require(path.join(__dirname, '../../lib/with-react-17.js'))({ skipValidation: true, }, }, -}) +} diff --git a/test/integration/amphtml-custom-optimizer/test/index.test.js b/test/integration/amphtml-custom-optimizer/test/index.test.js index b9a35e01a9b67..93f31d5b10270 100644 --- a/test/integration/amphtml-custom-optimizer/test/index.test.js +++ b/test/integration/amphtml-custom-optimizer/test/index.test.js @@ -12,19 +12,14 @@ import { let app let appPort const appDir = join(__dirname, '../') -const nodeArgs = ['-r', join(appDir, '../../lib/react-17-require-hook.js')] describe('AMP Custom Optimizer', () => { it('should build and start for static page', async () => { - const { code } = await nextBuild(appDir, undefined, { - nodeArgs, - }) + const { code } = await nextBuild(appDir) expect(code).toBe(0) appPort = await findPort() - app = await nextStart(appDir, appPort, { - nodeArgs, - }) + app = await nextStart(appDir, appPort) const html = await renderViaHTTP(appPort, '/') await killApp(app) @@ -39,11 +34,11 @@ describe('AMP Custom Optimizer', () => { }) it('should build and start for dynamic page', async () => { - const { code } = await nextBuild(appDir, undefined, { nodeArgs }) + const { code } = await nextBuild(appDir) expect(code).toBe(0) appPort = await findPort() - app = await nextStart(appDir, appPort, { nodeArgs }) + app = await nextStart(appDir, appPort) const html = await renderViaHTTP(appPort, '/dynamic') await killApp(app) diff --git a/test/integration/amphtml/next.config.js b/test/integration/amphtml/next.config.js index 32cc43dcc3932..9645154cca885 100644 --- a/test/integration/amphtml/next.config.js +++ b/test/integration/amphtml/next.config.js @@ -1,5 +1,4 @@ -const path = require('path') -module.exports = require(path.join(__dirname, '../../lib/with-react-17.js'))({ +module.exports = { onDemandEntries: { // Make sure entries are not getting disposed. maxInactiveAge: 1000 * 60 * 60, @@ -8,4 +7,4 @@ module.exports = require(path.join(__dirname, '../../lib/with-react-17.js'))({ canonicalBase: 'http://localhost:1234', }, // edit here -}) +} diff --git a/test/integration/amphtml/test/index.test.js b/test/integration/amphtml/test/index.test.js index 7251e628559e9..156a2a4234239 100644 --- a/test/integration/amphtml/test/index.test.js +++ b/test/integration/amphtml/test/index.test.js @@ -18,7 +18,6 @@ import webdriver from 'next-webdriver' import { join } from 'path' const appDir = join(__dirname, '../') -const nodeArgs = ['-r', join(appDir, '../../lib/react-17-require-hook.js')] let appPort let app @@ -36,14 +35,11 @@ describe('AMP Usage', () => { const result = await nextBuild(appDir, undefined, { stdout: true, stderr: true, - nodeArgs, }) output = result.stdout + result.stderr appPort = context.appPort = await findPort() - app = await nextStart(appDir, context.appPort, { - nodeArgs, - }) + app = await nextStart(appDir, context.appPort) }) afterAll(async () => { await rename( @@ -276,7 +272,6 @@ describe('AMP Usage', () => { onStderr(msg) { inspectPayload += msg }, - nodeArgs, }) await renderViaHTTP(dynamicAppPort, '/only-amp') @@ -301,7 +296,6 @@ describe('AMP Usage', () => { onStderr(msg) { output += msg }, - nodeArgs, }) }) @@ -549,7 +543,6 @@ describe('AMP Usage', () => { onStderr(msg) { inspectPayload += msg }, - nodeArgs, }) await renderViaHTTP(dynamicAppPort, '/invalid-amp') diff --git a/test/integration/app-document/next.config.js b/test/integration/app-document/next.config.js index e6b08f8f595f5..ecf49353c47b7 100644 --- a/test/integration/app-document/next.config.js +++ b/test/integration/app-document/next.config.js @@ -1,4 +1 @@ -const path = require('path') -module.exports = require(path.join(__dirname, '../../lib/with-react-17.js'))({ - crossOrigin: 'anonymous', -}) +module.exports = { crossOrigin: 'anonymous' } diff --git a/test/integration/app-document/pages/_document.js b/test/integration/app-document/pages/_document.js index c6a9c36e41430..432a3cfd38ea9 100644 --- a/test/integration/app-document/pages/_document.js +++ b/test/integration/app-document/pages/_document.js @@ -38,7 +38,7 @@ export default class MyDocument extends Document { } } - const result = ctx.renderPage(options) + const result = await ctx.renderPage(options) return { ...result, diff --git a/test/integration/app-document/test/index.test.js b/test/integration/app-document/test/index.test.js index 6edbe398077d0..cb606f37c4643 100644 --- a/test/integration/app-document/test/index.test.js +++ b/test/integration/app-document/test/index.test.js @@ -28,10 +28,6 @@ describe('Document and App', () => { context.server = await launchApp(join(__dirname, '../'), context.appPort, { onStdout: collectOutput, onStderr: collectOutput, - nodeArgs: [ - '-r', - join(__dirname, '../../../lib/react-17-require-hook.js'), - ], }) // pre-build all pages at the start diff --git a/test/integration/font-optimization/fixtures/with-google/next.config.js b/test/integration/font-optimization/fixtures/with-google/next.config.js index 4dc780b4c6150..b248a84265173 100644 --- a/test/integration/font-optimization/fixtures/with-google/next.config.js +++ b/test/integration/font-optimization/fixtures/with-google/next.config.js @@ -1,7 +1 @@ -const path = require('path') -module.exports = require(path.join( - __dirname, - '../../../../lib/with-react-17.js' -))({ - cleanDistDir: false, -}) +module.exports = { cleanDistDir: false } diff --git a/test/integration/font-optimization/fixtures/with-typekit/next.config.js b/test/integration/font-optimization/fixtures/with-typekit/next.config.js index 4dc780b4c6150..48d01ad0e21d2 100644 --- a/test/integration/font-optimization/fixtures/with-typekit/next.config.js +++ b/test/integration/font-optimization/fixtures/with-typekit/next.config.js @@ -1,7 +1,3 @@ -const path = require('path') -module.exports = require(path.join( - __dirname, - '../../../../lib/with-react-17.js' -))({ +module.exports = { cleanDistDir: false, -}) +} diff --git a/test/integration/font-optimization/test/index.test.js b/test/integration/font-optimization/test/index.test.js index ee2f24422bc4d..13c46360597e7 100644 --- a/test/integration/font-optimization/test/index.test.js +++ b/test/integration/font-optimization/test/index.test.js @@ -15,10 +15,6 @@ import { import webdriver from 'next-webdriver' const fixturesDir = join(__dirname, '..', 'fixtures') -const nodeArgs = [ - '-r', - join(__dirname, '../../../lib/react-17-require-hook.js'), -] const fsExists = (file) => fs @@ -229,9 +225,7 @@ describe('Font Optimization', () => { // Re-run build to check if it works when build is cached it('should work when build is cached', async () => { - await nextBuild(appDir, undefined, { - nodeArgs, - }) + await nextBuild(appDir) const testJson = JSON.parse( await fs.readFile(builtPage('font-manifest.json'), { encoding: 'utf-8', @@ -246,13 +240,9 @@ describe('Font Optimization', () => { if (fs.pathExistsSync(join(appDir, '.next'))) { await fs.remove(join(appDir, '.next')) } - await nextBuild(appDir, undefined, { - nodeArgs, - }) + await nextBuild(appDir) appPort = await findPort() - app = await nextStart(appDir, appPort, { - nodeArgs, - }) + app = await nextStart(appDir, appPort) builtServerPagesDir = join(appDir, '.next', 'server') builtPage = (file) => join(builtServerPagesDir, file) }) @@ -266,19 +256,12 @@ describe('Font Optimization', () => { beforeAll(async () => { await fs.writeFile( nextConfig, - ` - const path = require('path') - module.exports = require(path.join(__dirname, '../../../../lib/with-react-17.js'))({ target: 'serverless', cleanDistDir: false }) - `, + `module.exports = ({ target: 'serverless', cleanDistDir: false })`, 'utf8' ) - await nextBuild(appDir, undefined, { - nodeArgs, - }) + await nextBuild(appDir) appPort = await findPort() - app = await nextStart(appDir, appPort, { - nodeArgs, - }) + app = await nextStart(appDir, appPort) builtServerPagesDir = join(appDir, '.next', 'serverless') builtPage = (file) => join(builtServerPagesDir, file) }) @@ -295,19 +278,12 @@ describe('Font Optimization', () => { beforeAll(async () => { await fs.writeFile( nextConfig, - ` - const path = require('path') - module.exports = require(path.join(__dirname, '../../../../lib/with-react-17.js'))({ target: 'experimental-serverless-trace', cleanDistDir: false }) - `, + `module.exports = ({ target: 'experimental-serverless-trace', cleanDistDir: false })`, 'utf8' ) - await nextBuild(appDir, undefined, { - nodeArgs, - }) + await nextBuild(appDir) appPort = await findPort() - app = await startServerlessEmulator(appDir, appPort, { - nodeArgs, - }) + app = await startServerlessEmulator(appDir, appPort) builtServerPagesDir = join(appDir, '.next', 'serverless') builtPage = (file) => join(builtServerPagesDir, file) }) @@ -320,18 +296,14 @@ describe('Font Optimization', () => { describe('Font optimization for unreachable font definitions.', () => { beforeAll(async () => { - await nextBuild(appDir, undefined, { - nodeArgs, - }) + await nextBuild(appDir) await fs.writeFile( join(appDir, '.next', 'server', 'font-manifest.json'), '[]', 'utf8' ) appPort = await findPort() - app = await nextStart(appDir, appPort, { - nodeArgs, - }) + app = await nextStart(appDir, appPort) builtServerPagesDir = join(appDir, '.next', 'serverless') builtPage = (file) => join(builtServerPagesDir, file) }) diff --git a/test/integration/react-18-invalid-config/index.test.js b/test/integration/react-18-invalid-config/index.test.js index dc2f1e2c930cc..9e44ed847acda 100644 --- a/test/integration/react-18-invalid-config/index.test.js +++ b/test/integration/react-18-invalid-config/index.test.js @@ -11,7 +11,6 @@ import { } from 'next-test-utils' const appDir = __dirname -const nodeArgs = ['-r', join(appDir, '../../lib/react-17-require-hook.js')] const reactDomPackagePah = join(appDir, 'node_modules/react-dom') const nextConfig = new File(join(appDir, 'next.config.js')) const documentPage = new File(join(appDir, 'pages/_document.js')) @@ -52,7 +51,7 @@ describe('Invalid react 18 webpack config', () => { writeNextConfig({ runtime: 'edge', }) - const { stderr } = await nextBuild(appDir, [], { stderr: true, nodeArgs }) + const { stderr } = await nextBuild(appDir, [], { stderr: true }) nextConfig.restore() expect(stderr).toContain( @@ -76,7 +75,7 @@ describe('React 17 with React 18 config', () => { }) it('should warn user when not using react 18 and `experimental.reactRoot` is enabled', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true, nodeArgs }) + const { stderr } = await nextBuild(appDir, [], { stderr: true }) expect(stderr).toContain( 'You have to use React 18 to use `experimental.reactRoot`.' ) @@ -85,7 +84,6 @@ describe('React 17 with React 18 config', () => { it('suspense is not allowed in blocking rendering mode', async () => { const { stderr, code } = await nextBuild(appDir, [], { stderr: true, - nodeArgs, }) expect(stderr).toContain( 'Invalid suspense option usage in next/dynamic. Read more: https://nextjs.org/docs/messages/invalid-dynamic-suspense'