How to modularize an internal flutter app

Satyajit Malugu
4 min readOct 1, 2021

--

One app strategy
Unless you work for behemoths like Apple, Google or Microsoft your company has only one app in the app stores. This means that even though you have multiple teams and organizations with varying backends, deployment styles and skills, they all are forced to have one common code base for their mobile applications.

One app to rule them all

Autonomy

One of the core tenets of modern software development practices in product based companies is autonomy: i.e ownership of code and process. Each team owns their code, how it is deployed/tested etc. Over the last few years backend teams have gone extreme lengths on this principle by having small microservices that can easily be versioned, deployed, tested and owned by small teams. It has become the norm for modern development practices across different stacks Java, Node but for mobile developers this isn’t hasn’t picked up.

Modularization is an attempt to bridge these contrasting principles

Modularization of mobile apps is an attempt to bridge these two contrasting principles and give back the feature teams some ownership. Each feature or an organization has their own component/module/package and they can independently run in that package without impacting others.

Note: This doesn’t mean that modules can be deployed independently to app stores and there isn’t a need for a central team to work through common issues such as upgrades, app size, crashes etc . A central team is still essential but each feature team can play freely in their own sandbox.

In this article, focus is on modularizing a flutter app, the same for iOS and Android is covered elsewhere

Dart library packages

To share code independently dart recommends using packages: https://dart.dev/guides/libraries/create-library-packages. Each package will have its own package.yaml and code in lib and test folders.

I also recommend having a sub build files such as build-feature-module.yaml which is referenced from the main .gitlab-ci.yaml file, so that you can independently determine what build steps are required for passing your coding standards.

Monorepos

One way to create these modules/packages is to have each hosted in their own git repo. Each module is then brought into the main app as either submodules or hosted in an internal pub hosting service. But this approach might be too heavy handed for smaller mobile apps and hard to collaborate, re-use code and establish company wide UI theming. To address these issues you can employ monorepos i.e a huge repo which consists of all the sub-packages under one file structure. While monorepos seem like an anti-pattern, for smaller to medium sized file structures they can ease management of file structures and deployment scripts. Also, it is intuitive that a mobile app has one deliverable. Hence keeping all of these packages together makes sense.

Parent repo references the sub packages

Melos

But monorepos present a challenge for managing versions, creating build scripts and running tests across all the packages. Enter melos, a dart package management syste, that is used by high profile projects like flutterfire, amplify to manage their publicly available packages. While it is geared towards public facing packages, it can be modified to be used for private packages as well. One great thing about this setup is that the root project itself can be a package while also being the parent composing all the packages.

All modules under /packages folder and melos tying them together

Pre-requisite for successful modularization.

Existing app should be in a state already composed of modules for core functions such as networking, storage, UITheming, routes etc. Otherwise we could run into circular dependencies from the parent to child and child to parent packages, which isn’t good for long term.

Usually this is a huge lift, so I would recommend you start on this path before the code base becomes bigger and deeply coupled.

You can seen all the code that is used to demonstrate this concept here: https://github.com/prolificcoder/modularized_flutter_app

Let me know your thoughts on this approach and if there are other strategies you have followed.

Also, if you have a hybrid flutter app and include a flutter package into your existing Android and iOS apps, stay tuned for the next post.

--

--