我正在开发一个反应应用程序,现在已经扩展了几个主题。
这些主题在我的主题文件夹中的.scss
个文件中定义:
- themes
- - theme-base.scss
- - theme.dark.scss
- - theme.light.scss
它们包含带有一些变量的基本配色方案,例如:
[theme-dark.scss]
$color-primary: #100534;
$color-primary-accent: #231454;
所有组件只使用这些颜色变量来对其进行主题化。
现在我希望webpack编译并连接我的scss代码,以分离每个主题的静态css文件。
我通过使用extractWebpackTextPlugin和一些文件加载器来实现这一点:
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文件时抛出错误。
Invalid CSS after "...load the styles": expected 1 selector or at-rule, was "var content = requi"
我如何设置webpack来为每个主题编译一个静态css文件?
答案 0 :(得分:0)
我目前正在处理类似的问题,我试图在没有任何侵入性代码的情况下解决它。然后,我编写一个webpack插件themes-switch来做到这一点。它将根据主题目录提取主题。也许可以帮到您。
示例配置:
new ThemesGeneratorPlugin({
srcDir: 'src',
themesDir: 'src/assets/themes',
outputDir: 'static/css',
defaultStyleName: 'default.less',
themesLoader: {
test: /\.(less|css)$/,
loaders: [
{ loader: require.resolve('css-loader') },
{ loader: require.resolve('less-loader') }
]
}
})
现在,我仅使用变量来定义不同的颜色和尺寸,然后webpack会为我生成主题,并且样式格式可以更少,postcss和sass。然后,我可以在我的应用中进行实时切换。该插件将自动清除未使用的文件。
答案 1 :(得分:0)
我遇到了类似的问题,并且意识到发生错误是因为您不能有多个具有相同test: /\.s?css$/
条件的Webpack规则。第一个之后的所有内容都会出错。
要解决此问题,请为所有SCSS创建1条规则,然后将其他ExtractTextPlugin
实例推送到规则的oneOf
数组中。...
/ SASS文件夹
-- app.scss
-- custom/
---- /blue/theme.scss
---- /red/theme.scss
---- /default/theme.scss
---- ...
./src/sass/app.scss?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 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
加载适当的主题文件夹...
// load theme.scss from included path
@import "theme";
...
因此,每次以上forEach
碰到app.scss中的下一个themeKey
时,@import "theme"
都指向一个不同的子文件夹(蓝色,红色等),从而生成不同的CSS文件每个“主题”。