mirror of
https://github.com/vitejs/vite.git
synced 2024-11-21 22:59:10 +00:00
feat(build)!: inline SVGs (#14643)
This commit is contained in:
parent
e5ee4207d9
commit
5acda5e10a
@ -371,7 +371,8 @@ async function fileToBuiltUrl(
|
||||
let url: string
|
||||
if (
|
||||
config.build.lib ||
|
||||
(!file.endsWith('.svg') &&
|
||||
// Don't inline SVG with fragments, as they are meant to be reused
|
||||
(!(file.endsWith('.svg') && id.includes('#')) &&
|
||||
!file.endsWith('.html') &&
|
||||
content.length < Number(config.build.assetsInlineLimit) &&
|
||||
!isGitLfsPlaceholder(content))
|
||||
@ -382,9 +383,13 @@ async function fileToBuiltUrl(
|
||||
)
|
||||
}
|
||||
|
||||
const mimeType = mrmime.lookup(file) ?? 'application/octet-stream'
|
||||
// base64 inlined as a string
|
||||
url = `data:${mimeType};base64,${content.toString('base64')}`
|
||||
if (file.endsWith('.svg')) {
|
||||
url = svgToDataURL(content)
|
||||
} else {
|
||||
const mimeType = mrmime.lookup(file) ?? 'application/octet-stream'
|
||||
// base64 inlined as a string
|
||||
url = `data:${mimeType};base64,${content.toString('base64')}`
|
||||
}
|
||||
} else {
|
||||
// emit as asset
|
||||
const { search, hash } = parseUrl(id)
|
||||
@ -428,3 +433,28 @@ export async function urlToBuiltUrl(
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
// Inspired by https://github.com/iconify/iconify/blob/main/packages/utils/src/svg/url.ts
|
||||
function svgToDataURL(content: Buffer): string {
|
||||
const stringContent = content.toString()
|
||||
// If the SVG contains some text, any transformation is unsafe, and given that double quotes would then
|
||||
// need to be escaped, the gain to use a data URI would be ridiculous if not negative
|
||||
if (stringContent.includes('<text')) {
|
||||
return `data:image/svg+xml;base64,${content.toString('base64')}`
|
||||
} else {
|
||||
return (
|
||||
'data:image/svg+xml,' +
|
||||
stringContent
|
||||
.trim()
|
||||
.replaceAll('"', "'")
|
||||
.replaceAll('%', '%25')
|
||||
.replaceAll('#', '%23')
|
||||
.replaceAll('<', '%3c')
|
||||
.replaceAll('>', '%3e')
|
||||
// Spaces are not valid in srcset it has some use cases
|
||||
// it can make the uncompressed URI slightly higher than base64, but will compress way better
|
||||
// https://github.com/vitejs/vite/pull/14643#issuecomment-1766288673
|
||||
.replaceAll(/\s+/g, '%20')
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -293,7 +293,12 @@ describe('svg fragments', () => {
|
||||
|
||||
test('from js import', async () => {
|
||||
const img = await page.$('.svg-frag-import')
|
||||
expect(await img.getAttribute('src')).toMatch(/svg#icon-heart-view$/)
|
||||
expect(await img.getAttribute('src')).toMatch(
|
||||
isBuild
|
||||
? // Assert trimmed (data URI starts with < and ends with >)
|
||||
/^data:image\/svg\+xml,%3c.*%3e#icon-heart-view$/
|
||||
: /svg#icon-heart-view$/,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -16,6 +16,7 @@ export default defineConfig({
|
||||
cssCodeSplit: false,
|
||||
manifest: true,
|
||||
sourcemap: true,
|
||||
assetsInlineLimit: 100, // keep SVG as assets URL
|
||||
rollupOptions: {
|
||||
input: {
|
||||
index: path.resolve(__dirname, 'index.html'),
|
||||
|
@ -21,6 +21,7 @@ export default defineConfig({
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/es',
|
||||
assetsInlineLimit: 100, // keep SVG as assets URL
|
||||
rollupOptions: {
|
||||
output: {
|
||||
assetFileNames: 'assets/[name].[ext]',
|
||||
|
@ -38,6 +38,7 @@ export default defineConfig({
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/iife',
|
||||
assetsInlineLimit: 100, // keep SVG as assets URL
|
||||
manifest: true,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
|
@ -21,6 +21,7 @@ export default defineConfig({
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/relative-base-iife',
|
||||
assetsInlineLimit: 100, // keep SVG as assets URL
|
||||
rollupOptions: {
|
||||
output: {
|
||||
assetFileNames: 'other-assets/[name]-[hash].[ext]',
|
||||
|
@ -21,6 +21,7 @@ export default defineConfig({
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist/relative-base',
|
||||
assetsInlineLimit: 100, // keep SVG as assets URL
|
||||
rollupOptions: {
|
||||
output: {
|
||||
assetFileNames: 'other-assets/[name]-[hash].[ext]',
|
||||
|
@ -35,6 +35,7 @@ export default (sourcemap) => {
|
||||
},
|
||||
build: {
|
||||
outDir: `dist/iife-${typeName}/`,
|
||||
assetsInlineLimit: 100, // keep SVG as assets URL
|
||||
sourcemap: sourcemap,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
|
Loading…
Reference in New Issue
Block a user