vite
vite copied to clipboard
Generation of static svg sprite file in dist
Description
I'm currently trying vite instead of webpack, and seems it's pretty matching our needs, but i noticed one problem which i can not resolve -> generation of svg sprite.
In webpack we have used https://www.npmjs.com/package/svg-sprite-loader plugin with extract mode. If in short -> it takes svg files from some folder, then it generating svg-sprite file with all of those icons and put this file into dist folder. In the end we have a static svg-sprite file in dist which we can use from any template like this:
<svg>
<use xlink:href="path-to-dist/svg-sprite.svg#icon-name"></use>
</svg>
We don't use frameworks. We using Drupal and calling icons from twig templates for example (one of the available options).
Now about the problem - i really can't find at least one plugin or info in vite docs how we can do the same with vite. All existing plugins available on npm are mostly about dynamic js "imports" & dynamic svg-sprite generation & putting svg-sprite into DOM. But no plugin about creation of static file.
Any help please?
Suggested solution
For sure can be some plugin, since smells like "out of vite core's scope". Idk
Alternative
No response
Additional context
No response
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
Does these work for you? https://www.npmjs.com/package/vite-plugin-svg-sprite https://github.com/vbenjs/vite-plugin-svg-icons
Does these work for you? https://www.npmjs.com/package/vite-plugin-svg-sprite https://github.com/vbenjs/vite-plugin-svg-icons
Unfortunately they do not suit as they require a JS framework. My current project allows only vanilla JS. I suspect this is the same reason OP is searching for a solution.
I found https://www.npmjs.com/package/rollup-plugin-svgsprite-generator and it works perfectly for production builds but causes errors with HMR, namely:
[vite] Internal server error: Failed to resolve import "assets/svg" from "node_modules/vite/dist/client/client.mjs". Does the file exist?
Note that assets/svg
is a directory, not a file. I tried formatting the directory path in different ways and was unable to get it to play nicely with HMR.
Did you ever find a solution @koskinpark ?
Unfortunately they do not suit as they require a JS framework.
I don't think they require a JS framework. Won't vite-plugin-svg-sprite work by this code?
import appIconId from './path/to/icons/app.svg';
document.querySelector('#app-img').innerHTML = `
<svg>
<use xlinkHref="#${appIconId}" />
</svg>
`
But I might got what the OP mean. IIUC they want to extract svg file references automatically and convert it to svg sprite.
vite-plugin-svg-icons doesn't generate SVG file, there is an issue about that : Generate a .svg file instead of an embedded SVG tag
Any updates ? 🙄
https://github.com/JetBrains/svg-sprite-loader/issues/434
`import { Plugin } from 'vite'
import { readFileSync, readdirSync, writeFile } from 'fs'
import { join } from'path';
let idPerfix = ''
const svgTitle = /<svg([^>+].*?)>/
const clearHeightWidth = /(width|height)="([^>+].*?)"/g
const hasViewBox = /(viewBox="[^>+].*?")/g
const clearReturn = /(\r)|(\n)/g
function findSvgFile(dir): string[] {
const svgRes = []
const dirents = readdirSync(dir, {
withFileTypes: true
})
for (const dirent of dirents) {
if (dirent.isDirectory()) {
svgRes.push(...findSvgFile(dir + dirent.name + '/'))
} else {
const svg = readFileSync(dir + dirent.name)
.toString()
.replace(clearReturn, '')
.replace(svgTitle, ($1, $2) => {
// console.log(++i)
// console.log(dirent.name)
let width = 0
let height = 0
let content = $2.replace(
clearHeightWidth,
(s1, s2, s3) => {
if (s2 === 'width') {
width = s3
} else if (s2 === 'height') {
height = s3
}
return ''
}
)
if (!hasViewBox.test($2)) {
content += `viewBox="0 0 ${width} ${height}"`
}
return `<symbol id="${idPerfix}-${dirent.name.replace(
'.svg',
''
)}" ${content}>`
})
.replace('</svg>', '</symbol>')
svgRes.push(svg)
}
}
return svgRes
}
export const svgBuilder = (
path: string,
perfix = 'icon'
): Plugin => {
if (path === '') return
idPerfix = perfix
const res = findSvgFile(path)
// console.log(res)
// const res = []
writeFile(join(process.cwd(), 'public', '/spritemap.svg'), `
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
${res.join('')}
</svg>
`, function(err) {
if(err) {
return console.log(err, {color: 'red'});
}
console.log("The spritemap.svg saved!");
})
return {
name: 'svg-transform',
transformIndexHtml(): string {
return ''
}
}
}`
I add this code
writeFile(join(process.cwd(), 'public', '/spritemap.svg'), `
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
${res.join('')}
</svg>
`, function(err) {
if(err) {
return console.log(err, {color: 'red'});
}
console.log("The spritemap.svg saved!");
})
yeap, it need refactor but it work
Also https://www.npmjs.com/package/vite-svg-sprite-wrapper
Hi folks,
As I have done a bit of research for my own projects and most plugins have a similar name and overlapping features, I figured I could compile a somewhat easy-to-read list of available options that are out there:
Library | Version | Stars | Downloads | |
---|---|---|---|---|
@spiriit/vite-plugin-svg-spritemap NPM |
Generates a sprite from all the files from a directory/matching pattern. Additionally, has extra features for Vue. | |||
vite-plugin-svg-icons NPM |
Generate a sprite from all the files matching a pattern/in a directory and injects it into the body. Includes svgo with configuration. Additionally, can get icon names as list with virtual:svg-icons-names . |
|||
vite-plugin-svg-sprite NPM |
Generates a sprite on the fly from imported svg icons and injects it into the document. Includes svgo . |
|||
vite-plugin-svg-spritemap NPM |
Generates a sprite from all the files from a directory/matching pattern. Includes svgo and option to replace colors as currentColor . |
|||
vite-svg-sprite-wrapper NPM |
Generates a sprite from all the files from a directory/matching pattern. Additionally, can generate TypeScript types. |
For the sake of being somewhat exhaustive, Astro's astro-icon is a vite plugin under the hood.