Love Frontend
Сообщество
фронтенд разработчиков
EN

Как подключить всю папку svg изображений в webpack

Дата публикации: 16.07.2017

Данная статья содержит развёрнутый ответ на вопрос: "Как в webpack подключить всю папку svg, картинок, изображений, png, jpg и т.д."

Это относится именно к тем случаям, когда ресурсы подключаются не в стилях CSS, а именно вставляются в шаблон. Например во Vue в таком случае вы будете использовать такую конструкцию:

 <div v-html="svgIcon"></div>  

Где svgIcon – это переменная содержащая разметку SVG изображения. (Обычно для этих целей используется svg-inline-loader для webpack).

Так вот, вероятнее всего вы делаете так:

   import SVG1 from './assets/images/svg1'
import SVG2 from './assets/images/svg2'
import SVG3 from './assets/images/svg3'
...
data () {
return {
items: [
{
name: 'kuku',
icon: SVG1
},
{
name: 'blabla',
icon: SVG2
},
{
name: 'good',
icon: SVG3
}
]
}
}

И предположим в шаблоне вы выводите SVG следующим образом:

 <div v-for="item in items" v-html="item.icon"></div>   

Данная конструкция выведет все иконки у каждого item

Да, конечно вы сами чуствуете, что можно сделать более элегантно. К тому же если у вас много ресурсов, то файл компонента просто превратится в полотно.

Тут нам на помощь придёт такая чудная фича webpack - require.context.

В нашем случае нужно будет использовать её так:

   const SVG = require.context('../assets/svg/menu', true, /\.svg$/)  

первый параметр - путь до файлов, второе булево значение говорит функции, что нужно пройти папки рекурсивно и третий параметр шаблон регулярного выражения для взятия нужных ресурсов. В нашем случае все svg файлы.

Обратите внимание, что данная функция возвращает другую функцию. Да, нам нужно будет вызывать нашу константу SVG с нужным нам названием изображения, чтобы его получить из массива. Сам массив собранных svg вы можете увидеть вызвав метод keys() у возвращённой функции. То есть SVG.keys().

Но нам же нужно написать функцию, которая подставит название svg иконки, она будет выглядеть так:

 const getSVG = nameOfLogo => SVG(`./${nameOfLogo}.svg`)  

Теперь код выглядит так:

   const SVG = require.context('../assets/svg/menu', true, /\.svg$/)
const getSVG = nameOfLogo => SVG(`./${nameOfLogo}.svg`)
module exports = {
data () {
return {
items: [
{
name: 'kuku',
icon: getSVG('svg1')
},
{
name: 'blabla',
icon: getSVG('svg2')
},
{
name: 'good',
icon: getSVG('svg3')
}
]
}
}
}

Больше нет импорта каждой svg отдельно.

Но это ещё не всё, на последок можно ещё более упростить всю конструкцию и убрать повторяющиеся свойства объектов item.

Можно сделать так:

   data () {
return {
items: [
['kuku', 'svg1'],
['blabla', 'svg2'],
['good', 'svg3']
].map(i => ({ name: i[0], icon: getSVG(i[1])}))
}
}

Последнее не является обязательным и возможно кого-то запутает, однако я люблю использовать такой подход, чтобы не дублировать названия свойств в объектах. Например при статичном меню написанном на фронте, предпочитаю делать именно так.

Оставьте свой e-mail чтобы получать уведомления о свежих статьях.