Is Inline JavaScript Bad?

Wondering whether to inline your JavaScript code or load it externally from a file? We help you decide.

Published Categorized as JavaScript, Web & Code

One of the big debates in the JavaScript development community is whether inlining JavaScript code, whether by embedding it in a <script> tag or adding it using onclick attributes of links and buttons, is “bad” or not.

I’ won’t try to settle the debate. Even if I did, I couldn’t. But as someone who’s been developing websites since 2007 and using JavaScript for some time, I’ll give you my opinion on the subject.

Both inlining JavaScript code in your HTML document and hosting your JavaScript code externally in a file on your server or a CDN have their advantages and disadvantages.

Neither is necessarily right or wrong, and the decision to use one or the other should be the subject of careful consideration and informed decision-making by you, the developer.

Inline JavaScript code is embedded in the HTML document itself, so the browser doesn’t need to make an additional HTTP request to fetch it. With that said, inline JavaScript code can neither be cached (unless the web page itself is cached), nor can it be reused across multiple web pages.

Externally hosted JavaScript code can be developed, maintained, and version-controlled separately from the HTML documents that load it. Such files can also be cached by web browsers, saving network bandwidth on repeated HTTP requests until the cache expires or a new version of the script is requested.

However, an extra HTTP request is an extra request. Without caching, these requests can pile up. Also, adding files and creating dependencies between them makes your implementation more complex—so there is a clear trade-off.

Inline vs. External JavaScript

Performance

Let’s assume that 25 kilobytes of JavaScript code must be inserted into every single one of your HTML documents, and that this code is the same on every page.

If you host it on your server or a CDN, the browser will make one HTTP request to pull it, and then cache it. When the user navigates to the next page, these 25 kb of JavaScript code will already be cached, so the browser will only need to load the HTML and CSS markup.

If you inline it into every HTML document, the browser will load it anew with every page viewed. It will cache it along with the page, and clear the cache if the page itself expires or changes.

Maintainability

By separating your JavaScript code from your HTML markup, you’re applying the concept of separation of concerns—a best practice for software development and a fundamental principle of solution architecture.

Separation of concerns, first described by Edsger Dijkstra in his 1974 paper On the Role of Scientific Thought, is a simple concept that can help you write superior code and build better applications.

By separating your application into distinct pieces, with each piece addressing a unique concern of its implementation, you’re making that application easier to evolve and less burdensome to maintain.

In the case of HTML markup and JavaScript code, you’re basically separating the presentation layer (the static elements in the UX contained in the HTML file) from the business logic layer (the events and functions that make the UX dynamic in the JavaScript file).

This allows you to version-control the JavaScript file, along with the code that’s stored in it, separately from the HTML document. It also lets you write clean, fragmented blocks of code that don’t mix presentation with business logic.

Reusability

As a developer, you want to write simple and compact code for the business logic you need to create to deliver on the requirements. And, once you’ve created that business logic, you want to be able to reuse it as many times as needed without having to write code for it again.

There are two reasons why inline JavaScript code isn’t as reusable as JavaScript code that’s separated in a file:

  • If you embed the code in a <script> tag, you can only use it within that HTML document.
  • If you inline it in the onclick attribute of interactive DOM elements, like links and buttons, you can only execute it when they fire.

These two drawbacks won’t cause much of a headache on a simple website with a few pages. But it will cause more and more pain as the website grows… that is, until it eventually becomes unsustainable and requires, always unexpectedly and urgently, large-scale and last-minute refactoring.

Reuse Limited to Document

If you embed your JavaScript code in a <script> element inside the <head> tag of your index.html document:

<html>
<head>
  <title>index.html - Home Page</title>
  <script>
    function say(what,where) {
      document.querySelector(where).innerHTML = what;
    }
  </script>
</head>
<body>
  <div class="wrapper"></div>
  <script>
    say('Hello world!','.wrapper');
  </script>
</body>
</html>

Then you won’t be able to use it in your about.html page.

And, if you keep to the pattern of embedding your JavaScript code inline, you’ll have to copy/paste it into your about.html page, and every other page that needs to use it.

Version control will become significantly harder because you’ll have to update your <script> across multiple documents whenever you release a new version of it.

Reuse Limited to Clicks on DOM Element

Suppose that, when the user clicks on a link—any link—on our page, we want to push a custom event to an array object called dataLayer.

The custom event can then be picked up by a tag management tool, like Google Tag Manager, and sent to an analytics tool, like Google Analytics for dashboarding.

It’s easier to build (and test, and evolve, and maintain) one function that lets you listen to clicks and push custom events to a data layer dynamically, and then reuse it as many times as you want:

// Define function
function pushToDataLayer(query,userAction,eventName) {
let element = document.querySelectorAll(query);
element.forEach(occurence => {
  occurence.addEventListener(userAction, function () {
    window.dataLayer = window.dataLayer || [];
    dataLayer.push({'event' : eventName});
  });
});
}

// Call function
pushToDataLayer('a','click','click-link');

Than it is to spread out the same logic for each and every link in your HTML document:

<html>
<head>
  <title>Loreum Ipsum - Dolor Sit Amet</title>
</head>
<body>
  <p><a href="https://en.wikipedia.org/wiki/Lorem_ipsum" target="_blank" onclick="window.dataLayer = window.dataLayer || [];dataLayer.push({'event':'click-link'})">Lorem Ipsum</a> is simply dummy text of the printing and typesetting industry.
  <p>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
  <p>It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.</p>
  <p>It was popularised in the 1960s with the release of <a href="https://en.wikipedia.org/wiki/Letraset" target="_blank" onclick="window.dataLayer = window.dataLayer || [];dataLayer.push({'event':'click-link'})">Letraset sheets</a> containing Lorem Ipsum passages, and more recently with desktop publishing software like <a href="https://en.wikipedia.org/wiki/Adobe_PageMaker" target="_blank" onclick="window.dataLayer = window.dataLayer || [];dataLayer.push({'event':'click-link'})">Aldus PageMaker</a> including versions of Lorem Ipsum.</p>
</body>
</html>

Just imagine how unnecessarily complicated delivering against a simple requirement as this would become if you were doing this for a 1,000-page website!

When to Use Each

Although you probably have many other factors to consider in deciding whether to store your JavaScript code inline or in a file, the general rule of thumb below can help you take the first steps toward such a decision.

When to Inline JavaScript

Inline your JavaScript code with the HTML markup of a page when the code and the business logic that it enables are unique to that page and/or can be version-controlled with it.

Still, try to avoid adding JavaScript code to individual DOM elements using onclick attributes. It is better to inline an event listener in the <head> or at the bottom of the <body> tag instead.

When to Put JavaScript in a File

Put your JavaScript code in a file and host it on your server or a CDN when the code and business logic it enables are shared between pages and/or must be version-controlled separately.

Image courtesy of Julia Stankevych /Depositphotos

Leave a comment

Your email address will not be published. Required fields are marked *