If anybody needs animated webP support with Expo (Custom Dev Client) for the native <Image />
and <FastImage />
(read comments):
// create a file like plugins/withAnimatedWebPSupport.js -> this is for the native <Image />
const {
createRunOncePlugin,
withGradleProperties
} = require('@expo/config-plugins');
const withAnimatedWebPSupport = (config) => {
const propertyToModify = {
type: 'property',
key: 'expo.webp.animated',
value: true,
};
return withGradleProperties(config, (config) => {
config.modResults = config.modResults.filter(
(item) => !(item.type === propertyToModify.type && item.key === propertyToModify.key)
);
config.modResults.push(propertyToModify);
return config;
});
};
module.exports = createRunOncePlugin(withAnimatedWebPSupport, 'animated-webp-support', '1.0.0');
// create a plugins/withFastImageWebPSupportAndroid.js - This is for `<FastImage />` Support
// note that this will need withAnimatedWebPSupport, because I've replaced it in that if-condition. Feel free to customize if you only want webP with FastImage
const {
withAppBuildGradle,
} = require("@expo/config-plugins");
const withCustomAppBuildGradle = (config) => {
const insertString = `implementation "com.github.zjupure:webpdecoder:2.0.4.12.0"`;
return withAppBuildGradle(config, (config) => {
if (
config.modResults.contents.includes(
insertString
)
) {
return config;
}
config.modResults.contents = config.modResults.contents.replace(
`if (isWebpAnimatedEnabled) {`,
`if (isWebpAnimatedEnabled) {
${insertString}`
);
return config;
});
};
module.exports = function withFastImageWebPSupportAndroid(config) {
config = withCustomAppBuildGradle(config);
return config;
};
// create a plugins/withFastImageWebPSupportIOS.js
const {
WarningAggregator,
withAppDelegate,
createRunOncePlugin
} = require('@expo/config-plugins');
const RNFI_EXPO_WEBP_IMPORT = `#import "AppDelegate.h"
// expo-config-plugin fast-image webp animated support
#import "SDImageCodersManager.h"
#import <SDWebImageWebPCoder/SDImageWebPCoder.h>
// end config plugin
`
const RNFI_EXPO_WEBP_DID_FINISH_LAUNCHING_IDENTIFIER = `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{`
const RNFI_EXPO_WEBP_DID_FINISH_LAUNCHING_CODE = `
// start expo-config-plugin fast-image webp animated support
[SDImageCodersManager.sharedManager addCoder: SDImageWebPCoder.sharedCoder];
// end expo-config-plugin fast-image webp animated support
`
function modifyAppDelegate(appDelegate) {
if (!appDelegate.includes(RNFI_EXPO_WEBP_IMPORT)) {
appDelegate = appDelegate.replace(
/#import "AppDelegate.h"/g,
RNFI_EXPO_WEBP_IMPORT,
);
}
if (appDelegate.includes(RNFI_EXPO_WEBP_DID_FINISH_LAUNCHING_IDENTIFIER)) {
if (!appDelegate.includes(RNFI_EXPO_WEBP_DID_FINISH_LAUNCHING_CODE)) {
const block = RNFI_EXPO_WEBP_DID_FINISH_LAUNCHING_IDENTIFIER + RNFI_EXPO_WEBP_DID_FINISH_LAUNCHING_CODE
appDelegate = appDelegate.replace(RNFI_EXPO_WEBP_DID_FINISH_LAUNCHING_IDENTIFIER, block)
} else {
WarningAggregator.addWarningIOS('withFastImageWebPSupportIOSAppDelegate', `FastImage webP support already setup in AppDelegate`)
}
} else {
throw new Error('Failed to detect didFinishLaunchingWithOptions in AppDelegate')
}
return appDelegate
}
const withFastImageWebPSupportIOS = (config) => {
return withAppDelegate(config, (config) => {
if (['objc', 'objcpp'].includes(config.modResults.language)) {
config.modResults.contents = modifyAppDelegate(config.modResults.contents)
} else {
WarningAggregator.addWarningIOS('withFastImageWebPSupportIOSAppDelegate', `Cannot setup FastImage webP support, the project AppDelegate is not a supported language: ${config.modResults.language}`)
}
return config
})
}
module.exports = createRunOncePlugin(withFastImageWebPSupportIOS, 'rnfi-expo-animated-webp-support', '1.0.0');
Install plugin in your app.json / app.config.js (expo.plugins)
['./plugins/withAnimatedWebPSupport'],
['./plugins/withFastImageWebPSupportIOS.js'],
['./plugins/withFastImageWebPSupportAndroid.js'],
Based on other config plugins by @GollyJer, @wodin, @barthap, @EvanBacon and @nandorojo Thanks guys!
In case you only need native <Image />
support, just install this package:
https://github.com/Aleksefo/react-native-webp-format
and only use the withAnimatedWebPSupport Plugin for Android.
Be careful: the iOS plugin is using a dangerous mod to modify appDelegate.m. Android is using a dangerous mod
withAppBuildGradle
. You might need to triggerexpo prebuild --clean
or adjust the code if the search and replace strings have changed.Would be lovely if someone could make a AppDelegate Subscriber Edition out of it.
https://docs.expo.dev/modules/appdelegate-subscribers/