Hi everyone,
Since version
0.11.1, barback has supported two special types of transformers: lazy transformers and declaring transformers. However, until recently the fact that a transformer was lazy or declaring was ignored by pub; it was treated like any other transformer. As of
r35139, lazy and declaring transformers are fully supported in pub, so you can start using them.
Lazy Transformers
When using pub serve, lazy transformers don't run their apply methods until one of their outputs is requested. If a transformer takes so long to run that it's painful to run it eagerly every time a file changes, it's a good candidate for a lazy transformer. The built-in dart2js transformer is a good example: it can take a considerable amount of time to compile a large program, so it's lazy. This allows you to run pub serve in an application with many entrypoints and tests and only compile the entrypoints that you access when you access them—or, if you're using Dartium, never compile them at all.
In order to mark your transformer as lazy, it should implement the
LazyTransformer interface. This interface has one method,
declareOutputs, which takes a DeclaringTransform and uses it to declare which outputs it will emit. This is necessary so that barback knows which outputs should trigger a call to apply.
Here's an example of the dart2js transformer's declareOutputs method:
class Dart2JSTransformer extends Transformer implements LazyTransformer {
// ...
Future declareOutputs(DeclaringTransform transform) {
// Note that DeclaringTransform only gives access to the primary input's id, not its
// contents. This allows lazy transformers to be piped into one another while preserving
// their laziness.
transform.declareOutput(transform.primaryId.addExtension(".js"));
transform.declareOutput(transform.primaryId.addExtension(".precompiled.js"));
if (_generateSourceMaps) {
transform.declareOutput(transform.primaryId.addExtension(".js.map"));
}
return new Future.value();
}
}
Declaring Transformers
Declaring transformers are like lazy transformers in that they tell barback what outputs they'll emit via declareOutputs. Otherwise, though, they're just like normal transformers: they'll run eagerly whenever their inputs change. Telling barback what they'll output lets it figure out the asset graph quickly, which enables some optimizations, but the big benefit comes from how declaring transformers interact with lazy transformers. If a lazy transformer's output is used as a declaring transformer's primary input, laziness will be preserved.
For example, suppose the dart2js transformer is followed by a jsmin transformer. This transformer implements the
DeclaringTransformer interface to indicate that it's declaring:
class JSMin extends Transformer implements DeclaringTransformer {
// ...
Future declareOutputs(DeclaringTransform transform) {
transform.declareOutput(transform.primaryId.addExtension(".min"));
return new Future.value();
}
}
For the file app/myapp.dart, dart2js will declare that it emits app/myapp.dart.js. Then jsmin in turn will declare that it emits app/myapp.dart.js.min. When using pub serve, neither dart2js nor jsmin will run until app/myapp.dart.js.min is requested.
Note that LazyTransformer is a subtype of DeclaringTransformer, so laziness will be preserved through multiple lazy transformers as well.
What You Should Do
If your transformer takes a long time to run, mark it as lazy. That way, users of pub serve can only run your transformer when they need its outputs.
If you can tell what assets your transformer will emit by looking at its primary input, mark it as declaring. This will help barback optimize your asset graph and make your transformer interact well with lazy transformers.
If you make your transformer lazy or declaring, make sure your barback version constraint's lower bound is at least 0.11.1. You don't need to worry about compatibility with pub: older versions will just treat your transformers as though they weren't lazy or declaring, but will otherwise work fine.
Let me know if you have any questions!
- N