Skip to content

Performance Flutter Web Build Lags on Mobile Devices While Android and iOS Builds Perform Smoothly #194196

Open

Description

@Jydp07

Steps to reproduce

I am experiencing a performance issue in Flutter Web when displaying a GridView or ListView containing network images using the cached_network_image package, along with product details such as title and price.

The same UI works smoothly on Android and iOS, but on Flutter Web, scrolling and rendering feel noticeably slower and less responsive.

This is our web link you can check here
https://testnetlarx.qunoindia.com/

Steps to Reproduce

Create a Flutter screen containing a GridView.builder or ListView.builder.

Display network images using CachedNetworkImage.

Show additional data alongside each image, such as product title, price, and other details.

Populate the list with multiple items.

Run the same screen on Android, iOS, and Flutter Web.

Compare scrolling smoothness, image loading, and UI responsiveness.

Expected Behavior

Smooth scrolling and responsive UI on Flutter Web, comparable to Android and iOS.

Network images should load and display without noticeable UI lag.

Cached images should help reduce unnecessary network requests and improve the experience when revisiting the screen.

Actual Behavior

The UI feels laggy on Flutter Web when scrolling through the list or grid.

Image loading and rendering appear less smooth than on Android and iOS.

The same implementation performs well on mobile platforms.

  • Environment

  • Framework: Flutter

  • Platforms affected: Flutter Web

  • Platforms tested: Android and iOS

  • Widget: GridView / ListView

  • Image package: cached_network_image

  • Flutter version: 3.44.5

  • Browser: Chrome

Additional Information

This issue occurs with a relatively simple product listing UI containing network images and text data. I would like to understand whether this behavior is related to Flutter Web's image decoding, rendering pipeline, caching implementation, or widget rebuilding.

Could you please investigate whether there are any recommended optimizations or known limitations for this use case on Flutter Web?

A minimal reproducible example can be provided if needed.

Code sample

Minimal Reproducible Example

pubspec.yaml dependency:

dependencies:
  flutter:
    sdk: flutter
  cached_network_image: ^3.4.1

main.dart

import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const ProductGridScreen(),
    );
  }
}

class ProductGridScreen extends StatelessWidget {
  const ProductGridScreen({super.key});

  final List<Map<String, dynamic>> products = const [
    {
      'title': 'Product 1',
      'price': 499,
      'image': 'https://picsum.photos/id/10/600/600',
    },
    {
      'title': 'Product 2',
      'price': 799,
      'image': 'https://picsum.photos/id/20/600/600',
    },
    {
      'title': 'Product 3',
      'price': 999,
      'image': 'https://picsum.photos/id/30/600/600',
    },
    {
      'title': 'Product 4',
      'price': 1299,
      'image': 'https://picsum.photos/id/40/600/600',
    },
    {
      'title': 'Product 5',
      'price': 599,
      'image': 'https://picsum.photos/id/50/600/600',
    },
    {
      'title': 'Product 6',
      'price': 899,
      'image': 'https://picsum.photos/id/60/600/600',
    },
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Product Grid')),
      body: GridView.builder(
        padding: const EdgeInsets.all(12),
        itemCount: 1000,
        gridDelegate:
            const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          crossAxisSpacing: 12,
          mainAxisSpacing: 12,
          childAspectRatio: 0.65,
        ),
        itemBuilder: (context, index) {
          final product = products[index % products.length];

          return Card(
            clipBehavior: Clip.antiAlias,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Expanded(
                  child: SizedBox(
                    width: double.infinity,
                    child: CachedNetworkImage(
                      imageUrl: product['image'] as String,
                      fit: BoxFit.cover,
                      placeholder: (context, url) =>
                          const Center(
                        child: CircularProgressIndicator(),
                      ),
                      errorWidget: (context, url, error) =>
                          const Icon(Icons.error),
                    ),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8),
                  child: Column(
                    crossAxisAlignment:
                        CrossAxisAlignment.start,
                    children: [
                      Text(
                        product['title'] as String,
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                      const SizedBox(height: 4),
                      Text(
                        '₹${product['price']}',
                        style: const TextStyle(
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

How to test

Run the same example on each platform:

flutter run -d chrome --profile

Run on your Android or iOS device in profile mode as well, and compare scrolling performance. The example uses 1,000 grid items to make scrolling behavior easier to observe.

Reply to the GitHub maintainer

I've added a minimal reproducible example using GridView.builder and CachedNetworkImage, displaying product images, titles, and prices.

The same type of UI feels smooth on Android and iOS, but on Flutter Web, scrolling and rendering feel noticeably laggy.

Could you please check whether this behavior is expected on Flutter Web or if there are any known limitations or recommended optimizations for this use case?

What target platforms are you seeing this bug on?

Web

OS/Browser name and version | Device information

Platform:
Android, iOS

Browser:
Chrome

Does the problem occur on emulator/simulator as well as on physical devices?

Unknown

Logs

Logs
[Paste your logs here]

Flutter Doctor output

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.44.5, on macOS 26.4.1 25E253 darwin-arm64 (Rosetta), locale en-IN)
[!] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 26.4.1)
[✓] Chrome - develop for the web
[✓] Connected device (3 available)
! Error: Browsing on the local area network for iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local
area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources

! Doctor found issues in 1 category.

Activity

  1. saurabh-mirajkar commented on Oct 12, 2026

    @saurabh-mirajkar
    Contributor

    @Jydp07 Thanks for the report. Could you please verify the issue using latest stable Flutter 3.47.7 and the latest version of cached_network_image? If it does reproduce, share clear, step-by-step reproduction instructions, a complete log (if any) and a video recording demonstrating the issue.

  2. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    needs repro infoAutomated crash report whose cause isn't yet known
    and removed
    in triagePresently being triaged by the triage team
    on Oct 12, 2026
  3. saurabh-keskar commented on Oct 12, 2026

    @saurabh-keskar

    This is likely due to image decoding on the web's single main thread rather than the download itself. On Android and iOS, decoding happens on background threads, but on web (CanvasKit) it competes with scrolling. A few things that should help:

    1. Decode at display size: set memCacheWidth/memCacheHeight on CachedNetworkImage (or cacheWidth on Image.network). The sample decodes 600×600 images into small tiles.
    2. Serve thumbnail-sized or WebP images for grid views.
    3. Replace the per-tile CircularProgressIndicator with a static placeholder. Dozens of animated spinners repaint every frame.
    4. Try flutter build web --wasm (skwasm), which can decode off the main thread when COOP/COEP headers are set.
    5. Note that cached_network_image has no disk cache on web and relies on the browser HTTP cache.

    Precaching (precacheImage) can smooth out the first screen, but it still decodes on the main thread, so it moves the cost rather than removing it.

  4. Jydp07 commented on Oct 13, 2026

    @Jydp07
    Author

    @saurabh-keskar We already serve webp images and already set this memCacheWidth/memCacheHeight on CachedNetworkImage also there is no CircularProgressIndicator which can cause this problem

    flutter build web --wasm I will try with this and update you

  5. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Oct 13, 2026
  6. saurabh-mirajkar commented on Oct 13, 2026

    @saurabh-mirajkar
    Contributor

    @Jydp07 Thanks for the report. Could you please verify the issue using latest stable Flutter 3.47.7 and the latest version of cached_network_image? If it does reproduce, share clear, step-by-step reproduction instructions, a complete log (if any) and a video recording demonstrating the issue.

    kindly verify and update as requested above, until then keeping this aswaiting for response

  7. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Oct 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    from: performance templateIssues created via a performance issue templateneeds repro infoAutomated crash report whose cause isn't yet knownwaiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions