Skip to content

svg_element function is output even if no svg element in a component #6555

@tomoam

Description

@tomoam

Describe the problem

when hydratable: true, svg_element function is output even if no svg element in a component.

For example, if you have a simple component like the following:

<main> <h1>Hello world!</h1> </main>

compiled:

 function svg_element(name) { return document.createElementNS("http://www.w3.org/2000/svg", name); } ... function claim_element(nodes, name, attributes, svg) { return claim_node( nodes, (node) => node.nodeName === name, (node) => { const remove = []; for (let j = 0; j < node.attributes.length; j++) { const attribute = node.attributes[j]; if (!attributes[attribute.name]) { remove.push(attribute.name); } } remove.forEach((v) => node.removeAttribute(v)); }, () => (svg ? svg_element(name) : element(name)) ); }

minified(formatted):

 function m(t, n, e, o) { return _( t, (t) => t.nodeName === n, (t) => { const n = []; for (let o = 0; o < t.attributes.length; o++) { const r = t.attributes[o]; e[r.name] || n.push(r.name); } n.forEach((n) => t.removeAttribute(n)); }, () => o ? (function (t) { return document.createElementNS("http://www.w3.org/2000/svg", t); })(n) : s(n) ); } 

This isn't a bug (because it works fine), but it does increase the bundle size slightly.

Describe the proposed solution

Pass svg_element function, instead of 1.

  • src/compiler/compile/render_dom/wrappers/Element/index.ts
get_claim_statement(nodes: Identifier) {	const attributes = this.attributes	.filter((attr) => !(attr instanceof SpreadAttributeWrapper) && !attr.property_name)	.map((attr) => p`${(attr as StyleAttributeWrapper | AttributeWrapper).name}: true`);	const name = this.node.namespace	? this.node.name	: this.node.name.toUpperCase(); -const svg = this.node.namespace === namespaces.svg ? 1 : null; +const svg = this.node.namespace === namespaces.svg ? '@svg_element' : null;	return x`@claim_element(${nodes}, "${name}", { ${attributes} }, ${svg})`;	}
  • src/runtime/internal/dom.ts
-export function claim_element(nodes: ChildNodeArray, name: string, attributes: { [key: string]: boolean }, svg) { +export function claim_element(nodes: ChildNodeArray, name: string, attributes: { [key: string]: boolean }, create_element: (name: string) => Element | SVGElement = element) {	return claim_node<Element | SVGElement>(	nodes,	(node: ChildNode): node is Element | SVGElement => node.nodeName === name,	(node: Element) => {	const remove = [];	for (let j = 0; j < node.attributes.length; j++) {	const attribute = node.attributes[j];	if (!attributes[attribute.name]) {	remove.push(attribute.name);	}	}	remove.forEach(v => node.removeAttribute(v));	return undefined;	}, -() => svg ? svg_element(name as keyof SVGElementTagNameMap) : element(name as keyof HTMLElementTagNameMap) +() => create_element(name)	);	}

Alternatives considered

Also, element function is output even if the component has only svg elements.
If it is important to improve that as well, more changes are needed.

Importance

nice to have

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions