GithubHelp home page GithubHelp logo

alexcanessa / react-svg-use-external Goto Github PK

View Code? Open in Web Editor NEW
1.0 5.0 1.0 418 KB

A React library that enables external SVG <use> references in all browsers that support SVG

Home Page: https://react-svg-use-external.netlify.com

License: MIT License

JavaScript 88.35% HTML 9.23% CSS 2.42%
react svg polyfill svg-sprite

react-svg-use-external's Introduction

react-svg-use-external

Build Status Code coverage npm

A React library that enables external SVG <use> references in all browsers that support SVG.

Check out the demo.

Inspired by SVG for Everybody.

Usage

In your React SVG rendering code, replace <svg> and <use> with <Svg> and <Use> from this library:

import { Svg, Use } from "@digital-detox/react-svg-use-external";

<Svg
  style={{
    width: 64,
    height: 64,
    display: "inline-block",
    fill: "none",
    stroke: "currentColor",
    strokeWidth: ".4em",
    verticalAlign: "middle"
  }}
>
  <Use xlinkHref="/static/sprites.svg#icon-close" />
</Svg>;

These components are drop-in replacements for the <svg> and <use> React DOM intrinsics, supporting the exact same props. In fact, on browsers that don't need the polyfill, you'll find that Svg === "svg" and Use === "use".

In the rare case you need to access the underlying DOM elements, <Svg> and <Use> have you covered by the use of ref forwarding. Note that <Use> may render a <g> (SVGGElement) instance and not necessarily an actual SVGUseElement when the polyfill is active.

Browser support

This library supports IE 9 and up and should generally match svg4everybody's browser support as it uses similar techniques underneath. Polyfills for fetch, Promise and Map are required in environments that don't support these APIs.

Differences from svg4everybody

  • There is no fallback to <img> (and hence no support for IE < 9).
  • <use> references (internal or external) in the imported SVG content aren't resolved recursively (#5).
  • This polyfill observes the strict same-origin policy that all modern browsers apply to <use> references (ignoring CORS headers), as formally specified in SVG 2.

react-svg-use-external's People

Contributors

motiz88 avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

knobay

react-svg-use-external's Issues

Documentation for contributors

Most of this can go in README or a separate file.

  • Add semantic-release badge to README
  • Mention commit message format
  • Mention deploy previews
  • Mention required manual tests (cross-browser)
  • Mention Yarn, yarn.lock

Synchronous rerender with the same resource results in multiple requests

The following test code results in two requests being made to http://localhost/sprites.svg because we don't cache the fetch promise for a resource, only the parsed document after a successful fetch. Something similar would likely happen if we rendered multiple components referencing the same resource - a key use case for this library (TODO: add a separate test for that).

https://github.com/digital-detox/react-svg-use-external/blob/c8291c18813937e46d9f008632083ef2a1144b93/src/lib/__tests__/Use.test.js#L177-L186

The solution is probably to use DataLoader instead of rolling our own caching logic.

Introduce bounded and/or configurable document caching/refcounting

Currently, we cache parsed SVG documents on document.__SVG_USE_DOCUMENT_CACHE__ which is a simple Map. This is mostly fine assuming the number of different SVG documents used throughout the page's lifetime is bounded and not too large (a reasonable assumption in sprite-sheet scenarios). For long-lived pages that render very dynamic content, however, the unbounded growth may be a problem.

Some form of LRU cache naturally comes to mind - I originally used https://github.com/sindresorhus/quick-lru but reverted to Map after having bundling issues with the former.

Refcounting may be another valid strategy - keeping documents cached as long as they're referenced by a Use instance anywhere on the page, and only then possibly spilling into an LRU cache.

An open question is what API to use in order to make this cache usefully configurable (or, conversely, can we get away with a one-size-fits-all solution?)

One thing I don't want to do is complicate the API surface of this library more than necessary. I can envision an optional context-based API for setting cache parameters for a subtree, but one that will always fall back to a global cache.

import { SvgCache, Svg, Use } from "react-svg-use-external";

// We'd support something like this...

<SvgCache size={100}>
  <Svg>
    <Use />
  </Svg>
</SvgCache>

// ... but always still support this:
<Svg>
  <Use />
</Svg>

Note for DDers: The internal project that relies on react-svg-use-external likely doesn't need this fixed.

Create JSDOM unit tests

  • Test with Jest + JSDOM - started in #13
  • Report coverage and add README badge (e.g. codecov.io) - done in #13
  • Attain full unit test coverage - done in #20

Validate yarn.lock in CI

We should run yarn install --frozen-lockfile as the install step on Travis to catch missing yarn.lock updates.

Release this package

Continuously publish this package to npm using semantic-release.

  • Publish private scoped package - done as of 28fea90
  • Make scoped package public - done in #11

To do after resolving #1 and #5 (and ideally starting on #4)

  • Move to unscoped package name react-svg-use-external

Warn if rendering <Use> outside of <Svg>

<Use> has a dependency on the context provided by its containing <Svg> component, for the purpose of setting the viewBox correctly on the container.

Ideally, we should consistently catch this in development mode even if not polyfilling, so developers working in Chrome etc are notified long before the code goes through cross-browser testing. This means we can't universally fall back to <svg> and <use> on modern browsers, but (1) we should still do so in production, and (2) we shouldn't revert to the full polyfill, but rather to a thin wrapper implementing the warning.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.