Import Raw Assets in Vite
Today, I attempted to import a local image using the ?raw
query suffix in Vite and convert it into an image src
URL for use in the browser. However, I was repeatedly greeted by the dreaded image placeholder (🖼️), signaling that things went wrong.
Eager to uncover the cause, I delved into Vite’s source code and discovered how the ?raw
suffix is handled in asset.ts
:
function assetPlugin(config: ResolvedConfig): Plugin {
return {
//...
async load() {
// ...
// raw requests, read from disk
if (rawRE.test(id)) {
const file = checkPublicFile(id, config) || cleanUrl(id)
this.addWatchFile(file)
// raw query, read file and return as string
return `export default ${JSON.stringify(
await fsp.readFile(file, 'utf-8'),
)}`
}
// ...
}
}
}
From this, it became clear that Vite handles assets with ?raw
query by reading the files as UTF-8 encoded strings. It works well for plain text files, but with binary formats (like images) since non-Unicode characters in these files are replaced with the replacement character ”�” (U+FFFD
). This corruption renders the asset unusable for its intended purpose , and unfortunately, is unrecoverable.