Breaking Down the House - I mean Flutter Projects

Flutter makes it easy to create code that can be deployed on web, mobile, or PC-type native applications.  The Flutter templates are the perfect starting place in a greenfield scenario where you don't intend to embed Flutter in another application.  The default templates don't work as well when you want to drop your Flutter code into existing applications written with other tools while at the same time supporting standalone development apps or test jigs.

Here is my opinionated view on organizing code if you are building a simple application that works across channels and that may be embedded in existing applications on some platforms.


The Various Flutter Directories

Flutter maintains or creates various directories based on your target environments. Flutter supports having multiple target environments in the same project.  It has an opinionated file structure that prescribes where platform-specific / non-flutter pieces go.
  • Core Code
    • /lib: Flutter Code
    • /test: Tests for Flutter Code
  • Web: 
    • /web: Where a standalone web app goes or one embedded with iFrames or as elements. This is HTML plus javascript. Portions are persisted into version control.
  • Standalone Native - Portions are persisted into version control.
    • /android: A standalone Android application (wrapper) for new development or as a test jig for other code. Java or Kotlin code that is editable in Android Studio or other Android tools.
    • /ios: A standalone iOS application (wrapper) for new development or as a test jig for other code. Swift or Objective-C code that is editable in XCode.
    • /macos: Standalone Mac application. I've never used this and it isn't shown. 
    • /windows: Standalone Windows application. I've never used this and it isn't shown. 
    • /linux: Standalone Linux application.  I've never used this and it isn't shown.
  • Embedded Native - Created at build time and never persisted to version control.
    • /.android: Android support pieces when you are building a module that can be run inside an existing Android application.  
    • /.ios: iOS support pieces when you are building a module that can be run inside an existing iOS application.  
Mobile Native standalone applications and modules targeting being embedded cannot exist in the same project. This means you can't have a full Android app and Android module destined for an AAR in the same project.  No /.android and /android.  You can try it but it doesn't end well.

This picture shows 5 different target environments.  It is an invalid configuration that we will rework in the next section.

Standalone programs, test jigs, and legacy embedding

We're going to take that simple single project and break it apart so that we can get the two different deployment models: standalone applications and Flutter embedded in existing mobile native applications.  We will have one project that holds almost all the Flutter code, one for standalone applications using that code, and one that lets us package Flutter into modules for inclusion in existing applications

Split the code along functional lines. 
  1. package project that is the Flutter code library for use on various platforms.   This represents all the business functionality and common application scaffolding for the Flutter pieces. It can contain platform-specific code that can be switched out based on the target environment, Android, iOS, and web.  Common code across module and application deployments goes in one of these packages. Flutter scaffolding, MaterialApp, Themes, and other pieces can go here possibly including any startup code that is common across several targets

  2. An application project usually either a production app or an application can be used by developers as a test jig. Application projects are standalone applications or wrappers for the package/library project.  Applications include the main application, scaffolding, and other pieces required for standalone applications.

    You might have a standalone deployable web app and Mobile native test jigs in the same application. You can do this because the Android, iOS and, web directories represent a platform and it is up to you how to use the created applications.  You could break this into separate application projects but there is often no need for that. Module projects have dependencies that hold the real application functionality.

  3. A module project that describes an archive/component will be embedded in existing native applications. It holds all the module configurations for the various mobile native platforms.  This is a module wrapper for the package project.

    You can define a module for Android and iOS and build both out of the same project.  Module projects have dependencies that point to the packages containing real application functionality.

Relative Package dependencies

All of these projects are in the same repository. The applications and modules can all refer to the packages via relative references. This has the side effect of supporting hot reload in the apps when package changes are made.  There is no need to publish the packages and then pull them back down again to build the modules or applications.


Revision History

Created 2024 05


Popular posts from this blog

Understanding your WSL2 RAM and swap - Changing the default 50%-25%

Installing the RNDIS driver on Windows 11 to use USB Raspberry Pi as network attached

DNS for Azure Point to Site (P2S) VPN - getting the internal IPs