Skip to content

Instantly share code, notes, and snippets.

@rayfranco
Last active June 1, 2021 07:49
Show Gist options
  • Save rayfranco/b97c0450e8ed699e7775d7aa6d170553 to your computer and use it in GitHub Desktop.
Save rayfranco/b97c0450e8ed699e7775d7aa6d170553 to your computer and use it in GitHub Desktop.
Inline SVG with Nuxt

Inline SVG with Nuxt

I was looking for a SSR and scoped styles ready solution to implement inline SVG with Nuxt

You need svg-inline-loader and xmldom to be installed.

module.exports = {
plugins: ['~/plugins/svg-inline.js'],
build: {
// ...
extend (config, { isDev, isClient }) {
// ...
// Store Vue loaders
const vueLoader = config.module.rules.find(function (module) {
return module.test.toString() === '/\\.vue$/'
})
// Remove SVG from default rules
config.module.rules.forEach((rule) => {
if (rule.test.toString() === '/\\.(png|jpe?g|gif|svg)$/') {
rule.test = /\.(png|jpe?g|gif)$/
}
})
// Add svg inline loader configuration
config.module.rules.push({
test: /\.svg$/,
loader: 'svg-inline-loader'
})
// Important to apply transforms on svg-inline:src
vueLoader.options.transformToRequire['svg-inline'] = 'src'
}
},
}
import Vue from 'vue'
const DOMParser = process.browser ? window.DOMParser : require('xmldom').DOMParser
const parser = new DOMParser()
Vue.component('svg-inline', {
props: {
src: {
type: String,
required: true
}
},
render(h) {
const document = parser.parseFromString(this.src, 'text/xml')
const svg = document.getElementsByTagName('svg')[0]
const attrs = {}
Array.prototype.forEach.call(svg.attributes, (attribute) => {
attrs[attribute.nodeName] = attribute.nodeValue
})
return h('svg', {
...this.data,
attrs,
domProps: {
innerHTML: svg.innerHTML
}
})
}
})
<template>
<button>
<svg-inline src="~/assets/svg/icon.svg"/>
</button>
</template>
// Will render
<button>
<svg viewBox="..."> <!-- inline SVG code --> </svg>
</button>
@hputzek
Copy link

hputzek commented Jul 5, 2018

Thanks, I'll try this!

@hputzek
Copy link

hputzek commented Jul 6, 2018

Hey @rayfranco thanks for that gist, it works and is exactly what I needed

@schlunsen
Copy link

This doesn't seem to work with nuxt 2.0

Seems that transformToRequire is ignored

@pxwee5
Copy link

pxwee5 commented Jul 30, 2018

@olegnazarov23
Copy link

Does anyone have this error - Cannot read property 'attributes' of undefined const svg = document.getElementsByTagName('svg')[0]?
Coming from svg-inline.js? Paths are 100% correct. Nuxtjs 2

@Pitu
Copy link

Pitu commented Sep 30, 2018

@olegnazarov23 were you able to fix that issue?

@elcferreira
Copy link

Does anyone have this error - Cannot read property 'attributes' of undefined const svg = document.getElementsByTagName('svg')[0]?
Coming from svg-inline.js? Paths are 100% correct. Nuxtjs 2

I have the same problem!!
Anyone have find a solution? 😄

@elcferreira
Copy link

transformToRequire (now renamed to transformAssetUrls)

https://github.com/vuejs/vue-loader/blob/ecd66a5f194fa1f28b0c57444c810449adbb75e9/docs/migrating.md

This resolve the problem but appear the problem with attribute

@eikhunter
Copy link

Did anyone find a solution to the attribute issue?

@nevenduranec
Copy link

Test rules have changed - nuxt version ^2.3.4.

/\\.vue$/ => /\\.vue$/i
/\\.(png|jpe?g|gif|svg)$/ => /\\.(png|jpe?g|gif|svg|webp)$/i
/\.(png|jpe?g|gif)$/ => /\.(png|jpe?g|gif|webp)$/i

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