There are a few key differences that make the build system better for most use cases.
pub build will only ever output files into your
build directory, and
pub serve only ever outputs them into an in-memory file system. With the
build package, you can output files anywhere in the current package.
This enables you to generate dart files which are imported by your project, without getting any warnings about missing files from the analyzer. At the same time it enables you to easily go explore those files in your editor, and set breakpoints inside those files.
You can't overwrite any pre-existing files using
build, you can only generate
barback a transformer can overwrite a file any number of times, and this
can lead to confusion and difficulty when debugging, especially with source
build package requires Builders to configure which output file extensions
will be built for corresponding input file extensions. This allows fine grained
and incremental builds. See the
build_runner package for an approach to
barback, some transformations on your package dependencies may be cached,
but any transformations on your current package are always redone each time you
pub build or
pub serve. In serve mode it will do incremental builds
once the first build has run, but if you restart it then you have to start over
Execution modes and reflection
Most frameworks that use reflection today enable running in two different modes,
one which uses
dart:mirrors for development in dartium, and one which uses
static code generated by a
Transformer for deployment. All features that use
reflection have to be implemented in both modes, and bugs might exist in only
one mode. This all ends up resulting in obscure deployment time only issues,
as well as a lot of wasted cycles testing the same app in multiple different
build, you can eliminate entirely the
dart:mirrors mode. You are always
using the generated code, all the time. This makes it easier on framework devs,
and easier on users who have fewer modes to support.