perf(ivy): move attributes array into component def (#32798)
Currently Ivy stores the element attributes into an array above the component def and passes it into the relevant instructions, however the problem is that upon minification the array will get a unique name which won't compress very well. These changes move the attributes array into the component def and pass in the index into the instructions instead. Before: ``` const _c0 = ['foo', 'bar']; SomeComp.ngComponentDef = defineComponent({ template: function() { element(0, 'div', _c0); } }); ``` After: ``` SomeComp.ngComponentDef = defineComponent({ consts: [['foo', 'bar']], template: function() { element(0, 'div', 0); } }); ``` A couple of cases that this PR doesn't handle: * Template references are still in a separate array. * i18n attributes are still in a separate array. PR Close #32798
This commit is contained in:

committed by
Alex Rickabaugh

parent
b2b917d2d8
commit
d5b87d32b0
@ -240,12 +240,18 @@ export function compileComponentFromMetadata(
|
||||
definitionMap.set('ngContentSelectors', ngContentSelectors);
|
||||
}
|
||||
|
||||
// e.g. `consts: 2`
|
||||
definitionMap.set('consts', o.literal(templateBuilder.getConstCount()));
|
||||
// e.g. `decls: 2`
|
||||
definitionMap.set('decls', o.literal(templateBuilder.getConstCount()));
|
||||
|
||||
// e.g. `vars: 2`
|
||||
definitionMap.set('vars', o.literal(templateBuilder.getVarCount()));
|
||||
|
||||
// e.g. `consts: [['one', 'two'], ['three', 'four']]
|
||||
const consts = templateBuilder.getConsts();
|
||||
if (consts.length > 0) {
|
||||
definitionMap.set('consts', o.literalArr(consts));
|
||||
}
|
||||
|
||||
definitionMap.set('template', templateFunctionExpression);
|
||||
|
||||
// e.g. `directives: [MyDirective]`
|
||||
|
@ -165,8 +165,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
private templateIndex: number|null, private templateName: string|null,
|
||||
private directiveMatcher: SelectorMatcher|null, private directives: Set<o.Expression>,
|
||||
private pipeTypeByName: Map<string, o.Expression>, private pipes: Set<o.Expression>,
|
||||
private _namespace: o.ExternalReference, private relativeContextFilePath: string,
|
||||
private i18nUseExternalIds: boolean) {
|
||||
private _namespace: o.ExternalReference, relativeContextFilePath: string,
|
||||
private i18nUseExternalIds: boolean, private _constants: o.Expression[] = []) {
|
||||
this._bindingScope = parentBindingScope.nestedScope(level);
|
||||
|
||||
// Turn the relative context file path into an identifier by replacing non-alphanumeric
|
||||
@ -606,7 +606,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
// add attributes for directive and projection matching purposes
|
||||
attributes.push(...this.prepareNonRenderAttrs(
|
||||
allOtherInputs, element.outputs, stylingBuilder, [], i18nAttrs, ngProjectAsAttr));
|
||||
parameters.push(this.toAttrsParam(attributes));
|
||||
parameters.push(this.addConstants(attributes));
|
||||
|
||||
// local refs (ex.: <div #foo #bar="baz">)
|
||||
parameters.push(this.prepareRefsParameter(element.references));
|
||||
@ -869,7 +869,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
(a: t.TextAttribute) => { attrsExprs.push(asLiteral(a.name), asLiteral(a.value)); });
|
||||
attrsExprs.push(...this.prepareNonRenderAttrs(
|
||||
template.inputs, template.outputs, undefined, template.templateAttrs));
|
||||
parameters.push(this.toAttrsParam(attrsExprs));
|
||||
parameters.push(this.addConstants(attrsExprs));
|
||||
|
||||
// local refs (ex.: <ng-template #foo>)
|
||||
if (template.references && template.references.length) {
|
||||
@ -881,7 +881,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
const templateVisitor = new TemplateDefinitionBuilder(
|
||||
this.constantPool, this._bindingScope, this.level + 1, contextName, this.i18n,
|
||||
templateIndex, templateName, this.directiveMatcher, this.directives, this.pipeTypeByName,
|
||||
this.pipes, this._namespace, this.fileBasedI18nSuffix, this.i18nUseExternalIds);
|
||||
this.pipes, this._namespace, this.fileBasedI18nSuffix, this.i18nUseExternalIds,
|
||||
this._constants);
|
||||
|
||||
// Nested templates must not be visited until after their parent templates have completed
|
||||
// processing, so they are queued here until after the initial pass. Otherwise, we wouldn't
|
||||
@ -1020,6 +1021,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
|
||||
getVarCount() { return this._pureFunctionSlots; }
|
||||
|
||||
getConsts() { return this._constants; }
|
||||
|
||||
getNgContentSelectors(): o.Expression|null {
|
||||
return this._ngContentReservedSlots.length ?
|
||||
this.constantPool.getConstLiteral(asLiteral(this._ngContentReservedSlots), true) :
|
||||
@ -1291,10 +1294,21 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
return attrExprs;
|
||||
}
|
||||
|
||||
private toAttrsParam(attrsExprs: o.Expression[]): o.Expression {
|
||||
return attrsExprs.length > 0 ?
|
||||
this.constantPool.getConstLiteral(o.literalArr(attrsExprs), true) :
|
||||
o.TYPED_NULL_EXPR;
|
||||
private addConstants(constExprs: o.Expression[]): o.LiteralExpr {
|
||||
if (constExprs.length > 0) {
|
||||
const literal = o.literalArr(constExprs);
|
||||
|
||||
// Try to reuse a literal that's already in the array, if possible.
|
||||
for (let i = 0; i < this._constants.length; i++) {
|
||||
if (this._constants[i].isEquivalent(literal)) {
|
||||
return o.literal(i);
|
||||
}
|
||||
}
|
||||
|
||||
return o.literal(this._constants.push(literal) - 1);
|
||||
}
|
||||
|
||||
return o.TYPED_NULL_EXPR;
|
||||
}
|
||||
|
||||
private prepareRefsParameter(references: t.Reference[]): o.Expression {
|
||||
|
Reference in New Issue
Block a user