如何使用 webpack 提取多个主题样式表?

Posted

技术标签:

【中文标题】如何使用 webpack 提取多个主题样式表?【英文标题】:How to extract multiple theme stylesheets with webpack? 【发布时间】:2016-11-17 22:37:22 【问题描述】:

我正在尝试使 React 应用程序主题化。目前,主题仅由定义不同标题颜色等的不同 Sass 变量集组成。

根据我目前的理解,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'
,

但是为每个添加的新主题添加一个新的入口点感觉不对,我认为一定有更好的方法吗?

【问题讨论】:

嗯,我相信你需要plugins中的引用,类似于new ExtractTextPlugin('css/bundle.css')。我还没有看到有人把这些介绍entry。我只将 CSS 分成一个文件,但在这里查看,他似乎在示例中提取了 2 个文件(无论是 css 还是更少):github.com/webpack/extract-text-webpack-plugin#api 嗯,但是添加多个插件实例而不是多个条目听起来不太舒服。如果可以告诉插件它为在某个源/文件夹中遇到的每个 scss 文件生成一个单独的 css 文件,那该多好。 【参考方案1】:

为避免手动添加主题,一种可能的解决方案是创建一个函数,该函数读取主题文件夹的内容并以编程方式为每个 *.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
;

这将要求您在添加新主题文件时重新启动您的开发服务器或重新运行您的 webpack 构建,但至少您不必修改您的 webpack 配置。

【讨论】:

这种设置似乎会导致为每个 CSS 文件以及 CSS 文件本身输出一个 JS 文件。有什么办法可以阻止js文件被输出?【参考方案2】:

这是您的解决方案:

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"
,

文件加载器按文件名、哈希和扩展名写入文件,因此您可以保留名称。

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

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

【讨论】:

澄清一下,file-loader 实际上是一个文件编写器,但是根据 webpack 插件命名约定,它有这个 -loader 后缀 这看起来是一个非常好的解决方案!我试图调整您的示例并创建编译的主题。伟大的!但不知何故,这些文件不是由纯 css 组成,而是包装在一个模块中 exports = module.exports = require("./../../../node_modules/css-loader/lib/css-base.js")(); // imports // module exports.push([module.id, ".ReactModal__Overlayz-index:999;overflow:auto;margin:0!important;padding:0... 你知道可能是什么问题吗?我的主题加载器行如下所示:loader: "file-loader?name=./compiled-themes/css/[name].css!css!sass" raw!saas 可以解决问题。我刚试过。你需要npm i raw-loader 啊!不知何故,我什至不需要原始加载器。我只需要省略 css-loader。 有没有办法让它正常工作?如果我使用建议的设置,我会像上面的 Tudor 那样在 css 中获得 JS 输出。我无法取出 css-loader,因为我在 CSS 中的 url 输出不正确。

以上是关于如何使用 webpack 提取多个主题样式表?的主要内容,如果未能解决你的问题,请参考以下文章

如何应用多个 jQuery UI 主题

webpack 4:创建多个主题 css 文件

提取主题感知样式的 CSS 差异

如何使用 webpack、typescript、phaser 和 angular 配置全局 css 和 sass 样式表

Webpack:从相同的源生成多个 css 文件

Webpack + postcss + 主题 + 热加载