Detecting Unused Assets
While DCM provides various commands for detecting unused entities in your codebase (unused code, unused files, unused dependencies, etc.), there is no dedicated command to find unused assets.
But is it still possible to reliably find unused assets with DCM? The answer is "Yes!".
In this guide we will explore how DCM can help you with detecting unused assets.
Why No Dedicated Command?
The problem with detecting unused assets with static analysis is in how they can be referenced in code:
Image.asset('assets/images/profile.jpg'); // Full path, can be analyzed
Image.asset('assets/${variable}/profile.jpg'); // Composed path, analysis results will be error-prone
Image.asset(variable); // Uses a variable, cannot be statically analyzed
And while the first example is easy to analyze, when the path is a variable (which can also get its value from the backend), the analysis results quickly become full of false positives and therefore unreliable.
There is one case where detecting unused assets has no false positives: when it comes to resolution-aware images. If your project has a 2x image but no regular image, the former is definitely unused.
To quickly find such images (and other issues related to image assets), use the analyze-assets
command.
To get reliable output for unused assets, there needs to be a Dart class that references all assets (as fields or getters). Then, the fields or getters that are not directly referenced in your code are the ones that point to unused assets. For example,
abstract final class Assets {
static const profile = 'assets/images/profile.jpg';
// Not referenced and therefore unused
static const background = 'assets/images/background.jpg';
}
Image.asset(Assets.profile);
The only problem: going through all the fields manually is tedious work.
But since such fields are Dart code, this is exactly where the check-unused-code
command becomes handy!
Detecting Unused Assets with "check-unused-code"
Creating a Dart wrapper class by hand doesn't seem like a fun task, and it's also reduces maintainability, since an application can contain hundreds of image assets, and managing paths manually increases the chance of a mistake.
Luckily, Dart supports code generation, and there are at least two packages that can help you with that: flutter_gen
and spider
.
Using "flutter_gen" Package
flutter_gen is a code generator package for assets, fonts and colors that helps you get rid of string-based APIs and use Dart classes instead.
FlutterGen offers multiple ways to install the package. In this guide, we'll use the Pub Global
option (and for other examples, refer to their installation guide):
dart pub global activate flutter_gen
Once installed, run fluttergen
in your package root to generate the assets.gen.dart
file.
FlutterGen generates dart files based on the key flutter
and flutter_gen
of pubspec.yaml
and supports flexible configuration, which you can find here.
Here is an example of the generated Dart wrapper class:
class $AssetsIconsGen {
const $AssetsIconsGen();
/// File path: assets/icons/toastWarning.png
AssetGenImage get toastWarning =>
const AssetGenImage('assets/icons/toastWarning.png');
/// File path: assets/icons/close-button-icon-light.svg
SvgGenImage get closeButton =>
const SvgGenImage('assets/icons/close-button-icon-light.svg');
}
class Assets {
Assets._();
static const $AssetsIconsGen icons = $AssetsIconsGen();
}
And here is how it can be used in your code:
// Implicit usage
Widget build(BuildContext context) {
return Assets.icons.closeButton.svg(
width: 120,
height: 120,
);
}
// Explicit usage
Widget build(BuildContext context) {
return SvgPicture.asset(
Assets.icons.closeButton.path,
package: Assets.package,
width: 120,
height: 120,
);
}
Detecting Unused Assets For "flutter_gen"
Now, to detect unused assets, run dcm check-unused-code lib
in your project.
If you are running this command on a particular folder, make sure that assets.gen.dart
is also included into the analysis (by default, it's located under lib/gen
).
For example, dcm check-unused-code lib/some/folder lib/gen
.
For the example above, the command produces the following output:
lib/gen/assets.gen.dart:
⚠ unused getter toastWarning
at lib/gen/assets.gen.dart:5:21
❌ total unused code (top-level declarations and class members) - 1
Which shows that toastWarning
is indeed not referenced anywhere in the code, and therefore assets/icons/toastWarning.png
is unused and can be simply removed.
Using "spider" Package
Spider is another library for generating Dart classes for assets which can be used to reference the assets safely anywhere in the flutter app.
Spider offers multiple installation options. In this guide, we'll use pub (and for other examples, refer to their installation guide):
dart pub global activate spider
Once installed, create the configuration via spider create
and use spider build
to generate the wrapper class.
Here is an example of the generated Dart wrapper class:
class Images {
Images._();
static const String carousel1 = 'assets/images/carousel-1.png';
static const String carousel2 = 'assets/images/carousel-2.png';
}
And here is how it can be used in your code:
Widget build(BuildContext context) {
return Image(image: AssetImage(Images.carousel1));
}
Detecting Unused Assets For "spider"
Now, to detect unused assets, run dcm check-unused-code lib
in your project.
If you are running this command on a particular folder, make sure that generated file is also included into the analysis (by default, it's located under lib/resources
).
For example, dcm check-unused-code lib/some/folder lib/resources
.
For the example above, the command produces the following output:
lib/resources/images.dart:
⚠ unused getter carousel2
at lib/resources/images.dart:5:23
❌ total unused code (top-level declarations and class members) - 1
Which shows that carousel2
is indeed not referenced anywhere in the code, and therefore assets/images/carousel-2.png
is unused and can be simply removed.
CI/CD
Regardless of what package you use, detecting unused assets with check-unused-code
on CI/CD is similar to running any other DCM command on CI/CD.
Check out our guides for GitHub, BitBucker, GitLab or Azure.