mikevercoelen / icons-loader

Icons loader for webpack, generates iconfonts for webpack
https://www.npmjs.com/package/icons-loader
36 stars 9 forks source link

Icons loader (generate iconfonts for webpack)

This is a webpack loader for generating an iconfont from SVG dependencies.

Based on iconfont-loader by Jussi Kalliokoski thanks and <3.

It uses gulp-iconfont to create the font.

Features

Installation

npm install icons-loader --save-dev

Basic usage

Add the loader and plugin to your webpack config:

import IconsPlugin from 'icons-loader/IconsPlugin'

const RUN_TIMESTAMP = Math.round(Date.now() / 1000)

const webpackConfig = {
  loaders: [{
      test: /\.svg$/,
      loader: 'icons-loader',
  }],
  plugins: [
    new IconsPlugin({
      fontName: 'icons',
      timestamp: RUN_TIMESTAMP,
      normalize: true,
      formats: ['ttf', 'eot', 'woff', 'svg']
    })
  ]
}

Now you can require the icons in your code:

import iconFont from 'icons-loader'
import menu from './menu.svg'

console.log(iconFont) /*
{
  css: '@font-face(...)', // you could inject this into your body by using style-inject package?
  fontName: 'icons',
  glyphs: [1],
  <generated_icon_id>: {
    character: 'ea01',
    fontName: 'icons',
    unicode: ['']
  } ...
}
*/

console.log(menu) /*
{
  character: 'ea01',
  fontName: 'icons',
  unicode: ['']
}
*/

Example workflow integration

So how can you integrate icons-loader into your webpack workflow? Here is how I use it:

import menu from './menu.svg'
import cross from './cross.svg'

export default {
  menu: menu,
  cross: cross
}

src/components/icon.scss

.icon {
  font-weight: normal;
  font-style: normal;
  font-decoration: none;
  text-transform: none;
  vertical-align: middle;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

src/components/icon.js

import React, { Component, PropTypes } from 'react'

import styles from './icon.scss'
import * as icons from 'icons'

export default class Icon extends Component {
  static propTypes = {
    name: PropTypes.string.isRequired
  }

  render () {
    let icon = icons[this.props.name]

    if (icon === undefined) {
      console.warn('Unknown icon: ' + icon)
      return
    }

    return (
      <span
        className={styles.icon}
        style={
          fontFamily: icon.fontName
        }>
        {icon.unicode}
      </span>
    )
  }
}

src/components/header.js

<Icon name='icon-file-name' />
<Icon name='menu' />

The best way to do this is in your main app component. For example:

import React from 'react'
import { render } from 'react-dom'

...

import styleInject from 'style-inject'
import iconFont from 'icons-loader'

const injectIconFont = function () {
  styleInject(iconFont.css)
}

injectIconFont()

...

Options

Plugin

You can also add gulp-iconfont options.

Recommended options


const RUN_TIMESTAMP = Math.round(Date.now() / 1000)
const iconsPluginOptions = {
  fontName: 'icons',
  timestamp: RUN_TIMESTAMP,
  normalize: true,
  formats: ['ttf', 'eot', 'woff', 'svg']
}

Loader

template

The template option of the loader is the template for the module generated by the loader. By default the template is:

module.export = __ICON__;

where __ICON__ is an object that has the properties fontName (the name of the generated font, passed in the plugin options) and text (a string representation of the character of icon in the font).

This allows you to for example export a React element instead:

const iconModuleTemplate = encodeURIComponent('module.exports = require("react").createElement("span", { className: "icon" }, __ICON__.text);');

const webpackConfig = {
  loaders: [{
      test: /\.svg$/,
      loader: "icons-loader?template=" + iconModuleTemplate,
  }],
  ...
}