1.0.1 • Published 1 year ago

@svgx/vite-plugin-qwik v1.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

SVGX Vite Plugin for Qwik

Vite plugin to import SVG files as Qwik Components, it transforms raw SVG markup to Qwik Components that can be then inserted directly into the JSX code.

Install

This package is hybrid (ESM & CommonJS), which means it can be imported or required.

npm

npm install --save-dev @svgx/vite-plugin-qwik

Use

Include the plugin in vite.config.js

To use this plugin it needs to be included in the plugins array in the vite.config.js config file.

import { defineConfig } from "vite";
import svgx from "@svgx/vite-plugin-qwik";

export default defineConfig(async () => {
  return {
    plugins: [
      svgx(),
      /* ... other plugins*/
    ],
  };
});

Import an SVG file

Regular import

Say you have an SVG file named icon.svg and you want to include it in your JSX, you can simply import it as follows (note: it is highly recomanded to include the suffix '?component')

import MyIcon from "./icon.svg?component";
// <MyIcon />

you can also use ?url suffix to import the SVG as URL

import MyIcon from "./icon.svg?url";
// './assets/svg/icon.svg'

or use ?raw suffix to import the SVG as raw string

import MyIcon from "./icon.svg?raw";
// '<svg xmlns="http://www.w3.org/2000/svg" ...'

Example:

import MyIcon from "./icon.svg?component";
import { component$ } from "@builder.io/qwik";

export default component$(() => {
  return (
    <div>
      <MyIcon color="#FF5733" />
    </div>
  );
});

Dynamic import variables for SVG files

You have a component that has to render some SVG based on some variable, and this variable could have a lot of different values? one way of solving this is to use the regular import to import all the possible SVGs that could be rendered, and write some complex logic to choose one of them based on the value of that variable, or you may find an easier way to accomplish this, but with this plugin you can do that with just two lines of code, literally! all you need to do is to write this import statement:

import importVars from "@svgx-dir:/path/to/directory";

Replace /path/to/directory with the path to the directory containing your SVG files, the path to that directory must be either relative (start with ./) or absolute (start with /, resolved relative to project root) or an alias path.

This feature is using Vite's Glob Import feaure, if you want to read more about it head to Vite Documentation.

Important: you must include @svgx-dir: before the directory path, otherwise this won't work.

importVars is a function that accepts one argument which is a string representing the name of an SVG file in that directory without extension (without .svg at the end), and returns a function component representing the imported SVG file which you can then include in your JSX:

Include the SVG into JSX with importVars

import importVars from "@svgx-dir:/path/to/directory";
import { component$ } from "@builder.io/qwik";

export default component$((props) => {
  const MyIcon = importVars(props.iconName);
  return (
    <div>
      <MyIcon color="#FF5733" />
    </div>
  );
});

Pass props to the SVG component

As you can see, you can pass props to your component as you would do with regular JSX's <svg> element. all of this is handled for you by default, without the need to add any config to the plugin. but if you want to change the default settings for some reason, here are the available options:

Options

all of these options are optional:

defaultImport

  • type: "url" | "raw" | "component"
  • default: "component"

use this option to specify wether the plugin should return a component, raw svg string, or a url, when no suffix is appended to the file path. while it's possible to not append any suffix to the file path, appending it is highly recomanded to prevent confusion with other plugins and to get proper typings when using typescript.

passProps

  • type: boolean
  • default: true

use this option to specify wether the component accepts props (the props are passed directly to the <svg> element using spread operator <svg {...props}></svg>). note that if you are using typescript, you'll still get props suggestions in your IDE even when this option is set to false, so you need to just ignore the suggestions and avoid setting props for the component.

optimize

  • type: boolean
  • default: true

Wether to optimize the SVG files or not, (remove useless information like: editor metadata, comments, hidden elements, etc.), the optimization is done using SVGO

svgoConfig

  • type: import("svgo").Config (SVGO configuration)
  • default: default SVGO Options

When optimize is set to true, you can pass options to SVGO to configure the optimization process.

Example

svgx({
  optimize: true,
  svgoConfig: {
    multipass: true,
  },
});

runtime

  • type: "classic" | "automatic"
  • default: "automatic"

Wether to use classic or automatic JSX runtime, you can read more about it in the React official documentation (Introducing the New JSX Transform), if you are not sure, just leave the default setting as Qwik supports both automatic and classic runtimes.

importSource

  • type: string
  • default: "@builder.io/qwik"

Specify where you want to import the JSX runtime from, this is especially useful if you want to use the plugin with other JSX based libraries like React, Preact, Vue, etc.

when runtime is set to "automatic", and importSource is set to "@builder.io/qwik", this is transformed automatically to @builder.io/qwik/jsx-runtime, and when runtime is set to "classic", importSource is set to "@builder.io/qwik". so you just need to set the package name for this option and the rest is handled for you based on the runtime.

pragma

  • type: string
  • default: "h"

You don't need to touch this setting if you are using Qwik, but in case you want to use this plugin with another JSX based library you can set this option to the pragma specific to that library (createElement in case of React), you need to use this setting only when runtime is classic, as the case of automatic runtime is handled automatically,

pragmaFrag

  • type: string
  • default: "Fragment"

You don't need to touch this setting either if you are using Qwik, all of what has been said for the previous option applies here too, but for the pragma used to handle the fragments.

If you dont know what the pragma is, these pages may help you get an idea of it:

Typescript

If you are using typescript you may have noticed that typescript is showing this error when using these imports:

Cannot find module '@svgx-import:/path/to/directory' or its corresponding type declarations.

or

Cannot find module '/path/to/icon.svg?component' or its corresponding type declarations

To fix this, and to get proper types for the imported components you need to include "@svgx/vite-plugin-qwik" in the types array in the compilerOptions of your tsconfig.json file.

Note: if you have "vite/client" in that array, make sure to include the above declaration file before it, as it may have collisions with it, or better, include it as the first element in the array, like so:

"compilerOptions": {
  "types": ["@svgx/vite-plugin-qwik", "node", "vite/client"],
  // ...other settings
}

If you still have problems with typescript make sure to use the suffixes, especially the ?component suffix if you want to import the SVG as a component. as stated above, you can import the SVG as a component without using any suffixes, but it is highly recomanded to use them.

Another way to use the plugin with typescript is to use the reference triple slash directive:

/// <reference types="@svgx/vite-plugin-qwik" />