Skip to content

Commit

Permalink
feat(webpack): support passing function as postcssOptions (#19495)
Browse files Browse the repository at this point in the history
  • Loading branch information
obulat committed Jun 9, 2023
1 parent f842c75 commit 3e4284e
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 7 deletions.
21 changes: 14 additions & 7 deletions packages/webpack/src/utils/postcss.js
Expand Up @@ -154,7 +154,7 @@ export default class PostcssConfig {
* @param postcssOptions
* @returns {{ postcssOptions: { plugins?: unknown, order?: string, preset?: any} }}
*/
normalize (postcssOptions) {
normalize (postcssOptions, warnAboutTopLevelDeprecation = true) {
// TODO: Remove in Nuxt 3
if (Array.isArray(postcssOptions)) {
consola.warn('Using an Array as `build.postcss` will be deprecated in Nuxt 3. Please switch to the object' +
Expand All @@ -168,12 +168,19 @@ export default class PostcssConfig {
return { postcssOptions: {} }
}
if (postcssOptions.postcssOptions && typeof postcssOptions.postcssOptions === 'function') {
consola.warn('Using a Function as `build.postcss.postcssOptions` is not yet supported in Nuxt 2.16.2')
return { postcssOptions: {} }
const postcssOptionsFn = postcssOptions.postcssOptions
return {
postcssOptions: (loaderContext) => {
const result = this.normalize(postcssOptionsFn(loaderContext), false)
if (result) {
return result.postcssOptions
}
}
}
}
if (!('postcssOptions' in postcssOptions)) {
if (Object.keys(postcssOptions).length > 0) {
consola.warn('Using the top-level properties in `build.postcss` will be deprecated in Nuxt 3. Please move' +
if (Object.keys(postcssOptions).length > 0 && warnAboutTopLevelDeprecation) {
consola.warn('Using the top-level properties in `build.postcss` will be deprecated in Nuxt 3. Please move ' +
'the settings to `postcss.postcssOptions`')
}
postcssOptions = { postcssOptions }
Expand Down Expand Up @@ -211,7 +218,7 @@ export default class PostcssConfig {

/**
* Load plugins from postcssOptions
* @param {{ postcssOptions: {plugins?: unknown, order?: string | function}}} postcssOptions
* @param {{ postcssOptions: {plugins?: unknown, order?: string | function }}} postcssOptions
*/
loadPlugins (postcssOptions) {
const { plugins, order } = postcssOptions.postcssOptions
Expand Down Expand Up @@ -252,7 +259,7 @@ export default class PostcssConfig {

if (Array.isArray(postcssOptions.postcssOptions.plugins)) {
defaults(postcssOptions.postcssOptions.plugins, this.defaultPostcssOptions.plugins)
} else {
} else if (typeof postcssOptions.postcssOptions !== 'function') {
// Merge all plugins and use preset for setting up postcss-preset-env
if (postcssOptions.postcssOptions.preset) {
if (!postcssOptions.postcssOptions.plugins) {
Expand Down
55 changes: 55 additions & 0 deletions packages/webpack/test/postcss.test.js
@@ -0,0 +1,55 @@
import { join } from 'node:path'
import PostcssConfig from '../src/utils/postcss'

describe('webpack: postcss', () => {
const getConfigWithPostcssConfig = config =>
new PostcssConfig({
options: {
dev: false,
srcDir: join(__dirname),
rootDir: join(__dirname),
modulesDir: []
},
nuxt: {
resolver: {
requireModule: plugin => opts => [plugin, opts]
}
},
buildOptions: {
postcss: config
}
})

test('should have the right default configuration', () => {
// Use the default postcss config: stage 2
// https://cssdb.org/#staging-process
const pluginConfig = Object.fromEntries(
getConfigWithPostcssConfig({ postcssOptions: {} }).config().postcssOptions.plugins
)
expect(pluginConfig).toMatchInlineSnapshot(`
{
"cssnano": {
"preset": [
"default",
{
"minifyFontValues": {
"removeQuotes": false,
},
},
],
},
"postcss-import": {
"resolve": [Function],
},
"postcss-preset-env": {},
"postcss-url": {},
}
`)
})
test('can pass a function through', () => {
// Use the default postcss config: stage 2
// https://cssdb.org/#staging-process
const options = getConfigWithPostcssConfig({ postcssOptions: () => ({ preset: { stage: 2 } }) }).config().postcssOptions
expect(typeof options).toBe('function')
})
})
32 changes: 32 additions & 0 deletions test/dev/postcss-function.test.js
@@ -0,0 +1,32 @@
import { getPort, loadFixture, Nuxt } from '../utils'

let port
const url = route => 'http://localhost:' + port + route

let nuxt = null

describe('postcss configuration as function', () => {
beforeAll(async () => {
const options = await loadFixture('postcss-function')
nuxt = new Nuxt(options)
await nuxt.ready()

port = await getPort()
await nuxt.server.listen(port, '0.0.0.0')
})

for (const path of ['/css', '/postcss']) {
test(path, async () => {
const window = await nuxt.server.renderAndGetWindow(url(path))

const headHtml = window.document.head.innerHTML
expect(headHtml.replace(/\s+/g, '').replace(/;}/g, '}')).toContain('div.red{background-color:blue}.red{color:red}')

const element = window.document.querySelector('.red')
expect(element).not.toBe(null)
expect(element.textContent).toContain('This is red')
expect(element.className).toBe('red')
// t.is(window.getComputedStyle(element).color, 'red')
})
}
})
16 changes: 16 additions & 0 deletions test/fixtures/postcss-function/nuxt.config.js
@@ -0,0 +1,16 @@
const createData = async () => {
await new Promise(resolve => setTimeout(resolve, 500))
return {
build: {
postcss: {
postcssOptions: () => ({
plugins: [
['postcss-preset-env', { features: { 'custom-selectors': true } }]
]
})
}
}
}
}

export default createData
15 changes: 15 additions & 0 deletions test/fixtures/postcss-function/pages/css.vue
@@ -0,0 +1,15 @@
<template>
<div class="red">
This is red
</div>
</template>

<style>
@custom-selector :--red div.red;
:--red {
background-color: blue;
}
.red {
color: red;
}
</style>
15 changes: 15 additions & 0 deletions test/fixtures/postcss-function/pages/postcss.vue
@@ -0,0 +1,15 @@
<template>
<div class="red">
This is red
</div>
</template>

<style lang="postcss">
@custom-selector :--red div.red;
:--red {
background-color: blue;
}
.red {
color: red;
}
</style>
3 changes: 3 additions & 0 deletions test/fixtures/postcss-function/postcss-function.test.js
@@ -0,0 +1,3 @@
import { buildFixture } from '../../utils/build'

buildFixture('postcss-function')

0 comments on commit 3e4284e

Please sign in to comment.