svg-loader: una forma diferente de trabajar con SVG externo | Programar Plus

Los SVG son increíbles: son pequeños, se ven nítidos en cualquier escala y se pueden personalizar sin crear un archivo separado. Sin embargo, hay algo que creo que falta en los estándares web de hoy: una forma de incluirlos como un archivo externo que también conserva los poderes de personalización del formato.

Por ejemplo, supongamos que desea utilizar el logotipo de su sitio web almacenado como web-logo.svg. Tu puedes hacer:

<img src="https://css-tricks.com/images/logo.svg" />

Está bien si su logotipo se verá igual en todas partes. Pero en muchos casos, tiene 2-3 variaciones del mismo logotipo. Slack, por ejemplo, tiene dos versiones.

Incluso los colores del logotipo principal son ligeramente diferentes.

Si tuviéramos una forma de personalizar el color de relleno de nuestro logotipo anterior, podríamos pasar cualquier color arbitrario para representar todas las variaciones.

Tomemos también el caso de los iconos. No querrías hacer algo como esto, ¿verdad?

<img src="https://css-tricks.com/icons/heart-blue.svg" />
<img src="https://css-tricks.com/icons/heart-red.svg" />

Cargar SVG externos como elementos en línea

Para solucionar esto, he creado una biblioteca llamada svg-loader. En pocas palabras, obtiene los archivos SVG a través de XHR y los carga como elementos en línea, lo que le permite personalizar las propiedades como fill y stroke, al igual que los SVG en línea.

Por ejemplo, tengo un logo en mi proyecto paralelo, SVGBox. En lugar de crear un archivo diferente para cada variación, puedo tener un archivo y personalizar el color de relleno:

solía data-src para configurar la URL del archivo SVG. El fill anulaciones de atributos fill del archivo SVG original.

Para usar la biblioteca, lo único que tengo que asegurar es que los archivos que se sirven tengan los encabezados CORS apropiados para que los XHR tengan éxito. La biblioteca también almacena en caché los archivos localmente, lo que hace que el siguiente sea mucho más rápido. Incluso para la primera carga, el rendimiento es comparable al uso <img> etiquetas

Este concepto no es nuevo. svg-inject hace algo similar. Sin embargo, svg-loader es más fácil de usar ya que solo tenemos que incluir la biblioteca en algún lugar de su código (ya sea a través de un <script> etiqueta, o en el paquete de JavaScript). No se necesita ningún código adicional.

Los elementos agregados dinámicamente y los cambios en los atributos también se manejan automáticamente, lo que garantiza que funcione con todos los marcos web. Aquí hay un ejemplo en React:

¿Pero por qué?

Este enfoque puede parecer poco ortodoxo porque introduce una dependencia de JavaScript y ya hay varias formas de usar SVG, incluidos en línea y de fuentes externas. Pero hay un buen caso para usar SVG de esta manera. Examinémoslos respondiendo las preguntas comunes.

¿No podemos simplemente incluir SVG en línea nosotros mismos?

Inlining es la forma más sencilla de utilizar SVG. Simplemente copie y pegue el código SVG en el HTML. Eso es lo que finalmente está haciendo svg-loader. Entonces, ¿por qué agregar los pasos adicionales para cargar un archivo SVG desde otro lugar? Hay dos razones mayores:

  1. Los SVG en línea hacen que el código sea detallado: Los SVG pueden tener desde unas pocas líneas hasta unos pocos cientos. Los SVG en línea pueden funcionar bien si lo que necesita son solo un par de iconos y todos son pequeños. Pero se vuelve un gran problema si son grandes o muchos, porque entonces, se convierten en largas cadenas de texto en un código que no es “lógica empresarial”. El código se vuelve difícil de analizar.

    Es lo mismo que preferir una hoja de estilo externa a una <style> etiquetar o usar imágenes en lugar de URI de datos. No es de extrañar que en las bases de código de React, el enfoque preferido sea usar SVG como un componente separado, en lugar de definirlo como parte de JSX.

  1. Los SVG externos son mucho más convenientes: Copiar y pegar a menudo funciona, pero los archivos SVG externos pueden ser realmente convenientes. Supongamos que está experimentando con qué ícono usar en su aplicación. Si está utilizando SVG en línea, eso significa ir y venir para obtener el código SVG. Pero con los SVG externos, solo tienes que saber el nombre del archivo.

    Echale un vistazo a éste ejemplo. Uno de los repositorios de íconos más extensos en GitHub es Material Design Icons. Con svg-loader y unpkg, podemos comenzar a usar cualquiera de los más de 5,000 íconos de inmediato.

¿No es ineficiente activar una solicitud HTTP para cada SVG en lugar de hacer un sprite?

Realmente no. Con HTTP2, el costo de realizar una solicitud HTTP se ha vuelto menos relevante. Sí, todavía hay beneficios de la agrupación (por ejemplo, mejor compresión), pero para los recursos sin bloqueo y XHR, los pros son casi inexistentes en escenarios del mundo real.

Aquí hay un lápiz que carga 50 íconos de manera similar a la anterior. (Abrir en modo incógnito ya que los archivos se almacenan en caché de forma predeterminada):

Qué pasa <use> etiqueta (símbolos SVG)?

Los símbolos SVG separan la definición del archivo SVG de su uso. En lugar de definir el SVG en todas partes, podemos tener algo como esto:

<svg>
  <use xlink:href="https://css-tricks.com/svg-loader-a-different-way-to-work-with-external-svg/#heart-icon" />
</svg>

El problema es que ninguno de los navegadores admite el uso de archivos de símbolos alojados en un dominio de terceros. Por lo tanto, no podemos hacer algo como esto:

<svg>
  <use xlink:href="https://icons.com/symbols.svg#heart-icon" />
</svg>

Safari ni siquiera admite archivos de símbolos alojados en el mismo dominio.

¿No podemos usar una herramienta de construcción que incorpore los SVG?

No pude encontrar una forma obvia de recuperar archivos SVG de una URL e insertarlos en paquetes comunes, como webpack y Grunt, aunque existen para insertar archivos SVG almacenados localmente. Incluso si existe un complemento que hace esto, configurar agrupadores no es exactamente sencillo. De hecho, a menudo evito usarlos hasta que el proyecto ha alcanzado cierto nivel de complejidad. También debemos darnos cuenta de que la mayoría de Internet es ajena a cosas como webpack y React. Los scripts simples pueden tener un atractivo mucho más amplio.

Qué pasa con la <object> ¿etiqueta?

El <object> La etiqueta es una forma nativa de incluir archivos SVG externos que funcionan en todos los navegadores:

<object data="https://unpkg.com/[email protected]/svg/access-point-network.svg" width="32" height="32"></object>

Sin embargo, el inconveniente es que no podemos personalizar los atributos del SVG a menos que esté alojado en el mismo dominio (y el <object> etiqueta no respeta los encabezados CORS). Incluso si el archivo está alojado en el mismo dominio, necesitaríamos JavaScript para manipular el fill, como esto:

<object data="https://unpkg.com/[email protected]/svg/access-point-network.svg" width="32" height="32" onload="this.contentDocument.querySelector('svg').fill="red""></object>

En resumen, usar archivos SVG externos de esta manera hace que sea muy conveniente usar íconos y otros activos SVG. Como se mencionó anteriormente, con unkg, podemos usar cualquier ícono en GitHub sin necesidad de código adicional. Podemos evitar crear una canalización en un paquete para procesar archivos SVG o un componente para cada ícono, y simplemente alojar los íconos en un CDN.

La carga de archivos SVG de esta manera conlleva muchos beneficios con muy poco costo.