Slide 1

Slide 1 text

Build customization Flutter Montreal Meetup - January 2024

Slide 2

Slide 2 text

Nicolas Cuillery Software developer Has worked with: - Flutter - React Native - React - Angular.js - Flex - jQuery - JSP

Slide 3

Slide 3 text

BASE1 eCommerce Services Web and Mobile storefront

Slide 4

Slide 4 text

Cloud9

Slide 5

Slide 5 text

Cloud9 application - Project started in February 2021 - Android and iOS - Single codebase, multiple apps - Currently in production in 10 countries - 1M daily users

Slide 6

Slide 6 text

Multiple markets - Phase 1: Japan and Australia - Phase 2: Mexico, UK and New Zealand - Phase 3: Korea and Taiwan - Quarterly releases: France, Spain, Sweden, Iceland

Slide 7

Slide 7 text

Firebase Analytics In-app Messaging Cloud Messaging Firestore Crashlytics Remote Config Dynamic Links Performance

Slide 8

Slide 8 text

Firebase usage

Slide 9

Slide 9 text

Multiple applications com.cloud9.uat com.cloud9.qa com.cloud9.preprod com.cloud9.japan com.cloud9.uk com.cloud9.mexico com.cloud9.australia Cloud9 code base cloud9-prod-australia cloud9-prod-mexico cloud9-prod-japan cloud9-prod-uk etc… cloud9-dev-shared cloud9-dev-uat cloud9-dev-qa cloud9-dev-preprod

Slide 10

Slide 10 text

Multiple flavors/configurations Different builds from the same project. Examples: - Pricing model - White-label app - Beta version - etc.

Slide 11

Slide 11 text

Non-prod applications Country selector screen on startup - Ease dev and QA workflow - Faster CI build = faster feedback loop - Cheaper CI

Slide 12

Slide 12 text

New market launch

Slide 13

Slide 13 text

New requirements - Different dependencies for China - Alternatives for the Firebase products: - Remote Config - Cloud Messaging - Analytics - …

Slide 14

Slide 14 text

Nice-to-have goals - The unused deps are not compiled nor packaged in the app. - no Firebase deps in the app for China - no WeChat Pay in the UK build - Dev and tester experience preserved - “China” available in the country selector - Minimal impact in the dev workflow

Slide 15

Slide 15 text

Arsenal: Layered Architecture 🚀 Separation between: - Data - Business Logic - UI More about that on: https://www.reddit.com/r/FlutterDev/comments/192h8l0/comment/kh3sm2w/

Slide 16

Slide 16 text

Arsenal: Dependency injection Heavy usage of GetIt https://pub.dev/packages/get_it

Slide 17

Slide 17 text

Arsenal: Dependency injection Usage of “interface” (barely used)

Slide 18

Slide 18 text

Arsenal: Import tree-shaking Successive imports are read from the entry-point: main.dart

Slide 19

Slide 19 text

- Centralize all the Firebase usage in one place (per Firebase Product) - Abstraction layer between the Firebase SDK and its usages - Specific main file for China, loading the non-Firebase implementation Draft of a solution

Slide 20

Slide 20 text

Pre-china implementation main.dart

Slide 21

Slide 21 text

initialization_helper.dart

Slide 22

Slide 22 text

address_search_bloc.dart

Slide 23

Slide 23 text

Step 1: Preparation initialization_helper.dart

Slide 24

Slide 24 text

address_search_bloc.dart

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

Step 2: Specific main file main_china.dart

Slide 27

Slide 27 text

china_initialization_helper.dart

Slide 28

Slide 28 text

Less compiled code https://stackoverflow.com/questions/52822353/how-to-test-debug-tree-shaking-in-flutter Customers want guidance and docs for tree-shaking: https://github.com/dart-lang/sdk/issues/33920

Slide 29

Slide 29 text

Dev and tester experience preserved Previously (non-prod) Entry point initGlobalSingletons() {} InitializationHelper main() {} in main.dart Country Selector initCountrySingletons() {} Home Page InitializationHelper Splash screen setCountry() {} SettingsService

Slide 30

Slide 30 text

Now (non-prod) Entry point initGlobalSingletons() {} InitializationHelperImpl main() {} in main.dart Country Selector initCountrySingletons() {} Home Page InitializationHelper Splash screen setCountry() {} SettingsService initCountrySingletons() {} initCountrySingletons() {} InitializationHelperChinaImpl InitializationHelperProdImpl

Slide 31

Slide 31 text

Strip Flutter plugins - Native changes abstracted by Flutter - Manual changes in the native files kept as minimal as possible - pubspec.yaml is the main source of truth Non-prod Include all plugins (Firebase + the alternatives) China Strip the Firebase plugins Other countries Strip the chinese dependencies

Slide 32

Slide 32 text

Flutter plugins - iOS: Integration with cocoapods - Android: Hook in the app/build.gradle

Slide 33

Slide 33 text

CI script https://github.com/mikefarah/yq

Slide 34

Slide 34 text

Possible improvement #1

Slide 35

Slide 35 text

Possible improvement #2 From Flutter itself: https://github.com/flutter/flutter/issues/46979

Slide 36

Slide 36 text

Native changes Less hack-y because we are in the native world Access to the flavor/configuration 🎉

Slide 37

Slide 37 text

Size comparison

Slide 38

Slide 38 text

Takeaways - Architecture is key - Unknown path to scalability - OOP still works

Slide 39

Slide 39 text

Thanks! Kudos to Jhin, Billy and Ali❤