Updating your pub package to Dart 2
Dart 2 is imminent. If you own a package on pub.dartlang.org, you might want to make sure it’s ready.
Take inventory
Head over to pub and search for packages associated with your email. If you’ve been around the Dart ecosystem for a while (like me), you might have forgotten about ever writing some of these.
If you go to pub.dartlang.org and search for email:your.email@example.com
, you’ll see all the Dart packages you own.
Decide which ones are worth updating
Some packages are timeless, and some not so much. For example, my simple_preprocessor
package for adding C-style macros can safely die in Dart 1 land. It was useful at some point, but only to me, and not any more. Pub does a decent job of hiding these old packages from users, sorting them at the very bottom of everything. (In the future, we might add the possibility for package owners to flag their own packages with the [DEPRECATED] flag.)
Pub now helpfully scores every package, and one of the criteria is popularity. If your package has popularity > 0, then it’s definitely being used by people other than you, and it’s worth updating.
Install Dart 2 (and 1)
If you’re using Flutter, you already have a preview release of Dart 2 (in $YOUR_FLUTTER_PATH/bin/cache/dart-sdk/bin/dart
). But that's version 2.0.0-dev.58.0
so I recommend that you install the latest one via the standalone Dart SDK process. As of this writing, that will give you version 2.0.0-dev.69.1
.
I found it useful to keep Dart 1 around. You can do that via homebrew’s switch
command, but that's assuming that you still have Dart 1 in your homebrew cache — and it's also quite annoying to switch from one version to another all the time. So, if you're like me, you'll just go to the manual download page, download the latest Dart 1 SDK as a zip file, unzip it somewhere, and then make an alias like this in your .bash_profile
:
alias dart1=/path/to/dart-1.24.3-sdk/bin/dart
alias dartanalyzer1=/path/to/dart-1.24.3-sdk/bin/dartanalyzer
alias pub1=/path/to/dart-1.24.3-sdk/bin/pub
This lets you freely switch from running things in Dart 1 world and Dart 2 world. You should be able to do this now:
$ dart --version
Dart VM version: 2.0.0-dev.69.1 (Fri Jul 20 18:30:52 2018 +0200) on "macos_x64"
$ dart1 --version
Dart VM version: 1.24.3 (Wed Dec 13 23:26:59 2017) on "macos_x64"
Version 1.24.3
will likely be the last version of Dart 1, so I feel it's okay to install it manually like this.
Migrate the code
There’s a migration guide here: dartlang.org/dart-2. Go read it, it has really useful bits of information, like the existence of the dart2_fix
tool, the dartfmt --fix
flag, and many more.
If you haven’t touched your package in a while, a common set of things to do first is:
- Add
.dart_tool/
into.gitignore
- Bump the SDK version constraints in
pubspec.yaml
from something likesdk: ">=1.8.0 <2.0.0"
to something likesdk: ">=2.0.0-dev <3.0.0"
(orsdk: ">=1.24.3 <3.0.0"
if you want to keep Dart 1 compatibility) - Bump all
dependencies
(anddev_dependencies
) inpubspec.yaml
to Dart-2-compatible versions (check their change log to find the version). Avoid pinning dependencies to the very latest version unless you absolutely need to. Having a broader range will give you package users more freedom to pick their own dependency versions. - Run
pub upgrade
(not justpub get
). Even better, run_PUB_TEST_SDK_VERSION=2.0.0 pub upgrade
(explained here).
Then you’re ready to fix errors, if any. This is where the Dart 2 migration guide (linked above) is helpful, with pages like Fixing Common Type Problems.
When you have no more errors but still have warnings, don’t forget that you can use dart2_fix
and dartfmt --fix
(again, see the helpful migration guide linked above) to get rid of the lints and warnings automatically. dart2_fix
deals with changes to constant names (like JSON
becoming json
) and dartfmt --fix
removes unnecessary new
and const
. Don't do it yourself when you don't need to.
What’s left after this step are mostly deprecation warnings. For example, instead of int.parse(string, (_) => -1)
, you now do int.tryParse(string) ?? -1
. Integers are now 64-bit, so if you want really really big numbers, you need to use the new BigInt
class. That kind of thing.
Optional: add CI testing
If your package isn’t already continuously tested, now is a good chance to start. If you want to go with Travis, and assuming you have tests, then it’s pretty simple.
You create a new file in the root of your package called .travis.yml
and fill it with something like this:
language: dart
dart:
- dev
script:
- dartanalyzer --fatal-warnings --fatal-lints .
- pub run test
You need to tell Travis to use the dev
version of Dart (i.e. Dart 2) for now because by default it uses stable
(which is, as of this writing, still Dart 1).
Once Dart 2 lands, you might want to change this back, or use Travis’s build matrix to test on various versions.
By the way, the script:
part isn't necessary. It's useful if you want to prevent code with warnings or lints from ever reaching your repo. If you're not that hardcore, leave that out. Travis will run pub run test
for you.
(There’s more you can do in your .travis.yml
file. Read the Travis Dart docs here.)
Once you have the .travis.yml
file set up, go to your Travis profile, enable Travis for this particular repository, then push your changes (including the .travis.yml
file). If you're like me, you won't make it quite right on the first few tries. That's okay, just keep at it until Travis runs and the result is green.
Then, take the badge and put it in your README.md
. You earned it. (And potential users of your package will find it super useful.)
Oh, and do make use of Travis’s awesome “cron job” functionality. It’ll rerun your test every day/week/month for you even when there’s no change on your repo.
Add a change log
While we’re at this, add a CHANGELOG.md
file (assuming you don’t have it yet). Take this as a fresh start and just add the first record for this change, i.e. something like this:
## 1.2.3
- Upgrade to Dart 2
Bump your own version
If you only made some small internal changes, and no changes to your API, you can bump just the minor version. (At least that’s my reading of the semver spec.)
But do feel free to bump to the next major version. Especially if you’re not yet v1 (e.g. your version is something like 0.1.3
) and yet there are people building software on top of your package. This is as good an excuse as any to release a stable version.
Upload to pub
Run pub publish
.
Now wait a few minutes and review the package’s page on pub.dartlang.org. It should get a better score, but — more importantly — it’s now ready for Dart 2.