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.
Finished up all this today. Working great!
We're able to use fast-image across our app on iOS and Android.
This allows us to remove a shitload of code that determined what version of iOS, what file type, what type of animation.... blah, blah, blah... then do something different.
Now we just use webp and animated webp with fast-image regardless of operating system. This is great.