Skip to content

🚀 amp-bind: Use querySelectorAll to quickly find all bound elements#32851

Merged
jridgewell merged 16 commits intomasterfrom
amp-bind-queryselectorall
Mar 15, 2021
Merged

🚀 amp-bind: Use querySelectorAll to quickly find all bound elements#32851
jridgewell merged 16 commits intomasterfrom
amp-bind-queryselectorall

Conversation

@jridgewell
Copy link
Copy Markdown
Contributor

This detects if amp-bind is SSRd to insert i-amphtml-binding attributes on any elements which have bindings. If so, we'll do a simple querySelectorAll instead of a TreeWalker walk.

Part of #27590

@jridgewell jridgewell requested a review from samouri February 24, 2021 01:28
? toArray(root.querySelectorAll('[i-amphtml-binding]'))
: [];

// Confusingly, the old TreeWalker hit the root node. We need to match that behavior.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did it have any effect? I.e. is it harmful if we start skipping?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No tests fail, but I don't know if we just never tested this case.

@samouri
Copy link
Copy Markdown
Member

samouri commented Feb 25, 2021

This solution is very smart! Replacing the TreeWalker with a BindWalker, presenting a similar interface so it fits right in.

Have you thought about creating an entirely separate (and much simpler) flow for addBindingsForNodes_ that skips all the chunking (but retains quota). Most of the logic in that flow seems necessary when using querySelectorAll.

Galaxy brain idea: can you simply call fastScan_?

Copy link
Copy Markdown
Contributor Author

@jridgewell jridgewell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you thought about creating an entirely separate (and much simpler) flow for addBindingsForNodes_ that skips all the chunking (but retains quota). Most of the logic in that flow seems necessary when using querySelectorAll.

There are already two paths with slowScan and fastScan, adding a new path made my head hurt. Retrofitting the slow path to actually be very fast was the easiest approach.

Galaxy brain idea: can you simply call fastScan_?

I couldn't get it to work, and didn't want to dedicate the whole week to this PR.

? toArray(root.querySelectorAll('[i-amphtml-binding]'))
: [];

// Confusingly, the old TreeWalker hit the root node. We need to match that behavior.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No tests fail, but I don't know if we just never tested this case.

sebastianbenz added a commit to ampproject/amp-toolbox that referenced this pull request Feb 26, 2021
* Add amp-bind optimizer

See ampproject/amphtml#32851

* Apply suggestions from code review

Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com>

* Add tests

Co-authored-by: Sebastian Benz <sebastian.benz@gmail.com>
@samouri
Copy link
Copy Markdown
Member

samouri commented Mar 4, 2021

LMK what you think about an approach more similar to this: #33057

Co-Authored-By: Jake Fried <samouri@users.noreply.github.com>
@jridgewell
Copy link
Copy Markdown
Contributor Author

Done.

@jridgewell
Copy link
Copy Markdown
Contributor Author

@samouri: Ok, after attempting for 2 more days to get the tests to pass, I reverted the "simple" approach and kept the BindWalker. If you want to take a stab at it, I'd ask that you do so after approving this PR.

Copy link
Copy Markdown
Member

@samouri samouri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was difficult about making fastScan_ work with tests? Was it related to quota logic or skipping amp-list children logic?

Please add a TODO before merging to switch to fastScan_ in the future

/* opt_tagName */ 'input'
{
tag: 'input',
insertQuerySelectorAttr: useQuerySelector,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From purely a practical standpoint, do you think it would be cleaner to make a module level optimized var consumed by the createElement helper to conditionally add the css class? It breaks DI, but cuts down on boilerplate in each test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants