Custom Vite plugin for transforming SVGs only works in development mode, not in build mode. #15894
-
I'm building an app with SvelteKit, which uses Vite for bundling. I made a Vite plugin for importing SVG files (using the export default {
width: 100,
height: 100,
dataUrl: "data:image/svg+xml;charset=utf-8,[...]"
} The idea is to inline these SVGs into my code and provide some metadata that helps me display them properly. I have valid reasons for not being able to just access the width and height after displaying the SVG image in the browser. This plugin works perfectly fine in dev mode (i.e. when running As an example, here's a snippet from the bundled output:
The SVG has been inlined as raw SVG code urlencoded within a data url rather than my transformed version. I have tried the following things to no avail:
Config filesMy `vite.config.ts`import { sveltekit } from "@sveltejs/kit/vite";
import { svgResourcePlugin } from "./plugins/svgResourcePlugin";
import { defineConfig } from "vitest/config";
const config = defineConfig({
plugins: [svgResourcePlugin(), sveltekit()],
worker: {
format: "es",
},
test: {
include: ["src/**/*.{test,spec}.{js,ts}"],
},
});
export default config; My `svelte.config.js`SvelteKit is configured with the adapter import adapter from "@sveltejs/adapter-static";
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter({
pages: "build",
assets: "build",
fallback: undefined,
precompress: false,
strict: true,
}),
},
};
export default config; Plugin codeimport { transformWithEsbuild, type Plugin } from "vite";
import { readFileSync } from "fs";
import { XMLParser } from "fast-xml-parser";
export function svgResourcePlugin(options = {}): Plugin {
const {
defaultExport = "url",
svgoConfig,
expandProps,
svgo,
ref,
memo,
replaceAttrValues,
svgProps,
titleProp,
} = options;
const cache = new Map();
const svgRegex = /\.svg(?:\?(resource|url))?$/;
return {
name: "svg-resource",
async transform(source, id, isBuild) {
const result = id.match(svgRegex);
if (result) {
const type = result[1];
if ((defaultExport === "url" && typeof type === "undefined") || type === "url") {
return source;
}
if ((defaultExport === "resource" && typeof type === "undefined") || type === "resource") {
const idWithoutQuery = id.replace(".svg?resource", ".svg");
let result = cache.get(idWithoutQuery);
if (!result) {
const code = readFileSync(idWithoutQuery, "utf-8");
const parser = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: "",
});
const jsonObj = parser.parse(code);
if (jsonObj && jsonObj.svg) {
const width = parseInt(jsonObj.svg.width, 10);
const height = parseInt(jsonObj.svg.height, 10);
const dataURL = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(
Buffer.from(code).toString(),
)}`;
result = `export default ${JSON.stringify({
width,
height,
dataURL,
})};`;
} else {
this.error(`Invalid SVG resource file: ${id}`);
}
if (isBuild) {
cache.set(idWithoutQuery, result);
}
}
return result;
}
}
},
};
} Any help would be appreciated ❤️ |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
While messing around more with the Vite configuration, I noticed that there's a It appears that the plugin must be placed within this field too if I want the worker code to be able to use the plugin. This appears to have fixed my issue. Here's the updated import { sveltekit } from "@sveltejs/kit/vite";
import { svgResourcePlugin } from "./plugins/svgResourcePlugin";
import { defineConfig } from "vitest/config";
const config = defineConfig({
plugins: [svgResourcePlugin(), sveltekit()],
worker: {
format: "es",
plugins: [svgResourcePlugin()],
},
test: {
include: ["src/**/*.{test,spec}.{js,ts}"],
},
});
export default config; |
Beta Was this translation helpful? Give feedback.
While messing around more with the Vite configuration, I noticed that there's a
plugins
field underworker
.It appears that the plugin must be placed within this field too if I want the worker code to be able to use the plugin. This appears to have fixed my issue.
Here's the updated
vite.config.ts
: