I’m working on injecting some HTML content into a website I had built for me. During testing on a throttled network connection (e.g. Slow 4G or 3G) via the DevTools I’ve found that the following error comes up on occasion. The website in question as I understand it, was built using Nuxt and Vue JS.
I assume this is related to a check that’s happening on elements within the page but I cannot determine how to get around the issue. I am fairly sure it’s due to the timing of the checks being run and my content being inserted into the page.
At the moment I am adding the content in as soon as the page is available, so any recommendations on how to delay this or other solutions to this error would be appreciated.
Also, any advice on why this error may be occurring in the first place would be appreciated!
I also think this is the case. The script is not loaded before executed? Maybe slow connection needs more focus on ensure that the javascript is loading first?
You can wait for the element to be fully available using requestAnimationFrame. E.g.:
function poll() {
const element = document.querySelector("#element");
if (!element) {
window.requestAnimationFrame(poll);
} else {
// Insert your content here
}
}
This is explained in more detail here:
If this is a traditional SPA then this may not work as intended. The server will send a bunch of JavaScript to the client and the client will assemble the application’s HTML from this JavaScript and insert it into the body of the page. Timing issues can occur because the application’s JavaScript may take additional time to render components into the DOM after the document parsing is complete.
This may be the cause. If javascript is present in a sub page (SPA) it does not load the javascript at all (using innerHTML). The javascript must be loaded to the main page at startup.
On the other side “traditional” web sites does not use SPA (injecting html into the main page). So in this case it should work as usual IMO.
Yes that’s correct, it is an SPA - I should have clarified that from the beginning.
I’ve tried to implement the “requestAnimationFrame” method but the element is actually available before this can be run, thus causing the “else” case to fire and therefore causing the “appendChild” error to throw again.
function poll() {
const element = document.querySelector("#app-header");
if (!element) {
console.log("Element not found, requestAnimationFrame...");
window.requestAnimationFrame(poll);
} else {
// Insert your content here
console.log("Element available, add banner");
registerStartTrigger();
}
}
poll();
So the element you are targeting is available in the DOM, but your code to inject the content is causing the appendChild error you posted in post#1. Did I get that right?
Yes that’s correct.
I’ve been able to get around the error by injecting both the HTML and CSS via the JavaScript instead, using a createElement method and then insertAdjacentHTML method for the newly created element.
I then take the created elements and run appendChild on the target parent element to add them into the site.
I’m unsure as to the cause of the error, other than some background checks happening with the target parent element I’m trying to run the insertAdjacentHTML on.
I take it there’s no easy way for me to debug from my side? I found that when I click through to the file the site is erroring on via the Developer Tools, it’s a minified JS file with little to no reference of the variables or the actual error that’s occurring.
app-header is a div element which uses that ID. However, I assume that the actual error is occuring due to some checks running on the node which I can’t access information for? If you have any thoughts on how I could debug from my side that would be really appreciated!
Well a div definitely does support appendChild. The error message seems to indicate whatever the code picked up is not an Element node.
Note that the code found SOMETHING, because it’s not trying to invoke appendChild on undefined. It found a Node, but not one that supports appendChild.
Your code is 10 levels deep in its stack at that point, so tracking it is going to be exceedingly difficult, but from the few functions with proper names, it looks like a class is trying to update itself and failing. I’m not sure the problem is in your code, but may be in your environment, where things in the background are executing. Nothing code-wise that you’ve shown us would immediately strike to mind as diving that deep into a call stack.
Hard to say without seeing more of your code. You could check if the site includes source maps (.map files) which allow you to view the original, unminified code in Developer Tools. Or use the Pretty Print option (a {} icon in DevTools) to format the minified code for better readability. YMMV.
Also, if you’re injecting content directly into the DOM in a Vue/Nuxt app, it could be causing conflicts with the Vue runtime, which expects to control its DOM tree entirely.
But like I said, hard to say much more without seeing a reproducible example.