Differences between the build package and pub + barback.

If you have written a barbackTransformer in the past, then the
Builder API should be familiar to you. The main difference
is that Builders must always configure outputs based on input extensions.

The basic API looks like this:

abstract class Builder {
/// You can only output files in `build` that are configured here. You are not
/// required to output all of these files, but no other [Builder] is allowed
/// to produce the same outputs.
Map<String, List<String>> get buildExtensions;
/// Similar to `Transformer.apply`. This is where you build and output files.
Future build(BuildStep buildStep);
}

Here is an implementation of a Builder which just copies files to other files
with the same name, but an additional extension:

/// A really simple [Builder], it just makes copies!
class CopyBuilder implements Builder {
final String extension;
CopyBuilder(this.extension);
Future build(BuildStep buildStep) async {
/// Each [buildStep] has a single input.
var inputId = buildStep.inputId;
/// Create a new target [AssetId] based on the old one.
var copy = inputId.addExtension(extension);
var contents = await buildStep.readAsString(inputId);
/// Write out the new asset.
///
/// There is no need to `await` here, the system handles waiting on these
/// files as necessary before advancing to the next phase.
buildStep.writeAsString(copy, contents);
}
/// Configure output extensions. All possible inputs match the empty input
/// extension. For each input 1 output is created with `extension` appended to
/// the path.
Map<String, List<String>> get buildExtensions => {'': [extension]};
}

It should be noted that you should never touch the file system directly. Go
through the buildStep#readAsString and buildStep#writeAsString methods in
order to read and write assets. This is what enables the package to track all of
your dependencies and do incremental rebuilds. It is also what enables your
Builder to run on different environments.

If you need to do analyzer resolution, you can use the BuildStep#resolver
object. This makes sure that all Builders in the system share the same
analysis context, which greatly speeds up the overall system when multiple
Builders are doing resolution.

The build package includes a Resource class, which can give you an instance
of an expensive object that is guaranteed to be unique across builds, but may
be re-used by multiple build steps within a single build (to the extent that
the implementation allows). It also gives you a way of disposing of your
resource at the end of its lifecycle.

The Resource<T> constructor takes a single required argument which is a
factory function that returns a FutureOr<T>. There is also a named argument
dispose which is called at the end of life for the resource, with the
instance that should be disposed. This returns a FutureOr<dynamic>.

You can get an instance of the underlying resource by using the
BuildStep#fetchResource method, whose type signature looks like
Future<T> fetchResource<T>(Resource<T>).

Important Note: It may be tempting to try and use a Resource instance to
cache information from previous build steps (or even assets), but this should
be avoided because it can break the soundness of the build, and may introduce
subtle bugs for incremental builds (remember the whole build doesn't run every
time!). The build package relies on the BuildStep#canRead and
BuildStep#readAs* methods to track build step dependencies, so sidestepping
those can and will break the dependency tracking, resulting in inconsistent and
stale assets.

Changed the return type of Builder.build from Future<dynamic> to
FutureOr<void>. This should not be breaking for most Builder authors, it
is only breaking for build system implementations that run Builders.

Remove restrictions around the root package when Builders are running. It is
the responsibility of the build system to ensure that builders are only run on
inputs that will produce outputs that can be written.

Rename AssetReader.hasInput as canRead. This is breaking for implementers
of AssetReader and for any clients passing a BuildStep as an AssetReader

Make canRead return a FutureOr for more flexibility

Drop ManagedBuildStep class.

Drop BuildStep.logger. All logging should go through the top level log.

BuildStep.writeAs* methods now take a FutureOr for content. Builders which
produce content asynchronously can now set up the write without waiting for it
to resolve.

BreakingdeclareOutputs is replaced with buildExtensions. All Builder
implementations must now have outputs that vary only based on the extensions
of inputs, rather than based on any part of the AssetId.

A number of changes to the apis, primarily to support reading/writing as bytes,
as this is going to inevitably be a required feature. This will hopefully be the
last breaking change before the 1.0 release, but it is a fairly large one.

The type of the AssetWriterSpy#assetsWritten getter has changed from an
Iterable<Asset> to an Iterable<AssetId>.

BuildStep#input has been changed to BuildStep#inputId, and its type has
changed from Asset to AssetId. This means you must now use
BuildStep#readAsString or BuildStep#readAsBytes to read the primary input,
instead of it already being read in for you.

Resolver no longer has a release method (they are released for you).

BuildStep#resolve no longer exists, and has been replaced with the
BuildStep#resolver getter.

Resolver.getLibrary will now throw a NonLibraryAssetException instead of
return null if it is asked to resolve an impossible library.

Note: The changes to AssetReader and AssetWriter also affect BuildStep
and other classes that implement those interfaces.

BREAKING Move some classes and methods out of this package. If you are
using build, watch, or serve, along with PhaseGroup and related
classes add a dependency on build_runner. If you are using
BuilderTransformer or TansformerBuilder add a dependency on
build_barback.

BREAKING Resolvers is now an abstract class. If you were using the
constructor const Resolvers() as a default instance import build_barback
and used const BarbackResolvers() instead.

Added the deleteFilesByDefault option to all top level methods. This will
skip the prompt to delete files, and instead act as if you responded y.

Also by default in a non-console environment the prompt no longer exists and
it will instead just exit with an error.

Added support for multiple build scripts. Each script now has its own asset
graph based on a hash of the script uri.

You need to be careful here, as you can get in an infinite loop if two
separate build scripts keep triggering updates for each other.

There is no explicit link between multiple scripts, so they operate as if
all changes from other scripts were user edits. This will usually just do
the "right thing", but may result in undesired behavior in some
circumstances.