问题描述
我正在开发一个 React 应用,现在扩展了几个主题.
I am developing a react app, that is now extended by several themes.
这些主题在我的主题文件夹中的 .scss
文件中定义:
These themes are defined in .scss
files in my themes folder:
- themes
- - theme-base.scss
- - theme.dark.scss
- - theme.light.scss
它们包含带有一些变量的基本配色方案,例如:
they contain basic color schemes with some variables, eg:
[theme-dark.scss]
$color-primary: #100534;
$color-primary-accent: #231454;
所有组件都只是使用这些颜色变量来为它们设置主题.
All components just use these color variables to theme them.
现在我想让 webpack 编译并连接我的 scss 代码,以便为每个主题分隔静态 css 文件.
Now I want webpack to compile and concat my scss code to separate static css files for each theme.
我通过使用 extractWebpackTextPlugin 和一些像这样的文件加载器来实现它:
I got this to work by using extractWebpackTextPlugin and some file loaders like this:
module.exports = env => {
const config = require('./webpack.common')(env);
const project = env.project;
const postcss = {
loader: 'postcss-loader',
options: postcssConfig(settings.browsers),
};
config.watch = true;
config.devtool = 'eval';
const themes = ['theme-base'];
themes.forEach(themeKey => {
const themeInstance = new ExtractTextPlugin('css/' + themeKey + '.css');
const themePath = path.resolve(__dirname, '../../react/app/css/_' + themeKey + '.scss');
config.module.rules.push({
test: /\.s?css$/,
exclude: /node_modules/,
use: themeInstance.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
localIdentName: '[hash:base64:5]',
modules: true,
importLoaders: 1,
}
},
postcss,
{
loader: 'sass-loader',
options: {
data: `@import "${themePath}";`,
}
}
]
}),
});
config.plugins.push(themeInstance);
});
}
但是:我不能向我的数组 themes
添加多个主题!一旦它包含多个项目,css 和 sass 加载器就会在读取 scss 文件时抛出错误.
But:I can not add more than one theme to my array themes
! As soon as it contains more than one item, the css and sass loaders throw errors while reading the scss files.
...加载样式"后的 CSS 无效:预期为 1 选择器或规则,为var content = requi"
如何设置 webpack 为每个主题编译一个静态 css 文件?
How would I setup webpack to compile one static css file for each theme?
推荐答案
我遇到了类似的问题,并意识到错误的发生是因为您不能拥有多个具有相同 test:/\.s? 的 Webpack 规则?css$/
条件.第一个之后的任何内容都会出错.
I had a similar issue and realized that the error occurs because you can't have multiple Webpack rules with the same test: /\.s?css$/
condition. Anything after the first will error out.
为了解决这个问题,而是为所有 SCSS 创建 1 个规则,并将额外的 ExtractTextPlugin
实例推送到规则的 oneOf
数组....
To solve this instead create 1 rule for all of the SCSS, and the push the additional ExtractTextPlugin
instances to the rules' oneOf
array....
/SASS 文件夹
-- app.scss
-- custom/
---- /blue/theme.scss
---- /red/theme.scss
---- /default/theme.scss
---- ...
./src/sass/app.scss?theme
条目是默认/第一个主题.
The ./src/sass/app.scss?theme
entry is the default/first theme.
var themeDefault = "default";
module.exports = {
entry: ['./src/app.js','./src/sass/app.scss?theme'],
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'app.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{
test: /\.scss$/,
oneOf: [ // use oneOf since we'll need diff rules/handlers for each .scss
{
resourceQuery: /theme/,
use: extractSass.extract({
use: [
{
loader: "css-loader"
},
{
loader: "sass-loader",
options: {
allChunks: true,
sourceMap: true,
includePaths: [
'./src/sass/custom/'+themeDefault
]
}
}]
})
}
],
},
...
]
},
plugins: [
extractSass
],
...
}
迭代/custom 文件夹中的每个主题.
Iterate each theme in the /custom folder.
// iterate themes to add an entry point, rule and plugin instance for each
fs.readdirSync('./src/sass/custom').filter(f => fs.statSync("./src/sass/custom/"+f).isDirectory()).forEach(themeKey => {
const themeInstance = new ExtractTextPlugin('css/' + themeKey + '.css');
module.exports.entry.push('./src/sass/app.scss?'+themeKey);
// the SCSS rule is at index 1 in the rules array
module.exports.module.rules[1].oneOf.push(
{
resourceQuery: new RegExp(themeKey),
use: themeInstance.extract({
use: [
{
loader: "css-loader"
},
{
loader: "sass-loader",
options: {
allChunks: true,
includePaths: [
'./src/sass/custom/'+themeKey
]
}
}]
})
});
module.exports.plugins.push(themeInstance);
});
然后在app.scss
中,从Webpack sass-loader指定的includePaths
中加载相应的主题文件夹...
And then in the app.scss
, the appropriate theme folder is loaded from the includePaths
specified in Webpack sass-loader...
// load theme.scss from included path
@import "theme";
...
因此,每次上面的 forEach
命中下一个 themeKey
时,app.scss 中的 @import "theme"
指向不同的子文件夹(蓝色、红色等)导致每个主题"产生不同的 CSS 文件.
Therefore, each time the forEach
above hits the next themeKey
the @import "theme"
in app.scss point to a different sub folder (blue,red,etc) resulting in different CSS files for each "theme".
这篇关于如何配置 webpack 生成单独的 css 主题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!