Managing multi-package Flutter projects with Melos

Sagar Suri
Flutter Community
Published in
7 min readJun 5, 2021

Most of the time when you create a Flutter project. You work with a single package. The project consists of a single pubspec.yaml , lib folder. You put all your features and utilities in the same package. But there are projects which break their features and utilities into multiple packages. This helps in better separation of concerns and allows the team to open-source some of their packages. Here is a diagram of how a multi-package project will look like:

Here we have divided the project into three layers. The first layer is the root project which will hold common configurations that applies to all the different packages in the project. The 2nd layer is having independent feature packages that do not depend on each other. The 3rd layer consists of utility packages that are used in multiple feature packages. I won’t dive deep into how to create or structure a multi-package flutter project. This article will focus on solving a particular challenge that is typically faced in a multi-package flutter project.

The Challenge

In a single package flutter project running the following tasks is dead simple:

  1. flutter pub get
  2. flutter test
  3. flutter analyze
  4. Generating code coverage i.e flutter test --coverage

But running the same tasks in a multi-package flutter project can be challenging because you need to run those tasks in every package inside your project and give a summarised result at the end of completion of the task. Now we know what the challenge is. Let’s discuss what are the possible solutions for it.

The Solution

There are 2 possible solutions to solve this challenge. Let’s look at the first one:

  1. Writing bash scripts for various tasks.
    This is definitely a solution but not a smart solution. You need to first write a script that will find out all the packages in your project and run one of the above tasks in it. You also need to make sure that you display output in a pretty format to make things readable. If you are more of a GUI guy then you need to create some sort of configuration in your IDE to run your scripts through GUI.
  2. Integrating Melos into your project.
    This is a smart solution over the first one which I highly recommend. So let’s discuss in details what Melos is and how to integrate it into your multi-package project.

Introducing Melos

Melos is a CLI tool for managing Flutter/Dart project with multiple packages.

Melos is developed by a well-known team in the Flutter community i.e invertase. You can read in detail about Melos on their website but here is a quick list of features Melos provide:

  • Automatic versioning & changelog generation.
  • Automated publishing of packages to pub.dev.
  • Local package linking and installation.
  • Executing simultaneous commands across packages.
  • Listing of local packages & their dependencies.

Now let’s see how we can perform all the above tasks using Melos.

Note: Please download the starter project if you wanna learn by doing. There is another branch where you can find the final version of the project.

Installing Melos

Let’s install Melos first. I assume you have already installed Flutter SDK and set the Flutter and Dart path to bash_profile . Run the following command in your terminal:

You can copy the command from the above image

The next step is to open up your starter project in your IDE. I prefer using Intellij and would show you some awesome GUI features provided by Melos. The project structure should look like the following:

Now create a file named melos.yamlin your root app. and copy the following content to it:

You can copy the code from the above image

Let’s understand the above script:
a) name : You have to give the name of your project. You can find it inside the pubspec.yaml of the root project.
b) packages : This list should contain paths to the individual packages within your project. Each path can be defined using the glob pattern expansion format.

Melos Bootstrap

Now run the following command in your terminal from your root project to link all your local packages together and update the dependencies i.e flutter pub get .

Make sure to run this command from inside the root project

You should see the following output after running the above command:

You can read why you need to bootstrap Melos here. To be precise it’s one of the important commands you should execute when setting up Melos in a project or you performed a cleanup in your project.

Melos Clean

You can execute this command when you want to remove temporary files from your project(build artifacts, pub files etc). This is how the command looks like:

You can copy the command from the above image

Commands

Now you will work on creating different commands to achieve the tasks which we mentioned at the starting of the article.

a. Running test cases in specific packages
Write the following command in your melos.yaml file:

The colours in the above image look weird. Blame carbon.now.sh 😅

Let’s understand what’s happening in the above script:
1) You have created a custom script i.e test:selective_unit_test that once executed will show you an option to select a package whose unit tests you wanna run.

2) Melos provide powerful filtering options to select packages that meet the filter criteria. In the above script, you used --dir-exists="test" as the filtering option. This will filter all the packages which consist of testfolder. You can find more filtering options on their website.

3) --fail-fast will immediately terminate the script execution if it encounters a failing test case.

4) You can give a human-readable description to each script by using the description section.

5) You must be wondering why did you name this command like test:selective_unit_test . The next command will answer your question. 😃

6) You can read in detail what melos exec does. Basically, it will execute the command or script in every package inside your project.

Now run the following command:

You can copy the command from the above image

You will be seeing the following output:

The above command was able to find out these packages which contained the folder test. Enter 2 as the option and you will see the following output:

b. Running test cases in all the packages
Now write the following command which will run all the unit test cases in the project. This won’t prompt any option selection:

Let’s discuss what the above command does:

  1. This command will basically run the previous command with --no-select as an argument. That means, run all the unit tests.
  2. You can use melos run test to run this command. You named this command test because there can be multiple variants of test commands like you created in the previous step i.e test:selective_unit_test . You can also create more variants e.g test:e2e_test , test:bdd_test etc. You can combine all the variants together and run in a single command i.e test .

c. Running analyzein all the packages:
Create the following command under the script section:

You can copy the script from the above image

Nothing fancy here. You can execute melos run analyze to run the analyze in all the packages.

d. Generating code coverage of the whole project:
To generate the code coverage for the whole project. There is a custom script included in the project i.e combine_coverage.sh . This will basically merge all the lcov.info files from different packages into one lcov.info file. Then you can use this method to convert lcov.info file to HTML.

You can copy the script from the above image

Write the following command under the script section:

You can copy the script from the above image

MELOS_ROOT_PATH will give you the path where melos.yaml is stored i.e root project. After the script’s execution has been completed. You can see the coverage_report folder in the project. Now you have one lcov.info file which will give you a report of the whole project.

Finally, your melos.yaml file will look something like this:

You can copy the script from the image

GUI options

If you don’t want to execute these commands through the terminal and want to run them using GUI then Melos got you covered. After adding all the commands you can run the bootstrap command again. This will generate some configuration and you can see some GUI options like this:

Now you can execute all these commands without typing anything in the terminal. 😄

Next Steps

This is just the tip of the iceberg. You can learn much more filtering options and commands from the Melos website. Hope you enjoyed the article. Please do connect with me on Twitter and LinkedIn. Stay safe and stay healthy. 😃

--

--

Sagar Suri
Flutter Community

Google certified Android app developer | Flutter Developer | Computer Vision Engineer | Gamer