Vendoring Flutter into your app repo
In this post, I'll describe how to vendor Flutter into your app's repo using Git Submodules, so that you can easily change Flutter versions in your app between stable, beta, or even the code merged into master right this minute!
Why though?
The biggest reason is, we want our app's dependencies to be self-contained and not rely on the external environment. Just like we use pubspec.lock
to pin library versions so that all the developers on the team are getting the same libraries, we want the same thing for Flutter itself.
Vendoring Flutter makes changing the version of Flutter as easy as changing the version of one of your libraries, so that everyone on your team is on the same page. Another benefit is that setting up Flutter in CI is a bit easier, since you don't have to find a temp directory to extract it to, download and verify zips, etc etc, as well as being able to use the newest Flutter features without waiting for stable.
Setting it up
First, run this command in the root of your Git repo to set up Flutter in a vendor
folder in your repo:
git submodule add https://github.com/flutter/flutter
cd ./vendor/flutter
git checkout v1.2.1
cd ../../
git add .gitmodules ./vendor
git commit -m "Set Flutter to v1.2.1"
Now, we'll add a script to make it a bit easier to use. Similar to gradlew
which wraps Gradle to make sure you get the version you want, we're going to make a new script. Add these two files to the root of your repo:
For macOS / Linux: ./flutterw
#!/bin/bash
set -euo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export PATH="$DIR/vendor/flutter/bin:$PATH"
exec flutter $@
(Make sure to chmod +x
this script after you add it!)
For Windows: ./flutterw.cmd
%~dp0vendor\flutter\bin\flutter.bat" %*
Now, we can run all of the commands we're used to, only with flutterw
instead of flutter
:
./flutterw doctor
Setting up VS Code
In order to get VS Code to understand our new vendored Flutter, we need to add one more file. In your .vscode/settings.json
, merge in the following settings (if you don't have this file, create it):
{
"dart.flutterSdkPath": "vendor/flutter",
"dart.analysisExcludedFolders": [
"vendor"
],
"dart.doNotFormat": [
"vendor/**/*.dart"
],
}
This tells VS Code that when you start the debugger where to find Flutter, and it also tells VS Code not to try to treat all of Flutter as your app's code (without this, the Dart Analyzer will throw lots and lots of unrelated errors).
Configuring CI
The good news is, this step is actually a lot easier now. Your entire build script for Android is now as simple as:
git submodule update --init --recursive
./flutterw test
./flutterw build apk
If you're using Azure Pipelines (try it! it's very good!), it's usually better to split out setting up Flutter into its own step so that you can measure test and build time independently:
steps:
- script: git submodule update --init --recursive && ./flutterw doctor
displayName: 'Update submodules and set up Flutter'
- script: ./flutterw test
displayName: 'Flutter Test'
- script: ./flutterw build apk
displayName: 'Release build'
Switching Flutter Versions
When you want to switch versions of Flutter, you change the pinned submodule. Here's an example of how to change to the latest tag (as of this writing):
cd ./vendor/flutter
git fetch --tags
git checkout v1.5.8
cd ../..
git add -u ./vendor
git commit -m "Bump Flutter to v1.5.8"
## This last part will update the Dart SDK and related tools
./flutterw doctor
And that's it! Let me know on Twitter if this helped you out or if you're stuck.
Previous post: Using VS Code themes in Windows Terminal
Next post: New Game+