具有动态查询的Webpack加载器

Webpack Loader with Dynamic Query

本文关键字:Webpack 加载 查询 动态      更新时间:2024-03-11

我在我的Webpack配置中为SVG文件设置了一个Webpack加载程序,它看起来像这个

const SVGO_CONFIG = JSON.stringify({
  plugins: [
    {removeTitle: true},
  ],
});
const SVG_LOADER = {
  test: /'.svg$/,
  loader: 'babel!svg-react!svgo?' + SVGO_CONFIG,
};

这允许我将import svg文件视为像这样的反应组件

import Icon from 'src/images/icon.svg';

但在某些情况下,我希望能够告诉svgo-loader从文件中剥离fillstroke属性。我可以通过在配置中设置另一个插件来做到这一点

const SVGO_CONFIG = JSON.stringify({
  plugins: [
    {removeTitle: true},
    {removeAttrs: {attrs: "(fill|stroke)"}},
  ],
});

但这将适用于我导入的所有svg文件。有没有一种简单的方法可以标记导入语句来稍微修改配置?

import TransparentIcon from 'src/images/icon.svg?removeFill`;

我的一半解决方案是用额外的扩展名保存文件(或保存在不同的文件夹中),但这意味着我无法选择在删除或不删除属性的情况下导入它。

有两种方法:

  1. 在两个独立的SVG加载程序中使用test属性的regex,如下所示:

    const SVGO_CONFIG = JSON.stringify({
      plugins: [
        {removeTitle: true},
      ],
    });
    const SVG_LOADER = {
      test: /'.svg$/,
      loader: 'babel!svg-react!svgo?' + SVGO_CONFIG,
    };
    const SVGO_CONFIG_REMOVE_FILL = JSON.stringify({
      plugins: [
        {removeTitle: true},
        {removeAttrs: {attrs: "(fill|stroke)"}},
      ],
    });
    const SVG_LOADER_REMOVE_FILL = {
      test: /'.svg'?removeFill$/,
      loader: 'babel!svg-react!svgo?' + SVGO_CONFIG_REMOVE_FILL,
    };
    
  2. 您可以编写自己的加载程序来调整查询字符串。(这可能是过度工程化):

    module.exports = function(content) {
      return content;
    };
    module.exports.pitch = function(remainingRequest, precedingRequest, data) {
      var i;
      var len = this.loaders.length;
      var loader;
      if (this.resourceQuery === '?removeFill') {
        for (i = 0; i < len; i++) {
          loader = this.loaders[i];
          if (loader.query === '?{"plugins":[{"removeTitle":true}]}') {
            loader.query = '?' + JSON.stringify({
              plugins: [
                {removeTitle: true},
                {removeAttrs: {attrs: "(fill|stroke)"}},
              ],
            });
          }
        }
      }
    };
    

您可以为此目的使用include。示例:

const SVG_LOADER = {
  test: /'.svg$/,
  loader: 'babel!svg-react!svgo?' + SVGO_CONFIG,
  include: [path.join(__dirname, 'svgs/demo.svg', ...]
};

你需要两个像这样的独立规则。您应该确保它们的include不会重叠,否则它将同时执行这两个。解决这个问题的一个巧妙方法是将svg按目录拆分并指向这些目录。