question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Defer breaks autoload (when loading page without having resources cached)

See original GitHub issue

Information:

  • Prism version: 1.17.1
  • Plugins: autoloader
  • Environment: Browser

Description When the page is loaded without the JS resources being cached and the scripts are marked with defer then the syntax highlighting is not applied.

Example Without defer (workking): https://jsfiddle.net/f5vj903e/
With defer (not working): https://jsfiddle.net/f5vj903e/1/

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:29 (15 by maintainers)

github_iconTop GitHub Comments

4reactions
RunDevelopmentcommented, Oct 24, 2019

Alright, I think I know what causes the race condition.

Since the readyState of the document is interactive, Prism Core uses requestAnimationFrame to highlight all code blocks. The problem with this is that this means that all plugins have to loaded and executed before the next frame. This is the reason why some plugins are sometimes active and sometimes not.

(You can verify that this is indeed what’s going on by setting a breakpoint in e.g prism-linenumbers.min.js and you’ll see that the breakpoint sometimes hits after all code blocks have been highlighted.)

This is a bit of an issue because we’ll have to wait for resources that might be loaded. Unfortunately, defer doesn’t work on inline scripts:

<script defer data-manual src="https://cdn.jsdelivr.net/npm/prismjs@1.17.1/prism.min.js" integrity="sha384-ccmyu9Bl8HZLIVEUqF+ZzcZTBPB8VgMI2lQpOsNDOvro/1SfRnz3qkub0eUxof1s" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/prismjs@1.17.1/plugins/autoloader/prism-autoloader.min.js" integrity="sha384-xF5Qt8AUh+k8ZzozF9d1iDRKeeP1m9PPJKKhy3R/O4+5JccihNLvy1fIuGnkye7+" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/prismjs@1.17.1/plugins/line-numbers/prism-line-numbers.min.js" integrity="sha384-g0u6zLvZF3g2I+/vETu7YYk74PXoDBNGy5qtL04/uW6PJGMDeax43A5hFa55xaAT" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/prismjs@1.17.1/plugins/toolbar/prism-toolbar.min.js" integrity="sha384-Q7kIVs9c3Zyij/OpKzuVFFpRTTXHL3qytFywO0AtJdmisfKKSEsnoc7pHfkxgXZX" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/prismjs@1.17.1/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js" integrity="sha384-V+ZXzru/5DpvSuLtIS2SctoAyvpigW+zF56aiGLPc+PvQxO3EkpeYDUw6t1Y6d9y" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/prismjs@1.17.1/plugins/show-language/prism-show-language.min.js" integrity="sha384-xnJRKz3VKJloaoR0FNJVmbJ55eTSeuztu0Okhd9vvz2hblDQc0UJWVkj3sIikslo" crossorigin="anonymous"></script>
<script defer>Prism.highlightAll();</script>
<!-- defer won't do anything -->

So, instead of using the requestAnimationFrame path, we should use the DOMContentLoaded path in Prism Core because deferred scripts are guaranteed to be executed before that event. And to figure out whether the current script is deferred or not, we need currentScript. (yay, full circle) I’m imagining something along the lines of the following as a fix.

	if (document.readyState !== 'loading' && !script.defer) {
		// requestAnimationFrame
	} else {
		document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);
	}

Have I verified that this fix works? No. Why not? Funny story. As it turns out: the moment you add an inline script everything works. No race condition, it just works. Srsly, try it. Just add <script>/* how? */</script> anywhere in the test page. (btw <script></script> doesn’t work. Seems like someone at Mozilla wanted to optimize) How’s that as a fix? Just add <script>/**/</script>.

3reactions
RunDevelopmentcommented, Oct 24, 2019

Ok, I just verified that the fix works. I’ll make a PR.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to load from browser cache after the resources are ...
The solution i think off is to callback a .reload() after all the files are cached in the browser so you don't keep...
Read more >
Lazy Loading Individual Vue Components and Prefetching
The purpose of lazy loading is to postpone downloading parts of your application that are not needed by the user on the initial...
Read more >
Load JavaScript deferred - WP Rocket Knowledge Base
What does Load JavaScript Deferred do? This option addresses the Eliminate Render Blocking Resources PageSpeed recommendation. It is preferable ...
Read more >
How To Fix a Slow WordPress Site + Pass Core Web Vitals
Fix your slow WordPress site and pass core web vitals with these 25 in-depth speed optimization tips.
Read more >
25 Ways to Speed Up a Slow Elementor Website (2022)
1. Activate Elementor Experiments (optimized DOM output, improved asset + CSS loading, and inline Font icons). This addresses several PageSpeed recommendations ... 2....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found