-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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(postcss-loader): support passing in a function for postcss definition #8899
Conversation
in postcss@v8 "PostcssPlugin" is not a generic, but in postcss@v7 it is. As postcss@v7 is the default right now, but postcss@8 is supported, we need to ignore this "type conflict" right now
this.postcssOptions(loaderContext) | ||
) | ||
this.loadPlugins(postcssOptions) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems we are losing part of features comparted to non function mode (preset
, execute
) (and it might be source of more inconsistent behavior in the future)
Can we maybe convert L200:221 (isPureObject(postcssOptions))
) into an inline function to immediately call and return or delay to use by function wrapper to get context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.. we could wrap some parts in a function wrapper, but the main "problem" here is that preset and execute needs to be evaluated "at beginning" and not when the function itself is executed. The only return type the function can give is the "postcssOptions" itself as an object.
Therefore I would propose to allow a config like this:
postcss: {
execute: true,
order: 'presetEnvAndCssnanoLast',
preset: {
stage: 2
},
postcssOptions: // config or function.. well of course old plugins can still be used, but to keep it easier I would suggest also allowing setting configs inside this object too.
}
I will commit my idea, let me know what you think of it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems a nice idea just maybe we can use postcss.options
or postcss.postcssOptions
for new options passing/function possibility? (avoid two top level options for postcss)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@simllll Since linked issue is related to postcss < 8 (current) shall we support same feature in
postcss.js
util?
Could be possible, but it needs postcss-loader >= 4.x, see release notes https://github.com/webpack-contrib/postcss-loader/releases/tag/v4.0.0
and I couldn't run nuxt with postcss-loader 4.x without postcss8. Therefore I guess it's not really necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems a nice idea just maybe we can use
postcss.options
orpostcss.postcssOptions
for new options passing/function possibility? (avoid two top level options for postcss)
Not quite sure what you mean, is postcssOptions
good or should I go with options
instead?
I just finished some small tests, looks good to me. Fully backwards compatible and no duplicate code anymore :)
79c1c0a
to
0605dd5
Compare
@simllll Since linked issue is related to postcss < 8 (current) shall we support same feature in |
0605dd5
to
62bcf99
Compare
62bcf99
to
50c15e0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually we did some nomralization logic here for backward compatibility, the build.postcss
will be passed as postcssOptions
of postcss-loader v4, so we won't have postcssOptions.postcssOptions
.
export default {
build: {
postcss: {
plugins: {
'postcss-short': { prefix: 'x' },
}
}
}
}
// Will be
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
['postcss-short', { prefix: 'x' }],
],
},
},
},
Based on the above, I think we can just support build.postcss
as function which is same as postcss-loader.
export default {
build: {
postcss() {
// ...
}
}
}
// Will be
{
loader: "postcss-loader",
options: {
postcssOptions() {
// ...
}
},
},
hi @clarkdo, thanks for your review. Actually your comment was pretty much the same as my first implementation, but as @pi0 stated correctly, this will loose some magic nuxt can do for us. E.g. execute, preset,.. because "postcss" is defined with a function, and you cannot define additional properties to it. Therefore I was thinking how we could make this "better". By adding a new config option, which is used as postcssOptions if defined. (either a functino or an object), but everything stays the same when this option is not defined.
the nice thing on this is, that it's also easy possible to describe what are nuxt special options, and what are postcss "native" options, and they also can not conflict. |
Sorry, I did't follow all of your discussions carefully, I'm just thinking export default {
build: {
postcss: {
plugins: {
'postcss-short': { prefix: 'x' }
},
postcssOptions: {
plugins: [
['postcss-short': { prefix: 'x' }]
]
}
}
} And it will be much harder to deal with things like order and options of plugins: export default {
build: {
postcss: {
preset: {
stage: 2
},
postcssOptions: {
plugins: [
['postcss-preset-env': { stage: 1 }]
]
}
}
} And also cc @pi0 |
As far as I understand, there are two concercn about using the "postcss" parameter as a function. First, we are actually talking aobut the postcss-loader here, which has an object as input, see: one of the options is postcssOptions. so putting a function here directly, would break two things: therefore I would still suggest adding an additional "options" property, and would make them actually the same like postcss-loader has it already. |
I see both points :)
We can always return a function to pass to loader for
Config types would be like this: // type for build.postcss
interface NuxtPostcssOptions extends PostCSSOptions {
execute: Boolean
sourceMap: Boolean
postcssOptions: PostCSSOptions | ((ctx: any) => PostCSSOptions)
} |
Just to clarify, are we gonna support ? export default {
build: {
postcss: {
// puglins and preset here can be from user or our default config
plugins: {
'postcss-import': {},
'postcss-url': {},
cssnano: true
},
preset: {
stage: 2,
...
},
postcssOptions: {
plugins: [
['postcss-import': { prefix: 'x' }],
['postcss-short': { prefix: 'x' }],
['postcss-url': {}],
['postcss-preset-env': { ... }]
]
}
}
}
} What the finial config will be like in this case ?
I agree with the additional "options" property, what I concern is we should remove |
I agree with @clarkdo , to make things future proof I would suggest deprecating the old "root" options for
see here https://github.com/nuxt/nuxt.js/pull/8899/files#diff-9613feda5d5173514c3656904bb88e5a8545c01dcacdc2e6c74cf476435a60e3R175 for the function method Following up on @clarkdo's example, this means: export default {
build: {
postcss: {
// puglins and preset here can be from user or our default config
plugins: { // <-- this is NOT used in this case
'postcss-import': {},
'postcss-url': {},
cssnano: true
},
preset: {
stage: 2,
...
},
postcssOptions: {
plugins: [ // <-- ONLY this one is used, but regardless if function or object, defaults are applied
['postcss-import': { prefix: 'x' }],
['postcss-short': { prefix: 'x' }],
['postcss-url': {}],
['postcss-preset-env': { ... }]
]
}
}
}
} |
As this still blocks us from upgrading to postcss8, is there anything to help to get this thing going? :) |
any news on this? |
@pi0 hs created a module for postcss 8 https://github.com/nuxt/postcss8 , what do you think moving the logic to the module as a new feature? |
@clarkdo I was just looking into the postcss8 module, but it only adapts some configs, it hasn't included the webpack (webpack/src/utils/postcss-v8.js) configuration, therefore adding it to the module is not possible in my opinion, it needs to be part of the webpack postcss-v8.js implementation. |
Codecov Report
@@ Coverage Diff @@
## dev #8899 +/- ##
==========================================
- Coverage 65.10% 64.97% -0.13%
==========================================
Files 94 94
Lines 4098 4106 +8
Branches 1121 1124 +3
==========================================
Hits 2668 2668
- Misses 1152 1157 +5
- Partials 278 281 +3
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
Any chance to get this into nuxt2 or/and nuxt 3? :) I'm eager to find out due to the reason that the approach we are using right now (external postcss file) produces a warning that this will not be possible in nuxt 3... |
We can change webpack config in module and it's acutally doing by some modules, I think we can leverage build.exntend in nuxt.config to call the customized function you defined for postcss and change the postcss-loader options. |
i love this |
Hi, What's the status of this PR? It's really desired especially after support of external postcss config file is dropped on Nuxt@3 |
@simllll Would you like to update this PR now that we've updated to PostCSS 8 natively in 2.16? 🙏 |
@simllll, @danielroe, can we do anything to make this PR land? This would unblock our migration to Nuxt 2.16 (and to Nuxt 3 in the future) by fixing the issue I described in #19482 |
Yes, absolute fine to me, no worries :-) i would do it myself, unfortunately couldn't find time yet and the issue itself is not relevant anymore to us... ;-) |
…ition This is an updated version of nuxt#8899
implemented in #19495 |
Issue
Postcssconfig can either be an object (already supported) or a function which gets passed in the loadercontext. But nuxt does not support passing in a function currently.
Why
Passing in a function allows more complex uses cases, e.g. by applying different postcss steps for different ressources. (see also https://github.com/webpack-contrib/postcss-loader#function)
Solution
This approach adds a new "postcssConfig" option to the "postcss" nuxt config. Either this is the regular postcssConfig, or it is a function. see https://webpack.js.org/loaders/postcss-loader/#postcssoptions
(only works with postcss@8, because postcss-loader >= 4.0 is required, and postcss7 nuxt setup conflicts with this version of postcss-loader)
e.g.
nuxt.config.js.
this closes #7015
Types of changes
Description
If postcss config is a function, we execute the custom function, but we also apply the default config of nuxt. Therefore we can assure that the config has a minimum default.
Checklist:
The postcss option can also have a function.
nope, as this is a advanced use case, I'm not quite sure where to add a appropiat test or if there is even a test really needed?