diff --git a/packages/playground/assets/index.html b/packages/playground/assets/index.html index 9983d7fc4a5da7..6353270d303869 100644 --- a/packages/playground/assets/index.html +++ b/packages/playground/assets/index.html @@ -119,6 +119,18 @@

SVG Fragments via JS Import

+

SVG Fragments via URL JS Import

+
+

Imported path:

+ +
+ +

SVG Fragments via URL HASH JS Import

+
+

Imported path:

+ +
+

?raw import

@@ -159,6 +171,14 @@

new URL(`./${dynamic}`, import.meta.url)

text('.svg-frag-import-path', svgFrag) document.querySelector('.svg-frag-import').src = svgFrag + '#icon-heart-view' + import svgFragUrl from './nested/fragment-for-url.svg?url' + text('.svg-frag-import-js-url', svgFragUrl) + document.querySelector('.svg-frag-import-url').style = `background: url("${svgFragUrl}") no-repeat;` + + import svgFragUrlHash from './nested/fragment-for-url.svg?url#icon-heart-view' + text('.svg-frag-import-js-url-hash', svgFragUrlHash) + document.querySelector('.svg-frag-import-url-hash').style = `background: url("${svgFragUrlHash}") no-repeat;` + import rawSvg from './nested/fragment.svg?raw' text('.raw', rawSvg) diff --git a/packages/playground/assets/nested/fragment-for-url.svg b/packages/playground/assets/nested/fragment-for-url.svg new file mode 100644 index 00000000000000..e7de6d86b6e2f5 --- /dev/null +++ b/packages/playground/assets/nested/fragment-for-url.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/playground/assets/vite.config.js b/packages/playground/assets/vite.config.js index 1ecd3318627521..54d869e26c2f0c 100644 --- a/packages/playground/assets/vite.config.js +++ b/packages/playground/assets/vite.config.js @@ -13,7 +13,7 @@ module.exports = { }, build: { outDir: 'dist/foo', - manifest: true, - watch: {} + manifest: true + // watch: {} } } diff --git a/packages/vite/LICENSE.md b/packages/vite/LICENSE.md index 5f63f6317a6e59..76a3c7bba3613b 100644 --- a/packages/vite/LICENSE.md +++ b/packages/vite/LICENSE.md @@ -2881,6 +2881,35 @@ Repository: sindresorhus/mimic-fn --------------------------------------- +## mini-svg-data-uri +License: MIT +By: Taylor “Tigt” Hunt +Repository: git+https://github.com/tigt/mini-svg-data-uri.git + +> MIT License +> +> Copyright (c) 2018 Taylor Hunt +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + +--------------------------------------- + ## minimatch License: ISC By: Isaac Z. Schlueter diff --git a/packages/vite/package.json b/packages/vite/package.json index f438bd55e75bdb..24abee3513d7b9 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -101,6 +101,7 @@ "magic-string": "^0.25.7", "micromatch": "^4.0.4", "mime": "^3.0.0", + "mini-svg-data-uri": "^1.3.3", "okie": "^1.0.1", "open": "^8.4.0", "periscopic": "^2.0.3", diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts index a10ec3094229e7..5b8d6b5453a91a 100644 --- a/packages/vite/src/node/plugins/asset.ts +++ b/packages/vite/src/node/plugins/asset.ts @@ -8,6 +8,7 @@ import { cleanUrl } from '../utils' import { FS_PREFIX } from '../constants' import { OutputOptions, PluginContext, RenderedChunk } from 'rollup' import MagicString from 'magic-string' +import svgToTinyDataUri from 'mini-svg-data-uri' import { createHash } from 'crypto' import { normalizePath } from '../utils' @@ -156,7 +157,8 @@ export function fileToUrl( config: ResolvedConfig, ctx: PluginContext ): string | Promise { - if (config.command === 'serve') { + const file = cleanUrl(id) + if (config.command === 'serve' && !file.endsWith('.svg')) { return fileToDevUrl(id, config) } else { return fileToBuiltUrl(id, config, ctx) @@ -283,17 +285,25 @@ async function fileToBuiltUrl( return cached } + const { search, hash } = parseUrl(id) const file = cleanUrl(id) const content = await fsp.readFile(file) let url: string if ( - config.build.lib || - (!file.endsWith('.svg') && - content.length < Number(config.build.assetsInlineLimit)) + file.endsWith('.svg') || + ((config.build.lib || + Buffer.byteLength(content) < config.build.assetsInlineLimit) && + hash == null) ) { - // base64 inlined as a string - url = `data:${mime.getType(file)};base64,${content.toString('base64')}` + // svgs can be inlined without base64 + url = file.endsWith('.svg') + ? // The only difference between the default method and `toSrcset` is that + // the latter encodes spaces as `%20`, so it's safer to always use it + // to support `srcset` use-case even when svg is imported into JavaScript + svgToTinyDataUri.toSrcset(content.toString()) + : // base64 inlined as a string + `data:${mime.getType(file)};base64,${content.toString('base64')}` } else { // emit as asset // rollup supports `import.meta.ROLLUP_FILE_URL_*`, but it generates code @@ -304,7 +314,6 @@ async function fileToBuiltUrl( // https://github.com/rollup/rollup/issues/3415 const map = assetHashToFilenameMap.get(config)! const contentHash = getAssetHash(content) - const { search, hash } = parseUrl(id) const postfix = (search || '') + (hash || '') const output = config.build?.rollupOptions?.output const assetFileNames = diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 63675a1a47e49f..ba67dc9080ee7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -722,6 +722,7 @@ importers: magic-string: ^0.25.7 micromatch: ^4.0.4 mime: ^3.0.0 + mini-svg-data-uri: ^1.3.3 okie: ^1.0.1 open: ^8.4.0 periscopic: ^2.0.3 @@ -799,6 +800,7 @@ importers: magic-string: 0.25.7 micromatch: 4.0.4 mime: 3.0.0 + mini-svg-data-uri: 1.4.3 okie: 1.0.1 open: 8.4.0 periscopic: 2.0.3 @@ -6254,6 +6256,11 @@ packages: tiny-warning: 1.0.3 dev: false + /mini-svg-data-uri/1.4.3: + resolution: {integrity: sha512-gSfqpMRC8IxghvMcxzzmMnWpXAChSA+vy4cia33RgerMS8Fex95akUyQZPbxJJmeBGiGmK7n/1OpUX8ksRjIdA==} + hasBin: true + dev: true + /miniflare/1.4.1: resolution: {integrity: sha512-hJkMbTEM+sSiAo2yuPOucrdFYINLU7vvl9uVkRzAQ/h0CjmkYOCoyBn4jYzWtDZeQ0XrkyS6PGUCO277B5TsXA==} engines: {node: '>=10.12.0'}