feat(dart/transform): Inline templateUrl
values
Modify DirectiveProcessor to inline `templateUrl` values to avoid making additional browser requests. Closes #1035
This commit is contained in:
@ -1,10 +1,15 @@
|
||||
library angular2.transform.directive_processor.rewriter;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analyzer/analyzer.dart';
|
||||
import 'package:analyzer/src/generated/java_core.dart';
|
||||
import 'package:angular2/src/services/xhr.dart' show XHR;
|
||||
import 'package:angular2/src/transform/common/annotation_matcher.dart';
|
||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||
import 'package:angular2/src/transform/common/async_string_writer.dart';
|
||||
import 'package:angular2/src/transform/common/logging.dart';
|
||||
import 'package:angular2/src/transform/common/names.dart';
|
||||
import 'package:angular2/src/transform/common/xhr_impl.dart';
|
||||
import 'package:barback/barback.dart' show AssetId;
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
@ -17,20 +22,22 @@ import 'visitors.dart';
|
||||
/// If no Angular 2 `Directive`s are found in `code`, returns the empty
|
||||
/// string unless `forceGenerate` is true, in which case an empty ngDeps
|
||||
/// file is created.
|
||||
String createNgDeps(
|
||||
String code, AssetId assetId, AnnotationMatcher annotationMatcher) {
|
||||
Future<String> createNgDeps(AssetReader reader, AssetId assetId,
|
||||
AnnotationMatcher annotationMatcher) async {
|
||||
// TODO(kegluneq): Shortcut if we can determine that there are no
|
||||
// [Directive]s present, taking into account `export`s.
|
||||
var writer = new PrintStringWriter();
|
||||
var visitor = new CreateNgDepsVisitor(writer, assetId, annotationMatcher);
|
||||
parseCompilationUnit(code, name: assetId.toString()).accept(visitor);
|
||||
return '$writer';
|
||||
var writer = new AsyncStringWriter();
|
||||
var visitor = new CreateNgDepsVisitor(
|
||||
writer, assetId, new XhrImpl(reader, assetId), annotationMatcher);
|
||||
var code = await reader.readAsString(assetId);
|
||||
parseCompilationUnit(code, name: assetId.path).accept(visitor);
|
||||
return await writer.asyncToString();
|
||||
}
|
||||
|
||||
/// Visitor responsible for processing [CompilationUnit] and creating an
|
||||
/// associated .ng_deps.dart file.
|
||||
class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
|
||||
final PrintWriter writer;
|
||||
final AsyncStringWriter writer;
|
||||
bool _foundNgDirectives = false;
|
||||
bool _wroteImport = false;
|
||||
final ToSourceVisitor _copyVisitor;
|
||||
@ -42,12 +49,13 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
|
||||
/// The assetId for the file which we are parsing.
|
||||
final AssetId assetId;
|
||||
|
||||
CreateNgDepsVisitor(PrintWriter writer, this.assetId, this._annotationMatcher)
|
||||
CreateNgDepsVisitor(
|
||||
AsyncStringWriter writer, this.assetId, XHR xhr, this._annotationMatcher)
|
||||
: writer = writer,
|
||||
_copyVisitor = new ToSourceVisitor(writer),
|
||||
_factoryVisitor = new FactoryTransformVisitor(writer),
|
||||
_paramsVisitor = new ParameterTransformVisitor(writer),
|
||||
_metaVisitor = new AnnotationsTransformVisitor(writer);
|
||||
_metaVisitor = new AnnotationsTransformVisitor(writer, xhr);
|
||||
|
||||
void _visitNodeListWithSeparator(NodeList<AstNode> list, String separator) {
|
||||
if (list == null) return;
|
||||
|
@ -2,6 +2,7 @@ library angular2.transform.directive_processor.transformer;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||
import 'package:angular2/src/transform/common/logging.dart' as log;
|
||||
import 'package:angular2/src/transform/common/names.dart';
|
||||
import 'package:angular2/src/transform/common/options.dart';
|
||||
@ -32,9 +33,9 @@ class DirectiveProcessor extends Transformer {
|
||||
|
||||
try {
|
||||
var asset = transform.primaryInput;
|
||||
var assetCode = await asset.readAsString();
|
||||
var reader = new AssetReader.fromTransform(transform);
|
||||
var ngDepsSrc =
|
||||
createNgDeps(assetCode, asset.id, options.annotationMatcher);
|
||||
await createNgDeps(reader, asset.id, options.annotationMatcher);
|
||||
if (ngDepsSrc != null && ngDepsSrc.isNotEmpty) {
|
||||
var ngDepsAssetId =
|
||||
transform.primaryInput.id.changeExtension(DEPS_EXTENSION);
|
||||
|
@ -2,6 +2,8 @@ library angular2.transform.directive_processor.visitors;
|
||||
|
||||
import 'package:analyzer/analyzer.dart';
|
||||
import 'package:analyzer/src/generated/java_core.dart';
|
||||
import 'package:angular2/src/services/xhr.dart' show XHR;
|
||||
import 'package:angular2/src/transform/common/async_string_writer.dart';
|
||||
import 'package:angular2/src/transform/common/logging.dart';
|
||||
|
||||
/// `ToSourceVisitor` designed to accept {@link ConstructorDeclaration} nodes.
|
||||
@ -200,11 +202,17 @@ class FactoryTransformVisitor extends _CtorTransformVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(kegluenq): Use pull #1772 to detect when available.
|
||||
bool _isViewAnnotation(Annotation node) => '${node.name}' == 'View';
|
||||
|
||||
/// ToSourceVisitor designed to print a `ClassDeclaration` node as a
|
||||
/// 'annotations' value for Angular2's `registerType` calls.
|
||||
class AnnotationsTransformVisitor extends ToSourceVisitor {
|
||||
final PrintWriter writer;
|
||||
AnnotationsTransformVisitor(PrintWriter writer)
|
||||
final AsyncStringWriter writer;
|
||||
final XHR _xhr;
|
||||
bool _processingView = false;
|
||||
|
||||
AnnotationsTransformVisitor(AsyncStringWriter writer, this._xhr)
|
||||
: this.writer = writer,
|
||||
super(writer);
|
||||
|
||||
@ -226,6 +234,7 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
|
||||
Object visitAnnotation(Annotation node) {
|
||||
writer.print('const ');
|
||||
if (node.name != null) {
|
||||
_processingView = _isViewAnnotation(node);
|
||||
node.name.accept(this);
|
||||
}
|
||||
if (node.constructorName != null) {
|
||||
@ -237,4 +246,25 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// These correspond to the annotation parameters.
|
||||
@override
|
||||
Object visitNamedExpression(NamedExpression node) {
|
||||
// TODO(kegluneq): Remove this limitation.
|
||||
if (!_processingView ||
|
||||
node.name is! Label ||
|
||||
node.name.label is! SimpleIdentifier) {
|
||||
return super.visitNamedExpression(node);
|
||||
}
|
||||
var keyString = '${node.name.label}';
|
||||
if (keyString == 'templateUrl' && node.expression is SimpleStringLiteral) {
|
||||
var url = stringLiteralToString(node.expression);
|
||||
writer.print("template: r'''");
|
||||
writer.asyncPrint(_xhr.get(url));
|
||||
writer.print("'''");
|
||||
return null;
|
||||
} else {
|
||||
return super.visitNamedExpression(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user