X Tutup
Skip to content

Commit 15e1614

Browse files
Tim Blasivikerman
authored andcommitted
feat(dart/transform): Create standalone transformers for phases
Create transformers that allow specifying transformer actions on specific libraries. * angular2/transform/codegen: Generates all necessary code. * angular2/transform/reflection_rewriter: Replaces `bootstrap` calls in application entry points to remove transitive dart:mirrors import, resulting in smaller code size & faster execution. * angular2/transform/deferred_rewriter: Rewrites deferred imports and `loadLibrary` calls to initialize Angular2 and preserve deferred operation. Proper configuration of these three transformers can replace the single angular2 transformer, resulting in significant performance gains for builds of large angular2 apps. Update angular2 itself to declare the codegen transformer, since it has neither deferred imports nor application entry points. Remove the undocumented & unused quick_transformer.
1 parent ae49085 commit 15e1614

File tree

8 files changed

+219
-106
lines changed

8 files changed

+219
-106
lines changed

modules/angular2/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ dev_dependencies:
2727
quiver: '^0.21.4'
2828
test: '^0.12.6'
2929
transformers:
30-
- angular2
30+
- angular2/transform/codegen
3131
- $dart2js:
3232
commandLineOptions:
3333
- --show-package-warnings

modules_dart/transform/lib/src/transform/deferred_rewriter/transformer.dart

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,21 @@ import 'package:barback/barback.dart';
66

77
import 'package:angular2/src/transform/common/asset_reader.dart';
88
import 'package:angular2/src/transform/common/names.dart';
9-
import 'package:angular2/src/transform/common/options.dart';
109
import 'package:angular2/src/transform/common/zone.dart' as zone;
1110

1211
import 'rewriter.dart';
1312

14-
/// Transformer responsible for rewriting deferred library loads to enable
15-
/// initializing the reflector in a deferred way to keep the code with the
16-
/// deferred library.
13+
/// Transformer which rewrites deferred imports and `loadLibrary` calls.
14+
///
15+
/// Deferred imports with associated initialization code are rewritten to
16+
/// point to their associated generated code file.
17+
/// `loadLibrary` calls for libraries with associated initialization methods
18+
/// are rewritten to initialize after the library is loaded and before use.
1719
class DeferredRewriter extends AggregateTransformer implements LazyTransformer {
18-
final TransformerOptions options;
20+
DeferredRewriter();
1921

20-
DeferredRewriter(this.options);
22+
/// Ctor which tells pub that this can be run as a standalone transformer.
23+
DeferredRewriter.asPlugin(BarbackSettings _);
2124

2225
@override
2326
declareOutputs(DeclaringTransform transform) {
@@ -41,45 +44,51 @@ class DeferredRewriter extends AggregateTransformer implements LazyTransformer {
4144

4245
@override
4346
Future apply(AggregateTransform transform) async {
44-
return zone.exec(() async {
45-
final dartAsset = await _assetToProcess(transform);
46-
if (dartAsset == null) return;
47+
final dartAsset = await _assetToProcess(transform);
48+
if (dartAsset == null) return null;
49+
return applyImpl(transform, dartAsset.id);
50+
}
51+
52+
/// Transforms the asset with id [id].
53+
///
54+
/// [transform] must be an [AggregateTransform] or [Transform].
55+
Future applyImpl(dynamic transform, AssetId id) {
56+
assert(transform is AggregateTransform || transform is Transform);
4757

58+
return zone.exec(() async {
4859
var transformedCode = await rewriteDeferredLibraries(
49-
new AssetReader.fromTransform(transform), dartAsset.id);
60+
new AssetReader.fromTransform(transform), id);
5061
if (transformedCode != null) {
51-
transform
52-
.addOutput(new Asset.fromString(dartAsset.id, transformedCode));
62+
transform.addOutput(new Asset.fromString(id, transformedCode));
5363
}
5464
}, log: transform.logger);
5565
}
66+
}
5667

57-
/// Returns the asset we need to process or `null` if none exists.
58-
///
59-
/// Consumes the .dart.deferredCount asset if it is present.
60-
Future<Asset> _assetToProcess(AggregateTransform transform) async {
61-
// We only need to process .dart files that have an associated
62-
// .dart.deferredCount file with a value != "0".
63-
//
64-
// The .dart.deferredCount file is generated by a previous phase for files
65-
// which have deferred imports. An absent .dart.deferredCount asset is the
66-
// treated the same as a .dart.deferredCount asset with value "0".
67-
var dartAsset, deferredCountAsset;
68-
await for (Asset a in transform.primaryInputs) {
69-
if (a.id.path.endsWith(DEFERRED_EXTENSION)) {
70-
deferredCountAsset = a;
71-
} else if (a.id.path.endsWith('.dart')) {
72-
dartAsset = a;
73-
}
68+
/// Returns the asset we need to process or `null` if none exists.
69+
///
70+
/// Consumes the .dart.deferredCount asset if it is present.
71+
Future<Asset> _assetToProcess(AggregateTransform transform) async {
72+
// We only need to process .dart files that have an associated
73+
// .dart.deferredCount file with a value != "0".
74+
//
75+
// The .dart.deferredCount file is generated by a previous phase for files
76+
// which have deferred imports. An absent .dart.deferredCount asset is the
77+
// treated the same as a .dart.deferredCount asset with value "0".
78+
var dartAsset, deferredCountAsset;
79+
await for (Asset a in transform.primaryInputs) {
80+
if (a.id.path.endsWith(DEFERRED_EXTENSION)) {
81+
deferredCountAsset = a;
82+
} else if (a.id.path.endsWith('.dart')) {
83+
dartAsset = a;
7484
}
75-
if (deferredCountAsset == null) return null;
76-
// No longer necessary.
77-
transform.consumePrimary(deferredCountAsset.id);
78-
if ((await deferredCountAsset.readAsString()) == "0") return null;
79-
return dartAsset;
8085
}
86+
if (deferredCountAsset == null) return null;
87+
// No longer necessary.
88+
transform.consumePrimary(deferredCountAsset.id);
89+
if ((await deferredCountAsset.readAsString()) == "0") return null;
90+
return dartAsset;
8191
}
8292

83-
// Visible for testing
8493
Future<String> rewriteDeferredLibraries(AssetReader reader, AssetId id) =>
8594
rewriteLibrary(id, reader);

modules_dart/transform/lib/src/transform/quick_transformer.dart

Lines changed: 0 additions & 68 deletions
This file was deleted.

modules_dart/transform/lib/src/transform/reflection_remover/transformer.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:angular2/src/transform/common/asset_reader.dart';
88
import 'package:angular2/src/transform/common/mirror_mode.dart';
99
import 'package:angular2/src/transform/common/names.dart';
1010
import 'package:angular2/src/transform/common/options.dart';
11+
import 'package:angular2/src/transform/common/options_reader.dart';
1112
import 'package:angular2/src/transform/common/zone.dart' as zone;
1213

1314
import 'remove_reflection_capabilities.dart';
@@ -26,8 +27,13 @@ class ReflectionRemover extends Transformer implements LazyTransformer {
2627

2728
ReflectionRemover(this.options);
2829

30+
/// Ctor which tells pub that this can be run as a standalone transformer.
31+
factory ReflectionRemover.asPlugin(BarbackSettings settings) =>
32+
new ReflectionRemover(parseBarbackSettings(settings));
33+
2934
@override
30-
bool isPrimary(AssetId id) => options.entryPointGlobs != null &&
35+
bool isPrimary(AssetId id) =>
36+
options.entryPointGlobs != null &&
3137
options.entryPointGlobs.any((g) => g.matches(id.path));
3238

3339
@override

modules_dart/transform/lib/src/transform/transformer.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class AngularTransformerGroup extends TransformerGroup {
3737
[new DirectiveMetadataLinker()],
3838
[new ReflectionRemover(options)],
3939
[
40-
new DeferredRewriter(options),
40+
new DeferredRewriter(),
4141
new StylesheetCompiler(),
4242
new TemplateCompiler(options)
4343
],
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
library angular2.transform.codegen.dart;
2+
3+
import 'package:barback/barback.dart';
4+
import 'package:dart_style/dart_style.dart';
5+
6+
import 'package:angular2/src/transform/common/eager_transformer_wrapper.dart';
7+
import 'package:angular2/src/transform/common/formatter.dart' as formatter;
8+
import 'package:angular2/src/transform/common/options.dart';
9+
import 'package:angular2/src/transform/common/options_reader.dart';
10+
import 'package:angular2/src/transform/directive_metadata_linker/transformer.dart';
11+
import 'package:angular2/src/transform/directive_processor/transformer.dart';
12+
import 'package:angular2/src/transform/inliner_for_test/transformer.dart';
13+
import 'package:angular2/src/transform/stylesheet_compiler/transformer.dart';
14+
import 'package:angular2/src/transform/template_compiler/transformer.dart';
15+
16+
export 'package:angular2/src/transform/common/options.dart';
17+
18+
/// Generates code to replace mirror use in Angular 2 apps.
19+
///
20+
/// This transformer can be used along with others as a faster alternative to
21+
/// the single angular2 transformer.
22+
///
23+
/// See [the wiki][] for details.
24+
///
25+
/// [the wiki]: https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer
26+
class CodegenTransformer extends TransformerGroup {
27+
CodegenTransformer._(phases, {bool formatCode: false}) : super(phases) {
28+
if (formatCode) {
29+
formatter.init(new DartFormatter());
30+
}
31+
}
32+
33+
factory CodegenTransformer(TransformerOptions options) {
34+
var phases;
35+
if (options.inlineViews) {
36+
phases = [
37+
[new InlinerForTest(options)]
38+
];
39+
} else {
40+
phases = [
41+
[new DirectiveProcessor(options)],
42+
[new DirectiveMetadataLinker()],
43+
[new StylesheetCompiler(), new TemplateCompiler(options),],
44+
];
45+
}
46+
if (options.modeName == BarbackMode.RELEASE || !options.lazyTransformers) {
47+
phases = phases
48+
.map((phase) => phase.map((t) => new EagerTransformerWrapper(t)));
49+
}
50+
return new CodegenTransformer._(phases, formatCode: options.formatCode);
51+
}
52+
53+
factory CodegenTransformer.asPlugin(BarbackSettings settings) {
54+
return new CodegenTransformer(parseBarbackSettings(settings));
55+
}
56+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
library angular2.transform.deferred_rewriter.dart;
2+
3+
import 'dart:async';
4+
5+
import 'package:barback/barback.dart';
6+
7+
import 'package:angular2/src/transform/deferred_rewriter/transformer.dart'
8+
as base show DeferredRewriter;
9+
10+
// TODO(kegluneq): Make this a TransformerGroup and add an AggregateTransformer
11+
// that counts the number of transformed files & primary inputs.
12+
// If the number of primary inputs is >> transformed files, output an error
13+
// telling the user to use $include or $exclude in their pubspec.
14+
15+
/// Rewrites `deferred` imports that need Angular 2 initialization.
16+
///
17+
/// This transformer can be used along with others as a faster alternative to
18+
/// the single angular2 transformer.
19+
///
20+
/// See [the wiki][] for details.
21+
///
22+
/// [the wiki]: https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer
23+
class DeferredRewriter extends Transformer implements DeclaringTransformer {
24+
final base.DeferredRewriter _impl;
25+
26+
/// Ctor which tells pub that this can be run as a standalone transformer.
27+
DeferredRewriter.asPlugin(BarbackSettings _)
28+
: _impl = new base.DeferredRewriter();
29+
30+
/// Signal that we process all .dart files.
31+
///
32+
/// Instead, use the standard, built-in $exclude and $include transformer
33+
/// parameters to control which files this transformer runs on.
34+
/// See [https://www.dartlang.org/tools/pub/assets-and-transformers.html] for
35+
/// details.
36+
@override
37+
String get allowedExtensions => '.dart';
38+
39+
@override
40+
declareOutputs(transform) => _impl.declareOutputs(transform);
41+
42+
@override
43+
Future apply(transform) =>
44+
_impl.applyImpl(transform, transform.primaryInput.id);
45+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
library angular2.transform.reflection_remover.dart;
2+
3+
import 'dart:async';
4+
5+
import 'package:barback/barback.dart';
6+
7+
import 'package:angular2/src/transform/common/options.dart';
8+
import 'package:angular2/src/transform/common/options_reader.dart';
9+
import 'package:angular2/src/transform/reflection_remover/transformer.dart'
10+
as base show ReflectionRemover;
11+
12+
// TODO(kegluneq): Make this a TransformerGroup and add an AggregateTransformer
13+
// that counts the number of transformed files & primary inputs.
14+
// If the number of primary inputs is >> transformed files, output an error
15+
// telling the user to use $include or $exclude in their pubspec.
16+
17+
/// Removes the transitive dart:mirrors import from Angular 2 entrypoints.
18+
///
19+
/// This transformer can be used along with others as a faster alternative to
20+
/// the single angular2 transformer.
21+
///
22+
/// See [the wiki][] for details.
23+
///
24+
/// [the wiki]: https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer
25+
class ReflectionRemover extends Transformer implements DeclaringTransformer {
26+
final base.ReflectionRemover _impl;
27+
28+
ReflectionRemover._(this._impl);
29+
30+
/// Ctor which tells pub that this can be run as a standalone transformer.
31+
factory ReflectionRemover.asPlugin(BarbackSettings settings) {
32+
final options = parseBarbackSettings(settings);
33+
final entryPoints = options.entryPoints;
34+
if (entryPoints != null && entryPoints.isNotEmpty) {
35+
// TODO(kegluneq): Add a goo.gl link with more info.
36+
throw new ArgumentError.value(
37+
entryPoints.join(', '),
38+
ENTRY_POINT_PARAM,
39+
"Do not use '$ENTRY_POINT_PARAM' when specifying the Angular 2 "
40+
"reflection_remover transformer. Instead, use pub's built-in "
41+
r"$include and $exclude parameters to filter which files are "
42+
"processed.");
43+
}
44+
return new ReflectionRemover._(new base.ReflectionRemover(options));
45+
}
46+
47+
/// Signal that we process all .dart files.
48+
///
49+
/// The underlying ReflectionRemover implementation respects the entry_points
50+
/// transformer parameter, but this is inefficient and can be expensive for
51+
/// large numbers of files.
52+
///
53+
/// Instead, use the standard, built-in $exclude and $include transformer
54+
/// parameters to control which files this transformer runs on.
55+
/// See [https://www.dartlang.org/tools/pub/assets-and-transformers.html] for
56+
/// details.
57+
@override
58+
String get allowedExtensions => '.dart';
59+
60+
@override
61+
declareOutputs(transform) => _impl.declareOutputs(transform);
62+
63+
@override
64+
Future apply(transform) => _impl.apply(transform);
65+
}

0 commit comments

Comments
 (0)
X Tutup