single-spa / create-single-spa

https://single-spa.js.org/docs/create-single-spa
Other
128 stars 60 forks source link

Extract svg into own loader for easier overrides #353

Closed filoxo closed 1 year ago

filoxo commented 2 years ago

I was helping someone in the single-spa Slack who was having issues with conflicting SVG loaders. Our webpack config includes svgs in the list of images to process as resources, so its difficult to define a different loader for SVGs. SVGs are also very commonly imported as React components so this is a valuable usecase to accommodate. Prior to this change, one would need to filter out the problematic rule and the provide their own.

const { mergeWithCustomize, customizeArray } = require("webpack-merge");
const singleSpaDefaults = require("webpack-config-single-spa-react-ts");

const mergeCustom = mergeWithCustomize({
  customizeArray: customizeArray({
    "module.rules": "replace"
  })
});

module.exports = (webpackConfigEnv, argv) => {
  const defaultConfig = singleSpaDefaults({
    orgName: "abcde",
    projectName: "fghij",
    webpackConfigEnv,
    argv
  });

  const rules = defaultConfig.module.rules.map((rule) => {
    if (rule.test.toString().includes("svg")) {
      // remove svg from list of file types
      rule.test = /\.(bmp|png|jpg|jpeg|gif|webp)$/i;
    }
    return rule;
  });

  const finalConfig = mergeCustom(defaultConfig, {
    module: {
      rules: [
        ...rules,
        {
          test: /\.svg$/i,
          use: [
            {
              loader: "@svgr/webpack",
              options: {
                typescript: true
              }
            }
          ]
        }
      ]
    }
  });

  return finalConfig;
};

After this change, one would only need to define webpack-merge's mergeWithRules and use that.

const { mergeWithRules } = require('webpack-merge');
const singleSpaDefaults = require('webpack-config-single-spa-react-ts');

const merge = mergeWithRules({
  module: {
    rules: {
      test: 'match',
      use: 'replace',
    },
  },
});

module.exports = (webpackConfigEnv, argv) => {
  const defaultConfig = singleSpaDefaults({
    orgName: 'abcde',
    projectName: 'fghij',
    webpackConfigEnv,
    argv,
  });

  const finalConfig = merge(defaultConfig, {
    module: {
      rules: [
        {
          test: /\.svg$/i,
          use: [
            {
              loader: '@svgr/webpack',
              options: {
                typescript: true,
              },
            },
          ],
        },
      ],
    },
  });

  return finalConfig
};
changeset-bot[bot] commented 2 years ago

🦋 Changeset detected

Latest commit: 99ee5adc60d5a10ab0d322f840f67c25606d6601

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages | Name | Type | | ---------------------------------- | ----- | | webpack-config-single-spa | Minor | | webpack-config-single-spa-react | Patch | | webpack-config-single-spa-ts | Patch | | webpack-config-single-spa-react-ts | Patch |

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

aaleo402 commented 1 year ago

@filoxo Hi! How can I override type: "asset/resource" with mergeWithRules? I don't get it.

filoxo commented 1 year ago

@aaleo402 I've created a PR to our documentation site that might clarify: https://github.com/single-spa/single-spa.js.org/pull/574 please review and see if it helps you answer your own question. If not, please either ask in the community Slack channel or create a new issue that shows what you've attempted to do and any errors you're experiencing. thanks!