2016-07-14 93 views
6

我正在尝试使React应用程序成为主题。现在,主题只包含不同的sass变量集,这些变量定义了不同的标题颜色等。如何使用webpack提取多个主题样式表?

从我目前的理解来看,ExtractTextPlugin似乎是我最好的选择,因为我不希望我的样式被内联,而是分开每个主题的文件。

所以我创建了两个主题:

src/scss/themes/theme-a.scss 
src/scss/themes/theme-b.scss 

的主题导入的基本布局和常见的样式和覆盖相关的变量。

但是我设法让的WebPack创建单独的CSS文件 两个主题的唯一办法是在 每个主题制作不同的入口点我webpack.prod.config

entry: { 
    app: './src/js/init.js', 
    theme-a: './src/scss/themes/theme-a.scss', 
    theme-b: './src/scss/themes/theme-b.scss' 
}, 

但增加了对每一个新的切入点新增加的主题感觉不对,我认为必须有更好的方法?

+0

嗯,我相信你需要在'plugins'参考,类似'新ExtractTextPlugin( 'CSS/bundle.css')'。我没有看到人们把这些介绍入口。我只将CSS分隔成单个文件,但在这里查看,他似乎在示例中提取了2个文件(不管是css还是更少):https://github.com/webpack/extract-text-webpack-plugin#api – lux

+0

嗯,但添加多个插件实例而不是多个条目听起来不太舒服。如果可以告诉插件它为每个在特定的源/文件夹中遇到的scss文件分离出一个单独的css文件,那该多好。 – arie

回答

7

这里是您的解决方案:

npm i --save-dev file-loader 

loaders部分,补充一点:

{ 
    test: /themes\/.+\.scss$/, 
    loader: "file-loader?name=./compiled-themes/css/[name].css!css!sass" 
}, 

可能有更多的SCSS文件,如果是的话,必须有其捆绑他们像往常一样另一部分,但跳过主题:

{ 
    test: /\.scss$/, 
    exclude: /themes\/.+\.scss$/, 
    loader: "css!sass" 
}, 

文件加载器按文件名写入文件,散列a因此您可以保留名称。

注意name=./compiled-themes/css/[name].css部分,其中[]变量被替换。

https://github.com/webpack/file-loader

+0

为了澄清,文件加载器实际上是一个文件编写器,但它具有此加载器后缀根据webpack插件命名约定 –

+1

这看起来像一个非常好的解决方案! 我试图调整你的例子,编译的主题被创建。大! 但不知何故,这些文件不是纯粹的CSS组成,但包裹在一个模块 'exports = module.exports = require(“./../../../ node_modules/css-loader/lib/css-base.js“)();' '// imports' '// module' 'exports.push([module.id,”.ReactModal__Overlay {z-index:999; overflow:auto; margin: 0!important; padding:0 ...' 你有什么想法可能是这个问题? 我的装载线为主题如下所示: 'loader:“file-loader?name =。/ compile -themes/css/[name] .css!css!sass“' – arie

+0

'raw!saas'会做这个伎俩,我只是试了一下,你需要'npm我raw-loader' –

2

为避免必须手动添加主题,一种可能的解决方案是创建一个读取主题文件夹内容并以编程方式为每个* .scss文件添加条目的函数。沿此线

东西:

function getThemes(themePath) { 
    var themes = {}; 
    fs.readdirSync(themePath).forEach(function(fileName) { 
     var fileNameWithPath = path.join(themePath, fileName); 

     var stat = fs.lstatSync(fileNameWithPath); 
     if (stat.isDirectory()) return; 
     if (!/\.scss$/.test(fileName)) return; 

     var nameWithoutExt = path.basename(fileName, '.scss'); 
     themes[nameWithoutExt] = fileNameWithPath; 
    }); 

    return themes; 
} 

var themes = getThemes('./src/scss/themes'); 

var config= { 
    entry: _.merge({ app: './src/js/init.js' }, themes), 
    // rest of options 
}; 

这将要求您重新启动dev的服务器或重新运行在添加新的主题,虽然文件时的WebPack建设,但至少你不会有触摸你的webpack配置。

+0

此设置似乎导致为每个CSS文件以及CSS文件本身输出一个JS文件。有没有办法阻止JS文件被输出? – Giuseppe