From d6f4d53fb9b3dace5b67f9b116f8545a41a22ba8 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Fri, 8 Jan 2021 16:58:43 -0500 Subject: [PATCH 1/2] feat(css): add strictPostcssConfiguration flag --- packages/next/build/webpack-config.ts | 3 ++- packages/next/build/webpack/config/blocks/css/index.ts | 5 +---- packages/next/build/webpack/config/index.ts | 4 ++++ packages/next/build/webpack/config/utils.ts | 3 +++ packages/next/next-server/server/config.ts | 6 ++++++ 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 94f49a1b1cc85..882e231978e34 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1215,6 +1215,7 @@ export default async function getBaseWebpackConfig( assetPrefix: config.assetPrefix || '', sassOptions: config.sassOptions, productionBrowserSourceMaps: config.productionBrowserSourceMaps, + future: config.future, }) let originalDevtool = webpackConfig.devtool @@ -1337,7 +1338,7 @@ export default async function getBaseWebpackConfig( (e) => (e as any).__next_css_remove !== true ) } - } else { + } else if (!config.future.strictPostcssConfiguration) { await __overrideCssConfiguration(dir, !dev, webpackConfig) } diff --git a/packages/next/build/webpack/config/blocks/css/index.ts b/packages/next/build/webpack/config/blocks/css/index.ts index 1d4b85b7dfb27..549e061cb05fd 100644 --- a/packages/next/build/webpack/config/blocks/css/index.ts +++ b/packages/next/build/webpack/config/blocks/css/index.ts @@ -78,10 +78,7 @@ export const css = curry(async function css( const postCssPlugins = await getPostCssPlugins( ctx.rootDirectory, ctx.isProduction, - // TODO: In the future, we should stop supporting old CSS setups and - // unconditionally inject ours. When that happens, we should remove this - // function argument. - true + !ctx.future.strictPostcssConfiguration ) // CSS cannot be imported in _document. This comes before everything because diff --git a/packages/next/build/webpack/config/index.ts b/packages/next/build/webpack/config/index.ts index 7b110b8ddc11c..ece56c922d310 100644 --- a/packages/next/build/webpack/config/index.ts +++ b/packages/next/build/webpack/config/index.ts @@ -1,4 +1,5 @@ import webpack from 'webpack' +import { NextConfig } from '../../../next-server/server/config' import { base } from './blocks/base' import { css } from './blocks/css' import { ConfigurationContext, pipe } from './utils' @@ -13,6 +14,7 @@ export async function build( assetPrefix, sassOptions, productionBrowserSourceMaps, + future, }: { rootDirectory: string customAppFile: string | null @@ -21,6 +23,7 @@ export async function build( assetPrefix: string sassOptions: any productionBrowserSourceMaps: boolean + future: NextConfig['future'] } ): Promise { const ctx: ConfigurationContext = { @@ -37,6 +40,7 @@ export async function build( : '', sassOptions, productionBrowserSourceMaps, + future, } const fn = pipe(base(ctx), css(ctx)) diff --git a/packages/next/build/webpack/config/utils.ts b/packages/next/build/webpack/config/utils.ts index 28c08317e5466..d15a3f1d3db96 100644 --- a/packages/next/build/webpack/config/utils.ts +++ b/packages/next/build/webpack/config/utils.ts @@ -1,4 +1,5 @@ import webpack from 'webpack' +import { NextConfig } from '../../../next-server/server/config' export type ConfigurationContext = { rootDirectory: string @@ -14,6 +15,8 @@ export type ConfigurationContext = { sassOptions: any productionBrowserSourceMaps: boolean + + future: NextConfig['future'] } export type ConfigurationFn = ( diff --git a/packages/next/next-server/server/config.ts b/packages/next/next-server/server/config.ts index 8b8a50b1b1473..ba8b664dae66b 100644 --- a/packages/next/next-server/server/config.ts +++ b/packages/next/next-server/server/config.ts @@ -31,6 +31,11 @@ export type NextConfig = { [key: string]: any } & { redirects?: () => Promise trailingSlash?: boolean + + future: { + strictPostcssConfiguration: boolean + excludeDefaultMomentLocales: boolean + } } const defaultConfig: NextConfig = { @@ -83,6 +88,7 @@ const defaultConfig: NextConfig = { scriptLoader: false, }, future: { + strictPostcssConfiguration: false, excludeDefaultMomentLocales: false, }, serverRuntimeConfig: {}, From 04773f47b32ab60816fe54c45166bd67e436fd4f Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Fri, 8 Jan 2021 17:25:10 -0500 Subject: [PATCH 2/2] add tests --- .../css-customization/test/index.test.js | 33 +++++++++++++++++ .../next.config.js | 36 +++++++++++++++++++ .../pages/_app.js | 12 +++++++ .../pages/index.js | 3 ++ .../styles/global.css | 11 ++++++ 5 files changed, 95 insertions(+) create mode 100644 test/integration/css-fixtures/custom-configuration-webpack/next.config.js create mode 100644 test/integration/css-fixtures/custom-configuration-webpack/pages/_app.js create mode 100644 test/integration/css-fixtures/custom-configuration-webpack/pages/index.js create mode 100644 test/integration/css-fixtures/custom-configuration-webpack/styles/global.css diff --git a/test/integration/css-customization/test/index.test.js b/test/integration/css-customization/test/index.test.js index 015d5bfd20dcb..54034b9dd3cd3 100644 --- a/test/integration/css-customization/test/index.test.js +++ b/test/integration/css-customization/test/index.test.js @@ -108,6 +108,39 @@ describe('Legacy Next-CSS Customization', () => { }) }) +describe('Custom CSS Customization via Webpack', () => { + const appDir = join(fixturesDir, 'custom-configuration-webpack') + + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) + + it('should compile successfully', async () => { + const { code, stdout, stderr } = await nextBuild(appDir, [], { + stdout: true, + stderr: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) + expect(stderr).not.toMatch( + /Built-in CSS support is being disabled due to custom CSS configuration being detected/ + ) + }) + + it(`should've compiled and prefixed`, async () => { + const cssFolder = join(appDir, '.next/static/css') + + const files = await readdir(cssFolder) + const cssFiles = files.filter((f) => /\.css$/.test(f)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot( + `"@media (480px <= width < 768px){::placeholder{color:green}}.video{max-width:400px;max-height:300px}"` + ) + }) +}) + describe('CSS Customization Array', () => { const appDir = join(fixturesDir, 'custom-configuration-arr') diff --git a/test/integration/css-fixtures/custom-configuration-webpack/next.config.js b/test/integration/css-fixtures/custom-configuration-webpack/next.config.js new file mode 100644 index 0000000000000..567e9738538e0 --- /dev/null +++ b/test/integration/css-fixtures/custom-configuration-webpack/next.config.js @@ -0,0 +1,36 @@ +module.exports = { + onDemandEntries: { + maxInactiveAge: 1000 * 60 * 60, + }, + webpack(config) { + modifyLoaderConfig( + config.module.rules, + [/(? { + if (!Array.isArray(rule.use)) return + rule.use.forEach((u) => { + if (u.options.postcssOptions) { + u.options.postcssOptions.plugins = [ + require('postcss-short-size')({ + // Add a prefix to test that configuration is passed + prefix: 'xyz', + }), + ] + } + }) + } + ) + + return config + }, + future: { strictPostcssConfiguration: true }, +} + +function modifyLoaderConfig(rules, regexes, cb) { + rules.forEach((rule) => { + if (rule.oneOf) return modifyLoaderConfig(rule.oneOf, regexes, cb) + regexes.forEach((regex) => { + if (rule.test && rule.test.toString() === regex.toString()) cb(rule) + }) + }) +} diff --git a/test/integration/css-fixtures/custom-configuration-webpack/pages/_app.js b/test/integration/css-fixtures/custom-configuration-webpack/pages/_app.js new file mode 100644 index 0000000000000..17a2196742e95 --- /dev/null +++ b/test/integration/css-fixtures/custom-configuration-webpack/pages/_app.js @@ -0,0 +1,12 @@ +import React from 'react' +import App from 'next/app' +import '../styles/global.css' + +class MyApp extends App { + render() { + const { Component, pageProps } = this.props + return + } +} + +export default MyApp diff --git a/test/integration/css-fixtures/custom-configuration-webpack/pages/index.js b/test/integration/css-fixtures/custom-configuration-webpack/pages/index.js new file mode 100644 index 0000000000000..b3ba78da2d5e1 --- /dev/null +++ b/test/integration/css-fixtures/custom-configuration-webpack/pages/index.js @@ -0,0 +1,3 @@ +export default function Home() { + return
+} diff --git a/test/integration/css-fixtures/custom-configuration-webpack/styles/global.css b/test/integration/css-fixtures/custom-configuration-webpack/styles/global.css new file mode 100644 index 0000000000000..f942036ad16ef --- /dev/null +++ b/test/integration/css-fixtures/custom-configuration-webpack/styles/global.css @@ -0,0 +1,11 @@ +/* this should pass through untransformed */ +@media (480px <= width < 768px) { + ::placeholder { + color: green; + } +} + +/* this should be transformed to width/height */ +.video { + -xyz-max-size: 400px 300px; +}