Repository: flutter
Issue: [flutter_svg] Provide easy migration example(s) for `precachePicture`
Labels: package,p: flutter_svg

_Imported from https://github.com/dnfield/flutter_svg/issues/841_

Original report by @Dohmanlechx on Feb 3, 2023

I just updated this package to `2.0.0+1` and noticed how `precachePicture` no longer existed in the API.

Removed the affected functions from the "root page" of the app and yes, now my bottom navigation bar icons and the main logo are delayed. Didn't have this problem when I could precache the images.

I have found this: https://github.com/dnfield/flutter_svg/blob/master/vector_graphics.md#precachepicture
but unfortunately, it didn't tell me anything. Please provide proper code examples of how to precache an SVG resource, would be highly appreciated.

---
Comment by @hygehyge on Feb 3, 2023
@Dohmanlechx 
Maybe this would work.
```dart
const loader = SvgAssetLoader('res/large_icon.svg');
svg.cache.putIfAbsent(loader.cacheKey(null), () => loader.loadBytes(null));
```

---
Comment by @dnfield on Feb 4, 2023
1. Are your icons still delayed in release/profile mode? See #837 - in debug mode things are slower right now.
2. I can add something about precaching. The problem ends up being that people precache at "bad" times like startup, which delays whole app startup. It shouldn't be quite as bad with the new version because of isolates, but it's still not great.

The code that @hygehyge provided should work as well.

---
Comment by @Dohmanlechx on Feb 4, 2023
1. No, it's much better in profile mode! 🎉  The small icons in the bottom navigation bar load instantly, but the large SVG illustration we have on the main page still is a bit delayed. I wrote a similar comment here: https://github.com/dnfield/flutter_svg/issues/840#issuecomment-1416062838
2. Actually, we prefer like 500 ms slower app startup than letting our end users see a jumpy layout when the big illustration eventually pops up. That isn't good UX. It would be so nice if you added them back, but I fully understand your concern and motive. I will try to convince our designer to sacrifice this big illustration to get a slightly faster app startup.

> @Dohmanlechx Maybe this would work.
> 
> ```dart
> const loader = SvgAssetLoader('res/large_icon.svg');
> svg.cache.putIfAbsent(loader.cacheKey(null), () => loader.loadBytes(null));
> ```

Worked like a charm! I really can't feel any difference in the app startup either. Thank you!
@dnfield Feel free to close this issue anytime, but I believe this code example would help a lot of people.

---
Comment by @levi956 on Feb 6, 2023
> 1. Are your icons still delayed in release/profile mode? See [I am seeing a significant performance regression on 2.0.0 #837](https://github.com/dnfield/flutter_svg/issues/837) - in debug mode things are slower right now.
> 2. I can add something about precaching. The problem ends up being that people precache at "bad" times like startup, which delays the whole app startup. It shouldn't be quite as bad with the new version because of the isolates, but it's still not great.
> 
> The code that @hygehyge provided should work as well.

The color parameter seems to be deprecated, Please what's the replacement for color SVGs?

---
Comment by @levi956 on Feb 6, 2023
> @Dohmanlechx Maybe this would work.
> 
> ```dart
> const loader = SvgAssetLoader('res/large_icon.svg');
> svg.cache.putIfAbsent(loader.cacheKey(null), () => loader.loadBytes(null));
> ```

This seems like a single asset file, is it possible to add an asset path for the whole svg path and place it in void main startup?

---
Comment by @swiftymf on Feb 6, 2023
> The color parameter seems to be deprecated, Please what's the replacement for color SVGs?

I switched to using `colorFilter` by passing in my previous colors into a ColorFilter like this: 
`colorFilter: ColorFilter.mode(_color, BlendMode.srcIn),`

Looks like that is basically the default when you don't pass into anything for `colorFilter` and it's working for me.

---
Comment by @swiftymf on Feb 6, 2023
> 1. Are your icons still delayed in release/profile mode? See [I am seeing a significant performance regression on 2.0.0 #837](https://github.com/dnfield/flutter_svg/issues/837) - in debug mode things are slower right now.

This was exactly my case. I was running debug builds and it was slow. Once I found this I tried a release build and it's looking good. 👍



---
Comment by @simplenotezy on Feb 22, 2023
@hygehyge is there a reason you don't include the context, and instead pass null?

---
Comment by @hygehyge on Feb 22, 2023
@levi956 
You can iterate asset names like this.
```dart
final manifestJson = await rootBundle.loadString('AssetManifest.json')
final images = json.decode(manifestJson).keys.where((String key) => key.startsWith('assets/images'));
```

@simplenotezy 
I use that code to load a large icon for startup screen, on entry point(`void main()`).
So there is no `BuildContext` yet.

---
Comment by @sikandernoori on Mar 15, 2023
Based on @hygehyge example I have implemented below in main before running app.

```
      final manifestJson = await rootBundle.loadString('AssetManifest.json');
      List svgsPaths = (json.decode(manifestJson).keys.where((String key) => key.startsWith('assets/images/') && key.endsWith('.svg')) as Iterable).toList();

      for(var svgPath in svgsPaths as List<String>) {
        var loader = SvgAssetLoader(svgPath);
        await svg.cache.putIfAbsent(loader.cacheKey(null), () => loader.loadBytes(null));
      }
```

and this is how I am getting svg instance.

```
  static SvgPicture get getSomeImage => SvgPicture.asset(
        "assets/images/some_image.svg",
        height: 40,
        width: 40,
        color: Colors.white,
      );
      ```

---
Comment by @olegyablokov on Apr 12, 2023
What if I use ".svg.vec" files as described in "Precompiling and Optimizing SVGs" section in README in flutter_svg? Should I cache these files and if yes then how?

---
Comment by @dnfield on Apr 12, 2023
You should not need to cache the .vec files.

---
Comment by @keithhie on Apr 17, 2023
```
      final manifestJson = await rootBundle.loadString('AssetManifest.json');
      List svgsPaths = (json.decode(manifestJson).keys.where((String key) => key.startsWith('assets/images/') && key.endsWith('.svg')) as Iterable).toList();

      for(var svgPath in svgsPaths as List<String>) {
        var loader = SvgAssetLoader(svgPath);
        await svg.cache.putIfAbsent(loader.cacheKey(null), () => loader.loadBytes(null));
      }
```
This code snippet provided by @sikandernoori used to work for me, but all of a sudden, I'm facing this issue below:

```
Unhandled Exception: 'package:vector_graphics_codec/vector_graphics_codec.dart': Failed assertion: line 771 pos 12: 'format == 0': is not true.
#0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)
#1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
#2      VectorGraphicsCodec.writeImage (package:vector_graphics_codec/vector_graphics_codec.dart:771:12)
#3      _encodeInstructions (package:vector_graphics_compiler/vector_graphics_compiler.dart:171:11)
#4      encodeSvg (package:vector_graphics_compiler/vector_graphics_compiler.dart:142:10)
#5      SvgLoader._load.<anonymous closure>.<anonymous closure> (package:flutter_svg/src/loaders.dart:137:14)
#6      _testCompute (package:flutter_svg/src/utilities/compute.dart:12:38)
#7      SvgLoader._load.<anonymous closure> (package:flutter_svg/src/loaders.dart:135:21)
```

---
Comment by @felipecastrosales on Aug 23, 2023
Hi, any expectation about this? 

---
Comment by @feinstein on Sep 6, 2023
FYI: I see my bottom navigator SVGs "blinking" when the main screen opens, the same behavior we see with asset images. My bet is not on this library's performance, but on the time that takes from assets to be retrieved from storage.

I am on Flutter 3.10.7 and I can't see this on iOS, only on Android.

---
Comment by @felipecastrosales on Sep 6, 2023
@feinstein Yesterday I also noticed this in my app, precisely in my bottom navigation - like you. In fact, in a part of my app I decided to migrate the assets to png and perform a precacheImage and the difference in performance was absurd - much better.

---
Comment by @feinstein on Sep 6, 2023
There are other ways of solving this:

1 - Precache SVGs as described here.

2 - Create a dart file where each of your SVGs are a String. Since they will be part of your code, they don't need to be loaded from storage.

3 - Transform your SVGs into a font and use them as Icons (that's they way Flutter Icons work).

---
Comment by @DanMossa on Dec 6, 2023
> You should not need to cache the .vec files.

@dnfield 
I'm using the compiled `.vec` images and still experience a delay before the image renders

```dart
SvgPicture(AssetBytesLoader("assets/logo_lights_large.svg.vec"), height: 50),
```


---
Comment by @eshfield on Dec 13, 2023
> Based on @hygehyge example I have implemented below in main before running app

I have found a way to do the same without `AssetManifest.json` file:

```
Future<void> precacheSvgImages() async {
  final assetManifest = await AssetManifest.loadFromAssetBundle(rootBundle);
  final assets = assetManifest.listAssets();

  // the same code below
  final svgPaths = assets.where((path) => path.endsWith('.svg'));
  for (final svgPath in svgPaths) {
    final loader = SvgAssetLoader(svgPath);
    await svg.cache
        .putIfAbsent(loader.cacheKey(null), () => loader.loadBytes(null));
  }
}
```

This function has to be called inside of `initState()` method of `MainApp` for example—it will not work in the `main()` before `runApp` started.

---
Comment by @cedvdb on Feb 3, 2024
> There are other ways of solving this:
> 
> 1 - Precache SVGs as described here.
> 
> 2 - Create a dart file where each of your SVGs are a String. Since they will be part of your code, they don't need to be loaded from storage.
> 
> 3 - Transform your SVGs into a font and use them as Icons (that's they way Flutter Icons work).


For 3. I don't think fonts can have multiple colors can they ?

For 2. That behavior is different for the web for multiple reasons

---
Comment by @feinstein on Feb 4, 2024
Never tested it on the Web, could you elaborate more on why it doesn't work in the web? 

---
Comment by @cedvdb on Feb 4, 2024
assets are dwnloaded separately. Http2 parallelism and browser caching are some of the things you give up on the web by putting the svg inside your dart code.

---
Comment by @feinstein on Feb 4, 2024
Good point, but unless you have lots of SVGs, or huge ones, this shouldn't be a problem in today's internet speeds, since SVGs are tiny.