Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v5] Use webpack 5 asset modules also for svgr #11213

Open
raix opened this issue Jul 16, 2021 · 11 comments
Open

[v5] Use webpack 5 asset modules also for svgr #11213

raix opened this issue Jul 16, 2021 · 11 comments

Comments

@raix
Copy link
Contributor

raix commented Jul 16, 2021

Is your proposal related to a problem?

This issue is related to Webpack 5 and the svg loader part of the configuration. Webpack 5 now use Asset modules to replace raw/url/file loaders.

Most of file loading is already converted into asset modules in the new CRA webpack 5 config but theres on outstanding regarding loading svg.

Describe the solution you'd like

When converting to webpack 5 I didn't manage to convert the svgr loader setup to be using asset modules, for now it's using file-loader still. It would be great if it could be converted into the asset module pattern, ideally by setting the asset type instead of using other loaders to be webpack 5 native.

Describe alternatives you've considered

@marella mentioned that he did a new-url-loader as an alternative see comment for more details

Additional context

Reading the webpack 5 documentation I would imagine that something like this would have worked:
(Also note that we might have to think about url assets maybe thats out of scope for now?)

  test: /\.svg$/,
  use: [
    {
      loader: '@svgr/webpack',
      options: {
        prettier: false,
        svgo: false,
        svgoConfig: {
          plugins: [{ removeViewBox: false }],
        },
        titleProp: true,
        ref: true,
      },
    },
    type: 'asset/resource',
    generator: {
      filename: 'static/media/[name].[hash].[ext]',
    }
/* replacing:
    {
      loader: 'file-loader',
      options: {
        name: 'static/media/[name].[hash].[ext]',
      },
    },
*/
  ],
@raix
Copy link
Contributor Author

raix commented Jul 16, 2021

@evenstensberg input/hints from the webpack team on this one would be great :)

@evenstensberg
Copy link

@raix
Copy link
Contributor Author

raix commented Jul 17, 2021

Thanks @evenstensberg so we are still "allowed" to use file-loader. Will have to check if the current config we have is sufficient or if we need to split it using the issuer prop.

@dawnofmidnight
Copy link

It might be best to just leave it as file-loader then, I just initially pointed it out because I thought it was no longer going to work or cause a loss due to the note at the top of this page: https://v4.webpack.js.org/loaders/file-loader/

@raix
Copy link
Contributor Author

raix commented Jul 18, 2021

@dawnofmidnight no worries, I also tried just using the asset modules due to the documentation, but it didn't work for me - could be a limitation in webpack / the svgr loader or me missing out on some details (lets keep an eye on it)

@marella
Copy link

marella commented Jul 18, 2021

Webpack doesn't seem to support "chaining" asset modules and loaders, so the config posted by raix doesn't work. If there is a way to pass the asset modules output directly to loaders then file-loader (archived) can be replaced completely.

The alternative made by me (new-url-loader) doesn't directly process the assets like file-loader or url-loader. It simply generates URL assets which are processed by asset modules. So it is kind of like a proxy to asset modules and can pass its output to other loaders.

Show config
test: /\.svg$/,
oneOf: [
  {
    // Exclude URL assets from being processed by loaders.
    dependency: { not: ['url'] },
    use: [
      {
        loader: '@svgr/webpack',
        options: {
          prettier: false,
          svgo: false,
          svgoConfig: {
            plugins: [{ removeViewBox: false }],
          },
          titleProp: true,
          ref: true,
        },
      },
      // Generate URL assets which are processed by asset modules.
      'new-url-loader',
    ],
  },
  {
    // Process URL assets using asset modules.
    type: 'asset/resource',
    generator: {
      filename: 'static/media/[name].[hash][ext]',
    },
  },
],

Since CRA config has a catch-all block which uses asset/resource type, above config can be simplified to:

test: /\.svg$/,
dependency: { not: ['url'] },
use: [
  {
    loader: '@svgr/webpack',
    options: {
      prettier: false,
      svgo: false,
      svgoConfig: {
        plugins: [{ removeViewBox: false }],
      },
      titleProp: true,
      ref: true,
    },
  },
  'new-url-loader',
],

@raix
Copy link
Contributor Author

raix commented Jul 18, 2021

@marella not sure if could chain eg. Using dependency and maybe issuer to select? (I'll have to read the source to come up with better solutions)

@alexander-akait
Copy link

alexander-akait commented Jul 20, 2021

No need to use dirty solution like gregberge/svgr#551 (comment), just register loader on resourceQuery: /svgr/ and use import foo from './my.svg?svgr' to import, new-url-loader is wrong solution too, i.e.

module: {
    rules: [
      {
        test: /\.svg$/,
        resourceQuery: /svgr/,
        use: [
          {
            loader: "@svgr/webpack",
          },
        ],
      },
    ],
  },

and use code:

import result from './image.svg?svgr';

console.log(typeof result)

if (module.hot) {
  module.hot.accept();
}

In future we will improve this and will be possible to use:

import result from "./image.svg" assert { type: "@svgr/webpack" };

console.log(typeof result)

if (module.hot) {
  module.hot.accept();
}

@alexander-akait
Copy link

Both example doesn't violate ECMA modules spec

@gregberge
Copy link

Hello here! I am working on the new version of SVGR and I am trying to find the best solution to handle it! For now I don't have one that fits well. As you mentioned chaining is not supported, so the best way do handle it is to use a query, as mentioned here: gregberge/svgr#551 (comment)

I think it would be the recommended way for webpack 5. Also it is better for perf since you will not transpile SVG is you don't need it explicitely.

@stephannielsen
Copy link

I ran into this issue because we switch from Node 16 to 18 which is now the latest LTS. Would be nice to get file-loader removed from CRA and replaced also for loading svgs using asset modules. If I understand it correctly, @svgr has been updated by now to correctly support asset modules too, so this should no longer be blocked?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants