expo / vector-icons

https://icons.expo.fyi
MIT License
659 stars 115 forks source link

Bundle vector-icon with the app for offline access #29

Closed James2516 closed 6 years ago

James2516 commented 6 years ago

I used 2 icons with Ionicons. Is there a way to bundle the 2 icons to the app such that the user would not require internet connection to get the icons rendered?

I have also noticed something strange: https://docs.expo.io/versions/latest/guides/icons.html#existing-projects I didn’t actually have to add those fields to my app.json. The 2 icons i used are ios-checkbox and ios-square-outline. Is that only required for certain icons?

brentvatne commented 6 years ago

Hello! If you cache the assets on first load then it will work if they have an internet connection at the time: https://docs.expo.io/versions/latest/guides/preloading-and-caching-assets.html and subsequent loads will not require an internet connection.

We are currently working on bundling assets in standalone apps and hope to have a first version of it ready for sdk 23, barring any unforeseen complications.

James2516 commented 6 years ago

The assets are critical to the app, so it needs to be available even if the user decided to turn off the internet after installation and before opening the app.

Is there currently no way to store image data with the source code without needing to download from cloud? Would Base64 encoding of vector icons be possible?

If not, my only option is to eject?

brentvatne commented 6 years ago

Unfortunately the only option is to eject right now if that is the case. Or if you can wait a month we will include asset bundling.

Karsens commented 6 years ago

Awesome that you are going to include this in SDK 23 :) Really important for me too.

brentvatne commented 6 years ago

hey @James2516 and @karsens - it looks like this won't quite make it for sdk23, we tried our best but we want to do a bit more work on it before we release it to ensure that it works great out of the box. it's a big feature and we want to err on the side of safety here. sdk24 should do the trick

Karsens commented 6 years ago

Ah that's allright. Looking forward to it. :)

keith-kurak commented 6 years ago

Now that this feature exists for fonts as of Expo 25, a question on how to use it. I assume we need to include the font files in the @expo/vector-icons packages in the assetBundlePatterns in app.json as such:

"assetBundlePatterns": [
      "node_modules/@expo/vector-icons/fonts/**"
    ],

Is this correct, or is there something else happening with this package that would make doing this unnecessary? Thanks!

brentvatne commented 6 years ago

that will work yeah! but maybe you want to just include the fonts that you use specifically, so rather than ** you can point to like FontAwesome.ttf for example

Asday commented 5 years ago

Doesn't seem to work - I also nocite there's no such thing in my node_modules/ as @expo/vector-icons/fonts/. The closest thing is @expo/vector-icons/build/vendor/react-native-vector-icons/Fonts/, but thar doesn't appear to do anything when added to assetBundlePatterns[].

brentvatne commented 5 years ago

hey @Asday - you should add a leading ./ before the path, like so:

    "assetBundlePatterns": [
      "./node_modules/@expo/vector-icons/**/*"
    ]

you can verify what is included in the bundled assets by inspecting the manifest, eg: https://expo.io/@notbrent/my-vector-icons-app/index.exp?sdkVersion=33.0.0

paths without the leading "./" should work but it appears that they do not currently, making an issue for that

brentvatne commented 5 years ago

my bad, i was actually incorrect, it does indeed work as expected:

    "assetBundlePatterns": [
      "node_modules/@expo/vector-icons/**/*"
    ]

this will work. or alternatively, if you just do "*/" as the only pattern then it will bundle every asset you're using

Asday commented 5 years ago

I already had "**/*", and inspection of the output of expo export <...> has my assets in there.

For some reason, though, expo refuses to load any assets except the splash screen and icon. I don't even see any requests for them in my server's access log. My guess is I'm having a different issue because I'm trying to do weird stuff.

brentvatne commented 5 years ago

hmm if you can create a new issue on the main expo repo with more information and a reproducible example we can look into it

Asday commented 5 years ago

For sure, once I've investigated it more. I'm definitely doing something not intended, at least by Apple, if not by Expo.

Asday commented 5 years ago

I cracked it, but it was absolutely nothing to do with this issue, and I'm making my job 100x easier by most definitely subverting what Apple wants me to do. I haven't seen anyone else have the issue either, so I'm going to keep quiet until then.

Thank you for being so responsive and helpful so far @brentvatne, I really appreciate it.

ksairi commented 4 years ago

@brentvatne an observation to your comment .... or alternatively, if you just do "**/*" as the only pattern then it will bundle every asset you're using.

That is not happening to me, it is actually adding all the fonts (although I'm using only two of them) and other .pngs besides the ones I'm actually using. cheers!

brentvatne commented 4 years ago

@ksairi - it will include all assets that are imported from code that you import, regardless of whether you actually include that in your app code - metro (react-native packager) can't tell whether you actually render the component or not, it just knows that the file was imported. it doesn't properly handle es6 imports like webpack, so these imports are eagerly evaluated: https://github.com/expo/vector-icons/blob/master/src/Icons.ts. if you import with this style import FontAwesome from '@expo/vector-icons/FontAwesome' that should only bring in the font you want, but you have to make sure you don't import anything directly from @expo/vector-icons top main entrypoint elsewhere in your code

ksairi commented 4 years ago

@brentvatne cool! All clear now, thanks for that! And what about the .pngs? It is importing more .pngs that I'm actually requiring

brentvatne commented 4 years ago

probably some library that you are using is importing those, you'd have to audit specifically what the images are and where they come from

ksairi commented 4 years ago

@brentvatne thank you much!

Maffinius commented 3 years ago

Hey all, i tried everything stated in this issue but it still seems kinda buggy. My code goes like this:

"assetBundlePatterns": [ "assets/images/*", "assets/icons/*", "assets/fonts/*", "node_modules/@expo/vector-icons/fonts/EvilIcons.ttf", "node_modules/@expo/vector-icons/fonts/FontAwesome.ttf", "node_modules/@expo/vector-icons/fonts/FontAwesome5.ttf", "node_modules/@expo/vector-icons/fonts/Entypo.ttf" ],

I think this code is correct but the fonts still do not get loaded offline (wich breaks my app pretty bad).

Asday commented 3 years ago

@Maffinius How are you loading the app offline?

zzswang commented 2 years ago

Any update?

AlenToma commented 2 years ago

This is my settings and still not working?

Any idea ? app.json

  "expo": {
    "assetBundlePatterns": [
      "./node_modules/@expo/vector-icons/build/vendor/react-native-vector-icons/Fonts/*"
    ],
    },
AlenToma commented 2 years ago

Hi guys, after much work and research I came across this site https://docs.expo.dev/guides/preloading-and-caching-assets/ it says that I have to preload the fonts. But I am getting a connection error even though I am loading it from the assets, this is really funny

Here is my code incase anyone want to point out What I am doing wrong.

import * as React from 'react'
import { StyleProp, TextStyle, Text } from 'react-native'
import AntDesign from '@expo/vector-icons/AntDesign'
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons'
import Ionicons from '@expo/vector-icons/Ionicons'
import MaterialIcons from '@expo/vector-icons/MaterialIcons'
import Entypo from '@expo/vector-icons/Entypo'
import Feather from '@expo/vector-icons/Feather'
import FontAwesome5 from '@expo/vector-icons/FontAwesome5'
import FontAwesome from '@expo/vector-icons/FontAwesome'
import Fontisto from '@expo/vector-icons/Fontisto'
import EvilIcons from '@expo/vector-icons/EvilIcons'
import * as Font from 'expo-font';
const IconTypeArray = {
    AntDesign,
    MaterialCommunityIcons,
    Ionicons,
    MaterialIcons,
    Entypo,
    Feather,
    Fontisto,
    FontAwesome5,
    FontAwesome,
    EvilIcons
} as any;

type ElementType = "AntDesign" | "MaterialCommunityIcons" | "Ionicons" | "MaterialIcons" | "Entypo" | "Feather" | "FontAwesome5" | "FontAwesome" | "Fontisto" | "EvilIcons";

export default (props: { type: ElementType, name: string, size?: number, color?: string, style?: StyleProp<TextStyle> }) => {
    const Icon = IconTypeArray[props.type];
    const pType = { ...props } as any;
    const [loaded] = Font.useFonts({
        ...Icon.font
      });
    delete pType.type;

    if (!loaded)
        return <Text>Loading</Text>
    return (
        <Icon {...pType} />
    )
}

simple call the components

<Icon type="Ionicons" name='md-reload-circle' size={20} color="red" />