6

I have a prebuilt svg sprite with more than 100 icons:

<svg xmlns="http://www.w3.org/2000/svg" style="visibility:hidden; width:0; height:0;">
    <symbol id="icon--web" viewBox="0 0 70 100">...</symbol>
    ...
</svg>

How to configure webpack to use such a sprite in this simple way? :

<svg class="icon icon--web">
    <use xlink:href="../../images/sprite.svg#icon--web"></use>
</svg>

Most of plugins (svg-spritemap-webpack-plugin, svg-sprite-loader) are aimed to build sprites from many svg images, however I've not found how to configure them to use an earlier built sprite.

Prisacari Dmitrii
  • 1,985
  • 1
  • 23
  • 33

3 Answers3

4

So here's my solution for webpack4. This results to that svg sprite is included in javascript application code and is inserted into the page markup after opening body tag and all icons from the sprite are successfully loaded:

  1. Include sprite path to your index.js file:

    // index.js
    import '../images/_sprite.svg';
    
  2. Add rule to webpack config (use svg-sprite-loader):

    {
        test: /\.svg$/i,
    
        // from all svg images
        // include only sprite image
        include: /.*_sprite\.svg/,
    
        use: [
            {
                loader: 'svg-sprite-loader',
                options: {
                    publicPath: '',
                }
            },
        ],
    },
    
    
  3. Enable svg-sprite-loader plugin in your webpack config:

    const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');
    
    // ...
    plugins: [
        // ...
        new SpriteLoaderPlugin()
    ]
    
  4. Use the following html markup in your html:

    <svg class="icon icon--web">
        <use xlink:href="#_sprite_icon--web"></use>
    </svg>
    

    Pay attention that the sprite path is removed and the _sprite_ string is added.

Prisacari Dmitrii
  • 1,985
  • 1
  • 23
  • 33
  • You found your solution! I believe this is a good solution if you want to integrate your svg sprite in the complied source code. Cheers! – cypark May 19 '19 at 04:43
  • Is not there any way to do the exact same thing we do in the create-react-app project? I don't know what kind of loader react use to do so. I mean using tag with the static path and the id of the SVG content within the sprite file (`${imported path}#icon-like`). – Codie Dec 20 '22 at 11:15
1

The simplest way to reference the svg file without any transformation would be handling it as a static asset. Put the svg file in the static asset directory and copy it as you bundle the source code. You can achieve it by using copy-webpack-plugin. Below is a sample setup in webpack.config.js:

const CopyPlugin = require('copy-webpack-plugin');

// ...

plugins: [
  new CopyPlugin([
    {
      from: './src/static/assets/sprite.svg',
      to: 'static/assets', // relative path in output directory
    }
  ])
]

Once you successfully copy the svg file to the static assets folder, you can reference it like you did in your above code.

cypark
  • 838
  • 6
  • 21
  • Thanks for the answer. I've also tried this plugin but there's another issue: when we use path like `` we get error: `Module not found: Error: Can't resolve ../../images/sprite.svg#icon--web`. I suppose that webpack tries to resolve this path in file system and does not find any file named `sprite.svg#icon--web`. – Prisacari Dmitrii May 18 '19 at 10:50
  • I can't guarantee as I don't know your directory structure, but you could modify the link and see if it works. Assuming your `index.html` is in the root directory, `sprite.svg` will be copied to `/static/assets/sprite.svg` following above example. So if you want to reference your sprite in `index.html` or a js file that is in the root directory, you could try like: ``. Sorry if I'm giving you a bigger chaos, but this is a solid working solution. Just wanted to make clear for anyone's future reference. Good luck!! – cypark May 19 '19 at 04:40
0
module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          attributes: {
            list: [
              {
                tag: 'use',
                attribute: 'xlink:href',
                type: 'src',
              },
            ]
          },
        }
      },

      {
        test: /\.svg$/,
        use: 'file-loader'
      }
    ]
  }

You can configure webpack as follow and the markup should work as per your expectation!

Anh Do
  • 1
  • 3