diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index 7f308632333f525..e55eafd73d1d13b 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -9,7 +9,7 @@ import { escapeStringRegexp } from '../shared/lib/escape-regexp' import findUp from 'next/dist/compiled/find-up' import { nanoid } from 'next/dist/compiled/nanoid/index.cjs' import { pathToRegexp } from 'next/dist/compiled/path-to-regexp' -import path from 'path' +import path, { join } from 'path' import formatWebpackMessages from '../client/dev/error-overlay/format-webpack-messages' import { STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR, @@ -89,7 +89,6 @@ import { PageInfo, printCustomRoutes, printTreeView, - getCssFilePaths, getUnresolvedModuleFromError, copyTracedFiles, isReservedPage, @@ -1364,10 +1363,22 @@ export default async function build( await writeBuildId(distDir, buildId) if (config.experimental.optimizeCss) { - const cssFilePaths = getCssFilePaths(buildManifest) + const globOrig = + require('next/dist/compiled/glob') as typeof import('next/dist/compiled/glob') + + const cssFilePaths = await new Promise((resolve, reject) => { + globOrig('**/*.css', { cwd: join(distDir, 'static') }, (err, files) => { + if (err) { + return reject(err) + } + resolve(files) + }) + }) requiredServerFiles.files.push( - ...cssFilePaths.map((filePath) => path.join(config.distDir, filePath)) + ...cssFilePaths.map((filePath) => + path.join(config.distDir, 'static', filePath) + ) ) } diff --git a/packages/next/build/utils.ts b/packages/next/build/utils.ts index e03721527c60634..6c4ea4a0d7089f5 100644 --- a/packages/next/build/utils.ts +++ b/packages/next/build/utils.ts @@ -1103,19 +1103,6 @@ export function detectConflictingPaths( } } -export function getCssFilePaths(buildManifest: BuildManifest): string[] { - const cssFiles = new Set() - Object.values(buildManifest.pages).forEach((files) => { - files.forEach((file) => { - if (file.endsWith('.css')) { - cssFiles.add(file) - } - }) - }) - - return [...cssFiles] -} - export function getRawPageExtensions(pageExtensions: string[]): string[] { return pageExtensions.filter( (ext) => !ext.startsWith('client.') && !ext.startsWith('server.') diff --git a/test/integration/critical-css/components/hello.js b/test/integration/critical-css/components/hello.js new file mode 100644 index 000000000000000..018641433828b64 --- /dev/null +++ b/test/integration/critical-css/components/hello.js @@ -0,0 +1,5 @@ +import styles from './hello.module.css' + +export default function Hello() { + return

hello world

+} diff --git a/test/integration/critical-css/components/hello.module.css b/test/integration/critical-css/components/hello.module.css new file mode 100644 index 000000000000000..aa586c7e9cff305 --- /dev/null +++ b/test/integration/critical-css/components/hello.module.css @@ -0,0 +1,3 @@ +.hello { + color: orange; +} diff --git a/test/integration/critical-css/pages/another.js b/test/integration/critical-css/pages/another.js new file mode 100644 index 000000000000000..77c5991743842b7 --- /dev/null +++ b/test/integration/critical-css/pages/another.js @@ -0,0 +1,21 @@ +import styles from '../styles/index.module.css' +import dynamic from 'next/dynamic' + +const Hello = dynamic(() => import('../components/hello')) + +export default function Home() { + return ( +
+

Hello World

+ +
+ ) +} + +export const getServerSideProps = () => { + return { + props: { + hello: 'world', + }, + } +} diff --git a/test/integration/critical-css/pages/index.js b/test/integration/critical-css/pages/index.js index c9d02372f123e5d..5b3e2c75f4ef89e 100644 --- a/test/integration/critical-css/pages/index.js +++ b/test/integration/critical-css/pages/index.js @@ -1,9 +1,11 @@ import styles from '../styles/index.module.css' +import Hello from '../components/hello' export default function Home() { return (

Hello World

+
) } diff --git a/test/integration/critical-css/test/index.test.js b/test/integration/critical-css/test/index.test.js index 502f4e839733133..2c1469866c4c43b 100644 --- a/test/integration/critical-css/test/index.test.js +++ b/test/integration/critical-css/test/index.test.js @@ -1,5 +1,6 @@ /* eslint-env jest */ - +import globOrigig from 'glob' +import { promisify } from 'util' import { join } from 'path' import { killApp, @@ -10,12 +11,29 @@ import { } from 'next-test-utils' import fs from 'fs-extra' +const glob = promisify(globOrigig) const appDir = join(__dirname, '../') const nextConfig = join(appDir, 'next.config.js') let appPort let app function runTests() { + it('should have all CSS files in manifest', async () => { + const cssFiles = ( + await glob('**/*.css', { + cwd: join(appDir, '.next/static'), + }) + ).map((file) => join('.next/static', file)) + + const requiredServerFiles = await fs.readJSON( + join(appDir, '.next/required-server-files.json') + ) + + expect( + requiredServerFiles.files.filter((file) => file.endsWith('.css')) + ).toEqual(cssFiles) + }) + it('should inline critical CSS', async () => { const html = await renderViaHTTP(appPort, '/') expect(html).toMatch( @@ -24,6 +42,14 @@ function runTests() { expect(html).toMatch(/body{font-family:SF Pro Text/) }) + it('should inline critical CSS (dynamic)', async () => { + const html = await renderViaHTTP(appPort, '/another') + expect(html).toMatch( + // + ) + expect(html).toMatch(/body{font-family:SF Pro Text/) + }) + it('should not inline non-critical css', async () => { const html = await renderViaHTTP(appPort, '/') expect(html).not.toMatch(/.extra-style/) @@ -45,22 +71,10 @@ describe('CSS optimization for SSR apps', () => { appPort = await findPort() app = await nextStart(appDir, appPort) }) - afterAll(() => killApp(app)) - runTests() -}) - -describe('CSS optimization for serverless apps', () => { - beforeAll(async () => { - await fs.writeFile( - nextConfig, - `module.exports = { target: 'serverless', experimental: {optimizeCss: true} }`, - 'utf8' - ) - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) + afterAll(async () => { + await killApp(app) + await fs.remove(nextConfig) }) - afterAll(() => killApp(app)) runTests() })