perf(dart/transform): Only process deferred libs when necessary
Previously, every .dart file in a package was processed to ensure proper initialization of deferred loaded libraries. Update the transformer to avoid processing libraries which we know do not import any deferred libraries. Closes #6745
This commit is contained in:
parent
3a40cd79f0
commit
f56df65d48
|
@ -6,6 +6,7 @@ const SETUP_METHOD_NAME = 'initReflector';
|
||||||
const REFLECTOR_VAR_NAME = 'reflector';
|
const REFLECTOR_VAR_NAME = 'reflector';
|
||||||
const TRANSFORM_DYNAMIC_MODE = 'transform_dynamic';
|
const TRANSFORM_DYNAMIC_MODE = 'transform_dynamic';
|
||||||
const CSS_EXTENSION = '.css';
|
const CSS_EXTENSION = '.css';
|
||||||
|
const DEFERRED_EXTENSION = '.dart.deferredCount';
|
||||||
const SHIMMED_STYLESHEET_EXTENSION = '.css.shim.dart';
|
const SHIMMED_STYLESHEET_EXTENSION = '.css.shim.dart';
|
||||||
const NON_SHIMMED_STYLESHEET_EXTENSION = '.css.dart';
|
const NON_SHIMMED_STYLESHEET_EXTENSION = '.css.dart';
|
||||||
const META_EXTENSION = '.ng_meta.json';
|
const META_EXTENSION = '.ng_meta.json';
|
||||||
|
@ -21,8 +22,10 @@ const TEMPLATE_EXTENSION = '.template.dart';
|
||||||
|
|
||||||
/// Note that due to the implementation of `_toExtension`, ordering is
|
/// Note that due to the implementation of `_toExtension`, ordering is
|
||||||
/// important. For example, putting '.dart' first in this list will cause
|
/// important. For example, putting '.dart' first in this list will cause
|
||||||
/// incorrect behavior.
|
/// incorrect behavior because it will (incompletely) match '.template.dart'
|
||||||
|
/// files.
|
||||||
const ALL_EXTENSIONS = const [
|
const ALL_EXTENSIONS = const [
|
||||||
|
DEFERRED_EXTENSION,
|
||||||
META_EXTENSION,
|
META_EXTENSION,
|
||||||
SUMMARY_META_EXTENSION,
|
SUMMARY_META_EXTENSION,
|
||||||
TEMPLATE_EXTENSION,
|
TEMPLATE_EXTENSION,
|
||||||
|
@ -36,6 +39,7 @@ const ALL_EXTENSIONS = const [
|
||||||
/// any files named like transformer outputs will be reported as generated.
|
/// any files named like transformer outputs will be reported as generated.
|
||||||
bool isGenerated(String uri) {
|
bool isGenerated(String uri) {
|
||||||
return const [
|
return const [
|
||||||
|
DEFERRED_EXTENSION,
|
||||||
META_EXTENSION,
|
META_EXTENSION,
|
||||||
NON_SHIMMED_STYLESHEET_EXTENSION,
|
NON_SHIMMED_STYLESHEET_EXTENSION,
|
||||||
SHIMMED_STYLESHEET_EXTENSION,
|
SHIMMED_STYLESHEET_EXTENSION,
|
||||||
|
@ -44,6 +48,10 @@ bool isGenerated(String uri) {
|
||||||
].any((ext) => uri.endsWith(ext));
|
].any((ext) => uri.endsWith(ext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `uri` with its extension updated to [DEFERRED_EXTENSION].
|
||||||
|
String toDeferredExtension(String uri) =>
|
||||||
|
_toExtension(uri, ALL_EXTENSIONS, DEFERRED_EXTENSION);
|
||||||
|
|
||||||
/// Returns `uri` with its extension updated to [META_EXTENSION].
|
/// Returns `uri` with its extension updated to [META_EXTENSION].
|
||||||
String toMetaExtension(String uri) =>
|
String toMetaExtension(String uri) =>
|
||||||
_toExtension(uri, ALL_EXTENSIONS, META_EXTENSION);
|
_toExtension(uri, ALL_EXTENSIONS, META_EXTENSION);
|
||||||
|
|
|
@ -14,7 +14,7 @@ import 'rewriter.dart';
|
||||||
/// Transformer responsible for rewriting deferred library loads to enable
|
/// Transformer responsible for rewriting deferred library loads to enable
|
||||||
/// initializing the reflector in a deferred way to keep the code with the
|
/// initializing the reflector in a deferred way to keep the code with the
|
||||||
/// deferred library.
|
/// deferred library.
|
||||||
class DeferredRewriter extends Transformer implements LazyTransformer {
|
class DeferredRewriter extends AggregateTransformer implements LazyTransformer {
|
||||||
final TransformerOptions options;
|
final TransformerOptions options;
|
||||||
|
|
||||||
DeferredRewriter(this.options);
|
DeferredRewriter(this.options);
|
||||||
|
@ -25,23 +25,60 @@ class DeferredRewriter extends Transformer implements LazyTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool isPrimary(AssetId id) =>
|
dynamic classifyPrimary(AssetId id) {
|
||||||
id.extension.endsWith('dart') && _isNotGenerated(id);
|
// Map <name>.dart and <name>.dart.deferredCount => <name>.
|
||||||
|
// Anything else to `null`.
|
||||||
|
var extension = null;
|
||||||
|
if (id.path.endsWith(DEFERRED_EXTENSION)) {
|
||||||
|
extension = DEFERRED_EXTENSION;
|
||||||
|
} else if (id.path.endsWith('.dart') && !isGenerated(id.path)) {
|
||||||
|
extension = '.dart';
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return id.path.substring(0, id.path.length - extension.length);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future apply(Transform transform) async {
|
Future apply(AggregateTransform transform) async {
|
||||||
return zone.exec(() async {
|
return zone.exec(() async {
|
||||||
var asset = transform.primaryInput;
|
final dartAsset = await _assetToProcess(transform);
|
||||||
var reader = new AssetReader.fromTransform(transform);
|
if (dartAsset == null) return;
|
||||||
var transformedCode = await rewriteDeferredLibraries(reader, asset.id);
|
|
||||||
|
var transformedCode = await rewriteDeferredLibraries(
|
||||||
|
new AssetReader.fromTransform(transform), dartAsset.id);
|
||||||
if (transformedCode != null) {
|
if (transformedCode != null) {
|
||||||
transform.addOutput(new Asset.fromString(asset.id, transformedCode));
|
transform
|
||||||
|
.addOutput(new Asset.fromString(dartAsset.id, transformedCode));
|
||||||
}
|
}
|
||||||
}, log: transform.logger);
|
}, log: transform.logger);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool _isNotGenerated(AssetId id) => !isGenerated(id.path);
|
/// Returns the asset we need to process or `null` if none exists.
|
||||||
|
///
|
||||||
|
/// Consumes the .dart.deferredCount asset if it is present.
|
||||||
|
Future<Asset> _assetToProcess(AggregateTransform transform) async {
|
||||||
|
// We only need to process .dart files that have an associated
|
||||||
|
// .dart.deferredCount file with a value != "0".
|
||||||
|
//
|
||||||
|
// The .dart.deferredCount file is generated by a previous phase for files
|
||||||
|
// which have deferred imports. An absent .dart.deferredCount asset is the
|
||||||
|
// treated the same as a .dart.deferredCount asset with value "0".
|
||||||
|
var dartAsset, deferredCountAsset;
|
||||||
|
await for (Asset a in transform.primaryInputs) {
|
||||||
|
if (a.id.path.endsWith(DEFERRED_EXTENSION)) {
|
||||||
|
deferredCountAsset = a;
|
||||||
|
} else if (a.id.path.endsWith('.dart')) {
|
||||||
|
dartAsset = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deferredCountAsset == null) return null;
|
||||||
|
// No longer necessary.
|
||||||
|
transform.consumePrimary(deferredCountAsset.id);
|
||||||
|
if ((await deferredCountAsset.readAsString()) == "0") return null;
|
||||||
|
return dartAsset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Visible for testing
|
// Visible for testing
|
||||||
Future<String> rewriteDeferredLibraries(AssetReader reader, AssetId id) async {
|
Future<String> rewriteDeferredLibraries(AssetReader reader, AssetId id) async {
|
||||||
|
|
|
@ -33,6 +33,7 @@ class DirectiveProcessor extends Transformer implements LazyTransformer {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
declareOutputs(DeclaringTransform transform) {
|
declareOutputs(DeclaringTransform transform) {
|
||||||
|
transform.declareOutput(_deferredAssetId(transform.primaryId));
|
||||||
transform.declareOutput(_ngSummaryAssetId(transform.primaryId));
|
transform.declareOutput(_ngSummaryAssetId(transform.primaryId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +50,17 @@ class DirectiveProcessor extends Transformer implements LazyTransformer {
|
||||||
}
|
}
|
||||||
transform.addOutput(new Asset.fromString(
|
transform.addOutput(new Asset.fromString(
|
||||||
_ngSummaryAssetId(primaryId), _encoder.convert(ngMeta.toJson())));
|
_ngSummaryAssetId(primaryId), _encoder.convert(ngMeta.toJson())));
|
||||||
|
|
||||||
|
var deferredCount = 0;
|
||||||
|
if (ngMeta.ngDeps != null) {
|
||||||
|
deferredCount = ngMeta.ngDeps.imports.where((i) => i.isDeferred).length;
|
||||||
|
}
|
||||||
|
if (deferredCount > 0) {
|
||||||
|
// The existence of this file with the value != "0" signals
|
||||||
|
// DeferredRewriter that the associated .dart file needs attention.
|
||||||
|
transform.addOutput(new Asset.fromString(
|
||||||
|
_deferredAssetId(primaryId), deferredCount.toString()));
|
||||||
|
}
|
||||||
}, log: transform.logger);
|
}, log: transform.logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,3 +69,8 @@ AssetId _ngSummaryAssetId(AssetId primaryInputId) {
|
||||||
return new AssetId(
|
return new AssetId(
|
||||||
primaryInputId.package, toSummaryExtension(primaryInputId.path));
|
primaryInputId.package, toSummaryExtension(primaryInputId.path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssetId _deferredAssetId(AssetId primaryInputId) {
|
||||||
|
return new AssetId(
|
||||||
|
primaryInputId.package, toDeferredExtension(primaryInputId.path));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue