Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any reason why this lib can't read files? #753

Closed
Radilx opened this issue Aug 10, 2018 · 22 comments
Closed

Any reason why this lib can't read files? #753

Radilx opened this issue Aug 10, 2018 · 22 comments

Comments

@Radilx
Copy link

Radilx commented Aug 10, 2018

Apparently, there is still no good solution for reading SVG files?

I created my own script to deal with this for now (https://github.com/SM-Wistful/react-native-svg) but it's messy and written in Python. Why doesn't this library just read the file and use a bit of regex to convert it into a format that react-native-svg can understand?

I would have tried to make my project into a react-native library but I'm still learning the framework. Is it even being considered to add this?

@rodrigoelp
Copy link

Hi @SM-Wistful, I guess the guys maintaining this library are still trying to wrap up the foundation of svg in order to support other features (such as reading svg directly)

If you read the README.md file, it states quite clearly (at the bottom):

TODO:

  1. Add Native methods for elements.
  2. Pattern element.
  3. Mask element.
  4. Marker element.
  5. Load Image from URL.

Point 5 is the one you are talking about.

That would explain why they haven't generated a parser to translate svg files into react-native-svg (they need the native support first in order to make things smoother)

@msand
Copy link
Collaborator

msand commented Aug 17, 2018

I haven't properly evaluated https://github.com/target/react-native-svg-parser and https://github.com/vault-development/react-native-svg-uri
One of these could possibly be integrated.
Ideally it would be a babel plugin, allowing to import svg files, converting them to use react and react-native-svg, and allowing it be chained with e.g. https://babeljs.io/docs/en/babel-plugin-transform-react-inline-elements.html and https://babeljs.io/docs/en/babel-plugin-transform-react-constant-elements/
Such that the parsing and conversion can be done only once at buildtime, or alternatively, some runtime cache could be used for it. But, at least, the static nature of svg files should be optimised for.
At the moment, a script to convert .svg to .js/.jsx and importing that is probably the best performing way achieve this. Like this approach: https://github.com/SM-Wistful/react-native-svg
So, if someone could write a babel-plugin, then I would fully endorse that approach at least. These existing ones would probably make sense to document as workarounds for now as well.

@maxkomarychev
Copy link
Contributor

How would babel plugin help reading svg dynamically from arbitrary http url?

@msand
Copy link
Collaborator

msand commented Aug 17, 2018

But then again, keeping this functionality separate from the main rendering logic probably still makes sense. Some people won't need the svg dom parsing, hence its (imho) better to keep the core rendering logic module as small as possible.

@msand
Copy link
Collaborator

msand commented Aug 17, 2018

Well, for loading svg from url you'll need the parser available at runtime, so then your requirements demand to bundle it, but otherwise it would be unused code included into every project which depends on the renderer.

@stowball
Copy link

I wrote my own remote SVG parser because I wasn't happy with the other options out there, and while it works, it is quite slow on real iOS devices, but the simulators are perfect.

For Android, we integrated a native SVG module and wrote another remote bridge, so that actually renders all SVG natively now

@msand
Copy link
Collaborator

msand commented Sep 8, 2018

Found another option: https://github.com/smooth-code/svgr
Has node api: https://github.com/smooth-code/svgr/tree/master/packages/core
also cli, webpack loader, rollup plugin, and a web gui: https://svgr.now.sh/
but no babel plugin what I can find

@msand
Copy link
Collaborator

msand commented Sep 8, 2018

https://github.com/airbnb/babel-plugin-inline-react-svg/blob/master/src/index.js has most of the necessary logic, porting the logic (from svgr) for the differences between web svg and react-native-svg to the babel-plugin-inline-react-svg or making a babel version of svgr would give a complete solution.
@neoziro @ljharb Has either one of you planned anything like this?

@gregberge
Copy link

I would like to do it but babel plugin must be synchronous. As SVGR has built-in support for SVGO, it is actually the blocker to create a babel plugin: svg/svgo#1015

I could make it by disabling SVGO.

@msand
Copy link
Collaborator

msand commented Sep 10, 2018

@neoziro Actually, svgo has the _optimizeOnce method, it takes a callback but in reality is synchronous and gets called before optimizeonce returns.

@gregberge
Copy link

@msand I can't rely on internal method that takes a callback and that is technically synchronous. SVGO team doesn't want to do any effort. If I had time I would like to create a new SVGO based on unified. If someone is interested!

@msand
Copy link
Collaborator

msand commented Sep 15, 2018

I'm thinking that just taking the fastest possible xml parser, and doing the smallest possible transformation on it, would be ideal. At least for the loading of svg from uri and rendering on demand, if that is to be included in the main react-native-svg package.

A babel plugin for making react components from .svg files using the import syntax can have any amount of transforms on top configured with babelrc etc, and any optimisers implemented there could be used as middleware on top of normal fetch requests for svg files, if people have some special tradeoffs to take into account.

But at least to be spec conformant, referencing svg files using uris in the normal svg syntax shouldn't apply any special transforms. And probably should optimise for parsing performance and code bundle size. Or what do you think?

Btw, you can always fork svgo and just make that method public, or lock down the peer dependency version. And as you can see, the optimize method mostly just handles the multipass logic by calling _optimizeOnce repeatedly: https://github.com/svg/svgo/blob/62f67dee297430869e41f5649996699c44c68e5f/lib/svgo.js#L24-L72
Refactoring that to be completely synchronous and return the value straight wouldn't be much work.
Or are there some other benefits to using unified I'm unaware of?

Alternatively could request that svgo make the method "public" and supported. Essentially just removing the underscore from the beginning of the name. But I consider it a public method already, in javascript, private methods are hidden by closures, using weakmaps, or using the new private method syntax (# character).
https://github.com/tc39/proposal-private-methods
https://github.com/tc39/proposal-class-fields
Having an underscore as the first character of the name affects nothing but the name.

@msand
Copy link
Collaborator

msand commented Dec 9, 2018

@neoziro How is progress / your current thinking on this?

@gregberge
Copy link

@msand In finally decided to use the internal method. SVGR now exposes a synchronous method, not yet a Babel plugin, but it is technically possible to implement one.

@msand
Copy link
Collaborator

msand commented Jan 24, 2019

@neoziro I've added docs for using svg files now: https://github.com/react-native-community/react-native-svg#use-with-svg-files

.babelrc

{
  "presets": ["module:metro-react-native-babel-preset"],
  "plugins": [
    ["babel-plugin-inline-import", {
      "extensions": [
        ".svg"
      ]
    }]
  ]
}

App.js

import * as React from 'react';
import SvgUri from 'react-native-svg-uri';
import testSvg from './test.svg';
export default () => (
  <SvgUri
    width="200"
    height="200"
    svgXmlData={testSvg}
  />
);

Can svgr be given the .svg content, and output a function, rather than source code?
Either way, a babel plugin to do it only in development / at compile-time when the source changes, rather than every render or each startup at runtime, would be needed for proper performance. Or, at the very least caching it by filename/uri.

@msand
Copy link
Collaborator

msand commented Jan 25, 2019

@msand
Copy link
Collaborator

msand commented Jan 25, 2019

@msand
Copy link
Collaborator

msand commented Jan 25, 2019

@msand
Copy link
Collaborator

msand commented Jan 25, 2019

@brentvatne @ide Would it be possible to get react-native-svg-transform into Snack? Such that one could import an .svg file and use it as a component?
https://github.com/kristerkari/react-native-svg-transformer#step-3-configure-the-react-native-packager

import Logo from "./logo.svg"
const MyApp = () => <Logo width={120} height={40} />
export default MyApp

@msand
Copy link
Collaborator

msand commented Jan 25, 2019

I guess this issue could probably be closed at this point, as both remote and local svg files can be handled in multiple ways now.

@msand msand closed this as completed Jan 25, 2019
@msand
Copy link
Collaborator

msand commented Oct 19, 2019

SvgXml and SvgUri are exposed by react-native-svg nowadays, in case some stumbles upon this issue.

@douglassoldan
Copy link

douglassoldan commented Oct 14, 2022

import {WithLocalSvg} from 'react-native-svg';
const FileName = require('.../.../file.svg');
<WithLocalSvg asset={FileName} width={100} height={100} />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants