Inline JavaScript has been the bane of attempts to speed up my site. I’ve been fighting with the jQuery JavaScript library for years. All advice on making your website faster talks about the importance of deferring JavaScript so that it doesn’t execute in the header and slow down your page rendering. But the problem with jQuery is that it is so ubiquitous that deferring it breaks all scripts that come before it. Normally this isn’t a problem because if you’re deferring jQuery, you’re probably deferring all the other JavaScript files as well – so they’ll still execute in order. But not inline JavaScript.
Inline JavaScript executes in the order in which it appears in the page. There’s no “deferring” it. As a result, if something in there relies on jQuery, it’ll simply throw an error to the console log and refuse to execute. This is problematic for even simple sites like mine where I use inline JS to do things like create a Table of Contents or copy some text automatically when the user clicks on it.
I thought there was no way around this, so I was resigned to loading jQuery in my header as a render-blocking script. My focus was on reducing its impact on the page load times by loading it from a public library. Earlier, I was happy with what seemed to be WordPress’s willingness to dump jQuery for time-sensitive functions like the lazy loading of images.
But the problem has always bugged me. If only there was a way to defer inline JavaScript, that would be amazing! Most of the time, there’s no urgent requirement for the inline JavaScript to run ASAP. My table of contents could wait until the jQuery was executed, no problem. And a few days ago, I found a solution!
Deferring Inline JavaScript with type=”module”
I found that there’s a way to defer inline JavaScript if we simply classify it as a “module” instead of the standard “text/javascript” that we all use. Apparently, there’s a standard where we can treat JavaScript as something called an ECMAScript Module. Truth be told, I have no idea what these are and what their intended purpose is. I tried reading up a bit, but I lack a lot of context to understand what’s going on.
I can confirm however, that if we have an inline script that says:
<script type="text/javascript">
// Some JavaScript
</script>
We simply need to change it to:
<script type="module">
// Some JavaScript
</script>
The only change here is from “text/javascript” to “module”. Do this, and the script will automatically behave as if it was an external JS file with the “defer” attribute!
Making Changes to Plugins
Unfortunately, most of the time in WordPress, all of the inline JavaScript comes through plugins. On my site WP-Tweaks, there were two plugins that outputted important functionality as inline JS. So, there was no option but to go into the plugin files, find the lines which output the inline JS and make the changes directly. Keep in mind that any changes you make will immediately be overridden the next time the plugin updates.
Still, the benefit of being able to do this and deferring jQuery is so large, that it might be worth it. Using this, I was able to reduce my First Contentful Paint (FCP) times by more than 50%! And all with no loss of functionality. That’s a benefit I can’t afford to miss out on. I’ve made a note on which plugin files I’ve changed and will repeat the changes whenever they update.
Bottom Line
I feel like I’ve finally won a battle with jQuery. I’ve lived with the fact of its existence in the header of my site for so long, and now I’ve found a way to safely defer it without breaking my site. It’s quite a good feeling!

I’m a NameHero team member, and an expert on WordPress and web hosting. I’ve been in this industry since 2008. I’ve also developed apps on Android and have written extensive tutorials on managing Linux servers. You can contact me on my website WP-Tweaks.com!
How much have you tested this? Work on all the major browsers?
I’ve been using it on my production website for a few months now. Chrome and Firefox are both fine…
Great find, I was also looking for a way to defer my inline scripts. Can I use says it’s 92% supported in September 2020.
https://caniuse.com/es6-module
Interesting breakdown of the different defer / async
https://gist.github.com/jakub-g/385ee6b41085303a53ad92c7c8afd7a6
This has a major limitation which is that you cannot call module functions from outside the module. You would always have to export each function and import it from outside the module.
Hello dear, thank you for sharing this great idea, but can’t we avoid all the hurdles of changing the text/js every time there is an update by using a plugin? What do you think about autoptimize defer inline javascript feature?