Handle SPA navigations in reading time example. (#1496)

In the move to new infrastructure for https://developer.chrome.com/, the
site became an SPA which can soft navigate outside of browser
navigations. Therefore, we need to update the sample to watch for
changes to content after the content script is injected.
This commit is contained in:
Oliver Dunk
2025-06-23 08:34:53 +01:00
committed by GitHub
parent 8d6e02ae45
commit b55612ae64
2 changed files with 29 additions and 3 deletions

View File

@@ -6,6 +6,8 @@ This sample demonstrates how to run scripts on any Chrome extension and Chrome W
This sample demonstrates how developers can use content scripts which employ Document Object Models to read and change the content of a page. In this instance, the extension checks to find an article element, counts all the words inside of it, and then creates a paragraph that estimates the total reading time for that article.
As https://developer.chrome.com/ is a SPA (Single Page Application) it also includes an example of how to use `MutationObserver` to watch for changes to article content. Using `MutationObserver` can have a performance cost, so use them sparingly and only observe the most relevant changes.
## Running this extension
1. Clone this repository.

View File

@@ -12,10 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
const article = document.querySelector('article');
function renderReadingTime(article) {
// If we weren't provided an article, we don't need to render anything.
if (!article) {
return;
}
// `document.querySelector` may return null if the selector doesn't match anything.
if (article) {
const text = article.textContent;
/**
* Regular expression to find all "words" in a string.
@@ -45,3 +47,25 @@ if (article) {
// https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement
(date ?? heading).insertAdjacentElement('afterend', badge);
}
renderReadingTime(document.querySelector('article'));
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
// If a new article was added.
for (const node of mutation.addedNodes) {
if (node instanceof Element && node.tagName === 'ARTICLE') {
// Render the reading time for this particular article.
renderReadingTime(node);
}
}
}
});
// https://developer.chrome.com/ is a SPA (Single Page Application) so can
// update the address bar and render new content without reloading. Our content
// script won't be reinjected when this happens, so we need to watch for
// changes to the content.
observer.observe(document.querySelector('devsite-content'), {
childList: true
});