Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use document.importNode for when img/iframe use loading="lazy" #349

Merged
merged 6 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/babel-plugin-jsx-dom-expressions/src/dom/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export function transformElement(path, info) {
wrapSVG = info.topLevel && tagName != "svg" && SVGElements.has(tagName),
voidTag = VoidElements.indexOf(tagName) > -1,
isCustomElement = tagName.indexOf("-") > -1 || !!path.get("openingElement").get("attributes").find(a => a.node.name?.name === "is"),
isImportNode = (tagName === 'img'||tagName === 'iframe') && path.get("openingElement").get("attributes").some(a => a.node.name?.name === "loading" && a.node.value?.value === "lazy"
),
results = {
template: `<${tagName}`,
declarations: [],
Expand All @@ -70,6 +72,7 @@ export function transformElement(path, info) {
postExprs: [],
isSVG: wrapSVG,
hasCustomElement: isCustomElement,
isImportNode,
tagName,
renderer: "dom",
skipTemplate: false
Expand Down Expand Up @@ -830,6 +833,8 @@ function transformChildren(path, results, config) {
}

results.template += child.template;
results.isImportNode = results.isImportNode || child.isImportNode;

if (child.id) {
if (child.tagName === "head") {
if (config.hydratable) {
Expand Down Expand Up @@ -878,6 +883,7 @@ function transformChildren(path, results, config) {
childPostExprs.push(...child.postExprs);
results.hasHydratableEvent = results.hasHydratableEvent || child.hasHydratableEvent;
results.hasCustomElement = results.hasCustomElement || child.hasCustomElement;
results.isImportNode = results.isImportNode || child.isImportNode;
tempPath = child.id.name;
nextPlaceholder = null;
i++;
Expand Down
8 changes: 6 additions & 2 deletions packages/babel-plugin-jsx-dom-expressions/src/dom/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ export function appendTemplates(path, templates) {
cooked: template.template,
raw: escapeStringForTemplate(template.template)
};

const shouldUseImportNode = template.isCE || template.isImportNode

return t.variableDeclarator(
template.id,
t.addComment(
t.callExpression(
registerImportMethod(path, "template", getRendererConfig(path, "dom").moduleName),
[t.templateLiteral([t.templateElement(tmpl, true)], [])].concat(
template.isSVG || template.isCE
? [t.booleanLiteral(template.isCE), t.booleanLiteral(template.isSVG)]
template.isSVG || shouldUseImportNode
? [t.booleanLiteral(!!shouldUseImportNode), t.booleanLiteral(template.isSVG)]
: []
)
),
Expand Down Expand Up @@ -77,6 +80,7 @@ function registerTemplate(path, results) {
template: results.template,
isSVG: results.isSVG,
isCE: results.hasCustomElement,
isImportNode: results.isImportNode,
renderer: "dom"
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const JSXValidator = {
JSXElement(path) {
const elName = path.node.openingElement.name;
const parent = path.parent;

if (!t.isJSXElement(parent) || !t.isJSXIdentifier(elName)) return;
const elTagName = elName.name;
if (isComponent(elTagName)) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,16 @@ const template41 = (
<option value={Color.Blue}>Blue</option>
</select>
);

const template42 = <img src="" />;
const template43 = <div><img src=""/></div>;

const template44 = <img src="" loading="lazy"/>;
const template45 = <div><img src="" loading="lazy"/></div>;

const template46 = <iframe src=""></iframe>;
const template47 = <div><iframe src=""></iframe></div>;

const template48 = <iframe src="" loading="lazy"></iframe>;
const template49 = <div><iframe src="" loading="lazy"></iframe></div>;

Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ var _tmpl$ = /*#__PURE__*/ _$template(`<div id=main><h1 class=base id=my-h1><a h
),
_tmpl$18 = /*#__PURE__*/ _$template(`<button>`),
_tmpl$19 = /*#__PURE__*/ _$template(`<input value=10>`),
_tmpl$20 = /*#__PURE__*/ _$template(`<select><option>Red</option><option>Blue`);
_tmpl$20 = /*#__PURE__*/ _$template(`<select><option>Red</option><option>Blue`),
_tmpl$21 = /*#__PURE__*/ _$template(`<img src="">`),
_tmpl$22 = /*#__PURE__*/ _$template(`<div><img src="">`),
_tmpl$23 = /*#__PURE__*/ _$template(`<img src=""loading=lazy>`, true, false),
_tmpl$24 = /*#__PURE__*/ _$template(`<div><img src=""loading=lazy>`, true, false),
_tmpl$25 = /*#__PURE__*/ _$template(`<iframe src="">`),
_tmpl$26 = /*#__PURE__*/ _$template(`<div><iframe src="">`),
_tmpl$27 = /*#__PURE__*/ _$template(`<iframe src=""loading=lazy>`, true, false),
_tmpl$28 = /*#__PURE__*/ _$template(`<div><iframe src=""loading=lazy>`, true, false);
import * as styles from "./styles.module.css";
const selected = true;
let id = "my-h1";
Expand Down Expand Up @@ -426,4 +434,12 @@ const template41 = (() => {
_$effect(() => (_el$57.value = state.color));
return _el$57;
})();
const template42 = _tmpl$21();
const template43 = _tmpl$22();
const template44 = _tmpl$23();
const template45 = _tmpl$24();
const template46 = _tmpl$25();
const template47 = _tmpl$26();
const template48 = _tmpl$27();
const template49 = _tmpl$28();
_$delegateEvents(["click", "input"]);
4 changes: 2 additions & 2 deletions packages/dom-expressions/src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function render(code, element, init, options = {}) {
};
}

export function template(html, isCE, isSVG) {
export function template(html, isImportNode, isSVG) {
let node;
const create = () => {
if ("_DX_DEV_" && isHydrating())
Expand All @@ -76,7 +76,7 @@ export function template(html, isCE, isSVG) {
return isSVG ? t.content.firstChild.firstChild : t.content.firstChild;
};
// backwards compatible with older builds
const fn = isCE
const fn = isImportNode
? () => untrack(() => document.importNode(node || (node = create()), true))
: () => (node || (node = create())).cloneNode(true);
fn.cloneNode = fn;
Expand Down
6 changes: 5 additions & 1 deletion packages/lit-dom-expressions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type Options = {
templateNodes: IDom[][],
wrap?: boolean,
hasCustomElement?: boolean,
isImportNode?: boolean,
parent?: boolean,
fragment?: boolean,
}
Expand Down Expand Up @@ -293,6 +294,7 @@ export function createHTML(r: Runtime, { delegateEvents = true, functionBuilder
options.counter = childOptions.counter;
options.templateId = childOptions.templateId;
options.hasCustomElement = options.hasCustomElement || childOptions.hasCustomElement;
options.isImportNode = options.isImportNode || childOptions.isImportNode;
}

function processComponentProps(propGroups: (string | string[])[]) {
Expand Down Expand Up @@ -432,6 +434,8 @@ export function createHTML(r: Runtime, { delegateEvents = true, functionBuilder
const isSVG = r.SVGElements.has(node.name);
const isCE = node.name.includes("-");
options.hasCustomElement = isCE;
options.isImportNode = (node.name === 'img'||node.name === 'iframe') && node.attrs.some((e) => e.name === "loading" && e.value ==='lazy');

if (node.attrs.some(e => e.name === "###")) {
const spreadArgs = [];
let current = "";
Expand Down Expand Up @@ -488,7 +492,7 @@ export function createHTML(r: Runtime, { delegateEvents = true, functionBuilder
options.first = false;
processChildren(node, options);
if (topDecl) {
options.decl[0] = options.hasCustomElement
options.decl[0] = options.hasCustomElement || options.isImportNode
? `const ${tag} = r.untrack(() => document.importNode(tmpls[${templateId}].content.firstChild, true))`
: `const ${tag} = tmpls[${templateId}].content.firstChild.cloneNode(true)`;
}
Expand Down
Loading