Closed Vanuan closed 5 years ago
As a possible solution I see postcss-custom properties plugin to memoize whether it's the second time call and skip appendVariables logic.
A cleaner approach would be just to output a new css file with variables. Something like this:
const postCSSCustomProperties = require('postcss-custom-properties');
const symbolsParser = require('scss-symbols-parser');
...
const toObject = (arr, { keyName, valueName }) => {
return arr.reduce(
(object, arrayEl) => Object.assign(object, { [arrayEl[keyName]]: arrayEl[valueName] }), {}
);
};
const scssVarsToObject = (filename) => {
const scssParsed = symbolsParser.parseSymbols(
fs.readFileSync(path.resolve(filename), 'utf8')
);
const scssVars = toObject(scssParsed.variables, {
keyName: 'name',
valueName: 'value',
});
return scssVars;
};
const scssVarsToCssVar = (filename) => {
const dollarObj = scssVarsToObject(filename);
return toObject(
Object.entries(dollarObj).map(
(el) => [el[0].replace(/^\$/, ''), el[1]]
), {
keyName: '0',
valueName: '1'
}
);
};
...
module: {
rules: [
test: /colors\.scss$/,
use: new ExtractTextPlugin({
filename: 'colors.css',
allChunks: true
}).extract([{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]',
importLoaders: 1
},
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [postCSSCustomProperties({
appendVariables: true,
variables: scssVarsToCssVar('./css/variables/colors.scss'),
warnings: true,
noValueNotifications: true,
})],
},
},
]),
]
}
The use case here is to get scss files as a source of variables, convert it to css custom properties definitions and output it somewhere in html or css.
Wow, thanks for the detailed report, @Vanuan . I think the ability to export variables to a file seems very reasonable when PostCSS is running over multiple files.
Some background. It’s been difficult for PostCSS plugin authors (or, at least, me) to feel comfortable creating new files. First; PostCSS plugins try to do one thing and do it well, and that one thing typically involves manipulating the CSS AST. This means creating new files often feels out of scope. Second; there is no convention (that I know of) from Webpack, Gulp, Grunt, etc. that instructs authors as to how our libraries/plugins should distribute supplemental content, such as a css file with just the exported variables. While I’d love to see these bigger questions answered, I don’t want this to stop me from delivering this feature. Let me think.
And while I do that, @ai, @ben-eb, @RyanZim, do you have any ideas or insights?
I think there should be some way to emulate import or entry point. So that when extract-text-webpack-plugin (along with postcss-loader) encounters duplicate chunks it doesn't produce duplicate content.
The problem here is not putting variables to separate file but avoiding the duplication.
I'm using Webpack with postcss loader and extract text plugin. This results in postcss-custom-properties plugin to be called multiple times, for each imported css file.
So when appendVariables is set to true the appended ":root" section is duplicated multiple times in the resulted css. This slows down chrome dev tools and significally increases css file size.