codefeathers / rollup-plugin-svelte-svg

Import SVG files as Svelte Components
MIT License
75 stars 13 forks source link

ENOENT error with basic Vite setup #31

Closed arseneyr closed 2 years ago

arseneyr commented 2 years ago

I'm having an issue getting this plugin to work with a basic Vite setup. After putting the SVG into the src folder, I'm getting the error ENOENT: no such file or directory, open '/src/test.svg'.

Repro steps

  1. Create a boilerplate svelte-ts project with npm init vite@latest
  2. Install rollup-plugin-svelte-svg and add it to the vite.config.js, placing it before vite-plugin-svelte and passing {enforce: 'pre'}.
  3. Add an SVG to the src folder and reference it in a svelte file (e.g. import Icon from './test.svg'; in App.svelte)

I have a sample repo here.

Expected output

The SVG loads as a svelte component

Actual output

ENOENT: no such file or directory, open '/src/test.svg'

Notes

Looks like rollup-plugin-svelte-svg is correctly adding .svelte to the SVG in resolveId(), but load() is called with the absolute path /src/test.svg.svelte instead of the one returned by load(). I'm not sure if this is a change to Vite's resolution strategy, but the vite.config.js is all defaults except for the two plugins.

hitchhooker commented 2 years ago
5:22:50 PM [vite-plugin-svelte] /home/satoshi/code/project/src/lib/header/Header.svelte:8:61 'logo' is not defined
5:22:50 PM [vite] Internal server error: ENOENT: no such file or directory, open '/src/lib/header/project-logo.svg

battling with same issue using SvelteKit. Overall would be worth making repo compatible with sveltekit now that its close to release.

rraihansaputra commented 2 years ago

@arseneyr @hitchhooker

For some unknown reason, SvelteKit/Vite tries to re-resolve the resolved .svg.svelte without success. As the plugin only processes .svg, not .svg.svelte, the load function tries to load the default source.

If you really need this to work, you can use the code below as a plugin to be imported on the SvelteKit config instead of this plugin from npm.

To maintainers: Really unsure why is this happening, but this is probably not the most ideal way to handle this.

import { extname, dirname, resolve } from "path";
import { readFile } from "fs/promises";

import { optimize as optimise } from "svgo";
import { createFilter } from "rollup-pluginutils";

const svgRegex = /(<svg.*?)(>.*)/s;
const svgheader = /^\<\?xml.+?\>/;

function addProps(source) {
  const parts = svgRegex.exec(source);
  if (!parts) throw new Error("Unable to parse as svg.");

  const [, svgStart, svgBody] = parts;
  return `${svgStart} {...$$props} ${svgBody}`;
}

export function svelteSVG(options = {}) {
  const { svgo, enforce } = options;
  const filter = createFilter(options.include, options.exclude);

  return {
    name: "rollup-plugin-svelte-svg",

    // vite-only
    // https://vitejs.dev/guide/api-plugin.html#plugin-ordering
    ...(enforce && { enforce }),

    async resolveId(source, importer, options) {
      if (
        !filter(source) ||
        (extname(source) !== ".svg" && !source.endsWith(".svg.svelte"))
      ) {
        return null;
      }

      let properSource = source;
      if (source.endsWith(".svg.svelte")) {
        properSource = source.slice(0, -".svelte".length);
      }

      // resolve path using other plugins first (alias, node-resolve, etc)
      const { id: resovledId } = await this.resolve(properSource, importer, {
        skipSelf: true,
        ...options,
      });

      // add .svelte to resolved id for the file to be processed by the svelte plugin
      const appendDotSvelte = resovledId + ".svelte";

      return appendDotSvelte;
    },

    load(id) {
      if (!id.endsWith(".svg.svelte")) return null;

      return readFile(id.slice(0, -".svelte".length), "utf-8")
        .then((file) => (svgo ? optimise(file, svgo).data : file))
        .then((file) => file.replace(svgheader, "").trim())
        .then(addProps);
    },
  };
}
cibernox commented 2 years ago

@rraihansaputra thanks for that snippet, I used it and worked for me.

MKRhere commented 2 years ago

Thanks @rraihansaputra, I've published a fix based on your snippet. It should work now with the double resolve call. rollup-plugin-svelte-svg@1.0.0-beta.6 is up on npm ^^

rraihansaputra commented 2 years ago

@MKRhere Great to see the update! This inadvertently solves the previous problem of other resolvers too, so I'm closing this PR (https://github.com/codefeathers/rollup-plugin-svelte-svg/pull/30).