0.1.2 • Published 2 years ago

icon-prerender v0.1.2

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

codecov

🚀 CI

🚀 Icon Prerender

A framework-agnostic plugin (likely compatible with your build tool) that prerenders your SVG icons at build time so your clients don't have to fetch them during browsing. Designed for ease-of-use and maximum performance.

Why?

There are several icon libraries out there. However, it is rare to find one that ticks all the following:

  • Works at build time (to minimise bundle size)
  • Does not affect your bundle size at all
  • Optimises SVGs at build time
  • Requires no configuration or fiddling with other configuration options
  • Allows you to simply specify icons in the template e.g., `mdi:chevron-right
  • Does not require importing a bunch of components or creating icon sets

This library is heavily inspired by astro-icon and essentially works the same except:

  • icon-prerender works for any framework, even raw HTML (provided you use a bundler)
  • astro-icon provides icon components - icon-prerender allows you to use just HTML
  • icon-prerender provides much more flexibility on how icons are specified
  • icon-prerender allows you to inline raw SVG elements

Again, astro-icon works in this way, but only supports .astro components and does not work with server-side rendering.

Installation

This plugin requires @iconify/json as a peer dependency:

npm i --save-dev icon-prerender @iconify/json
yarn add -D icon-prerender @iconify/json
pnpm i -D icon-prerender @iconify/json

I also recommend installing and enabling the iconify-intellisense VSCode extension by Anthony Fu.

Usage

In the template, you can define an icon to prerender as either:

  • One of the following HTML elements with a data-icon attribute:
    • <div>
    • <span>
    • <figure>
    • <img>
    • <svg>
    • any custom element tag
  • Any <svg /> element wrapped around a use tag with either a href or xlink:href attribute i.e.:
<svg>
  <use href="assets/icon.svg#id"></use>
</svg>
  • Note that for it to be valid HTML, you need to point to the ID of the element in the SVG file
  • This suffix is stripped when resolving the path to the raw SVG item

This last feather sets icon-prerender from other icon libraries as this is valid HTML - if you disabled icon-prerender, the above would still work (assuming the href points to a valid path). The only difference would be it would have to make an extra network request during runtime to fetch the SVG and would then have to render it.

So, the cases above describe the default resolution algorithm; by default, these are the only elements that will be transformed into <svg /> elements. See "Configuration" to see how this can be changed.

Additionally, the data-icon attribute can either be:

  • A [pack]:[name] string specifying the icon pack and the specific icon in the pack
  • A relative path to a .svg file
    • Note that this is relative to the build output directory - you can modify the asset chunk names to make the filenames more predictable if needed
    • This also means there is no need to register icon sets - just set the path to the SVG file and it will be inlined
  • An external URL pointing to an SVG file - this can be an API endpoint or simply a statically hosted SVG file
    • The API must return an raw SVG (not JSON or HTML) and must contain svg in the content-type header

Whatever you provide to data-icon will be resolved and prerendered at build time.

Any attributes defined on the original element (apart from data-icon unless it is a [pack]:[name] string) will be preserved and will override identical attributes in the resolved SVG element, except:

  • The class will be concatenated from both elements
  • Any children will be merged from both elements with children in the resolved SVG appearing lower in the template
    • In the case of a <use> tag wrapped inside an <svg>, the <use> tag will be removed

Note that icons can be nested inside each other, however, children will be resolved first. So the innermost icon will be prerendered first.

Then, you use the include the appropriate plugin with in your bundler's config:

Astro

import { defineConfig } from "astro/config";
import icons from "icon-prerender/astro";

export default defineConfig({
 integrations: [icons()],
})

Vite

import { defineConfig } from "vite";
import icons from "icon-prerender/vite";

export default defineConfig({
 plugins: [icons()],
})

Rollup

import { defineConfig } from "rollup";
import icons from "icon-prerender/rollup";

export default defineConfig({
 plugins: [icons()],
})

esbuild

import esbuild from "esbuild";
import icons from "icon-prerender/esbuild";

esbuild.build({
 plugins: [icons()],
}).catch(() => process.exit(1));

Webpack

In CommonJS form:

const IconPrerenderPluginWebpackPlugin = require("icon-prerender/webpack");

module.exports = {
  plugins: [new IconPrerenderPluginWebpackPlugin()],
}

Configuration

  • include - A regex, an array of strings (or regexes) of HTML attributes (can be custom) to filter elements on

    • If an attribute of any HTML element matches anything inside this array, it will be transformed into an SVG element.
    • default undefined - enables default filtering
  • exclude - A regex, an array of strings (or regexes) of HTML attributes (can be custom) to filter elements on

    • If an attribute of any HTML element matches anything inside this array, it will not be transformed into an SVG element.
    • default: undefined - enables default filtering

Note: specifying include or exclude will not override default filtering - they are used to either include extra elements, or exclude elements that would have been included for transformation by default.

Roadmap

  • Allow consumers to disable default resolution via a new plugin option

    • Completely custom resolution would then be achieved by simply using include and exclude in tandem with this new plugin option
  • Add more component tests, especially with larger files

Have any other ideas? Make a suggestion in the Discussions tab.

Contributing

To get started with development, you will need an editor (VS Code is recommended), a browser that runs JavaScript and some extra prerequisites:

To get started with contributing to this project, first fork this git repository:

git clone https://github.com/Ernxst/icon-prerender.git

Then, install dependencies and start coding.

Submitting Improvements

If you have a suggestion that would make this app better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE for more information.