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

feat(webpack): support passing function as postcssOptions #19495

Merged
merged 12 commits into from Jun 9, 2023
Merged
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')