Bud.js import svg for inline html injected via js

I’m using Bud.js to hash asset files, including svg. What is the best way to get the contents of an svg file so that it can be inlined via html that is injected via js?

I want the svg compiled with the js file, instead of using a client side fetch to get the manifest file and hashed svg filename for use with .text().

I also want to avoid using <img> or <object> so that external css can modify the svg.

import svg from '@src/images/image.svg' returns the url.

import svg from '@src/images/image.svg?inline' is close but for CSS.

import svg from '@src/images/image.html' works, but I need the extension to remain .svg.

I have a feeling there’s an easy answer for this that’s just eluding me. Perhaps a more manual approach with fs.readFile(), but maybe there’s a better approach with Bud?

Hi @esaner,

import svg from '!!raw-loader!@src/test.svg';

Should do the trick.

Here’s some more information on the !!loader! syntax.

1 Like

Thanks, @talss89!

For future me: the following link was also helpful, there’s no need to register raw-loader with Bud, and raw-loader is deprecated in webpack v5.

https://v4.webpack.js.org/loaders/raw-loader/

1 Like

Worked through this some more and also came up with the following solution, which doesn’t require raw-loader.

Some helpful links:

https://webpack.js.org/guides/asset-modules/

/**
 * Custom Rules
 * Get SVG file contents with `import icon from '@src/icon.svg?source'`
 *
 * @link https://bud.js.org/learn/general-use/customizing-loaders
 * @link https://webpack.js.org/guides/asset-modules/
 */
bud.hooks.on(`build.module.rules.oneOf`, (rules = []) => {
    rules.push({
        test: /\.svg$/,
        resourceQuery: (/source/),
        type: 'asset/source'
    })

    return rules
})
4 Likes